axisbox_funcs.h

00001 // axisbox_funcs.h (Axis-aligned box implementation)
00002 //
00003 //  The WorldForge Project
00004 //  Copyright (C) 2000, 2001  The WorldForge Project
00005 //
00006 //  This program is free software; you can redistribute it and/or modify
00007 //  it under the terms of the GNU General Public License as published by
00008 //  the Free Software Foundation; either version 2 of the License, or
00009 //  (at your option) any later version.
00010 //
00011 //  This program is distributed in the hope that it will be useful,
00012 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //  GNU General Public License for more details.
00015 //
00016 //  You should have received a copy of the GNU General Public License
00017 //  along with this program; if not, write to the Free Software
00018 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 //
00020 //  For information about WorldForge and its authors, please contact
00021 //  the Worldforge Web Site at http://www.worldforge.org.
00022 //
00023 
00024 // Author: Ron Steinke
00025 
00026 // The implementation of this class is based on the geometric
00027 // parts of the Tree and Placement classes from stage/shepherd/sylvanus
00028 
00029 #ifndef WFMATH_AXIS_BOX_FUNCS_H
00030 #define WFMATH_AXIS_BOX_FUNCS_H
00031 
00032 #include <wfmath/const.h>
00033 #include <wfmath/vector.h>
00034 #include <wfmath/point.h>
00035 #include <wfmath/axisbox.h>
00036 #include <wfmath/ball.h>
00037 
00038 namespace WFMath {
00039 
00040 template<const int dim>
00041 inline bool AxisBox<dim>::isEqualTo(const AxisBox<dim>& b, double epsilon) const
00042 {
00043   return Equal(m_low, b.m_low, epsilon)
00044        && Equal(m_high, b.m_high, epsilon);
00045 }
00046 
00047 template<const int dim>
00048 bool Intersection(const AxisBox<dim>& a1, const AxisBox<dim>& a2, AxisBox<dim>& out)
00049 {
00050   for(int i = 0; i < dim; ++i) {
00051     out.m_low[i] = FloatMax(a1.m_low[i], a2.m_low[i]);
00052     out.m_high[i] = FloatMin(a1.m_high[i], a2.m_high[i]);
00053     if(out.m_low[i] > out.m_high[i])
00054       return false;
00055   }
00056 
00057   out.m_low.setValid(a1.m_low.isValid() && a2.m_low.isValid());
00058   out.m_high.setValid(a1.m_high.isValid() && a2.m_high.isValid());
00059 
00060   return true;
00061 }
00062 
00063 template<const int dim>
00064 AxisBox<dim> Union(const AxisBox<dim>& a1, const AxisBox<dim>& a2)
00065 {
00066   AxisBox<dim> out;
00067 
00068   for(int i = 0; i < dim; ++i) {
00069     out.m_low[i] = FloatMin(a1.m_low[i], a2.m_low[i]);
00070     out.m_high[i] = FloatMax(a1.m_high[i], a2.m_high[i]);
00071   }
00072 
00073   out.m_low.setValid(a1.m_low.isValid() && a2.m_low.isValid());
00074   out.m_high.setValid(a1.m_high.isValid() && a2.m_high.isValid());
00075 
00076   return out;
00077 }
00078 
00079 template<const int dim>
00080 AxisBox<dim>& AxisBox<dim>::setCorners(const Point<dim>& p1, const Point<dim>& p2,
00081                                        bool ordered)
00082 {
00083   if(ordered) {
00084     m_low = p1;
00085     m_high = p2;
00086     return *this;
00087   }
00088 
00089   for(int i = 0; i < dim; ++i) {
00090     if(p1[i] > p2[i]) {
00091       m_low[i] = p2[i];
00092       m_high[i] = p1[i];
00093     }
00094     else {
00095       m_low[i] = p1[i];
00096       m_high[i] = p2[i];
00097     }
00098   }
00099 
00100   m_low.setValid();
00101   m_high.setValid();
00102 
00103   return *this;
00104 }
00105 
00106 template<const int dim>
00107 Point<dim> AxisBox<dim>::getCorner(int i) const
00108 {
00109   assert(i >= 0 && i < (1 << dim));
00110 
00111   if(i == 0)
00112     return m_low;
00113   if(i == (1 << dim) - 1)
00114     return m_high;
00115 
00116   Point<dim> out;
00117 
00118   for(int j = 0; j < dim; ++j)
00119     out[j] = (i & (1 << j)) ? m_high[j] : m_low[j];
00120 
00121   out.setValid(m_low.isValid() && m_high.isValid());
00122 
00123   return out;
00124 }
00125 
00126 template<const int dim>
00127 inline Ball<dim> AxisBox<dim>::boundingSphere() const
00128 {
00129   return Ball<dim>(getCenter(), Distance(m_low, m_high) / 2);
00130 }
00131 
00132 template<const int dim>
00133 inline Ball<dim> AxisBox<dim>::boundingSphereSloppy() const
00134 {
00135   return Ball<dim>(getCenter(), SloppyDistance(m_low, m_high) / 2);
00136 }
00137 
00138 
00139 #ifndef WFMATH_NO_TEMPLATES_AS_TEMPLATE_PARAMETERS
00140 template<const int dim, template<class, class> class container>
00141 AxisBox<dim> BoundingBox(const container<AxisBox<dim>, std::allocator<AxisBox<dim> > >& c)
00142 {
00143   // FIXME become friend
00144 
00145   typename container<AxisBox<dim>, std::allocator<AxisBox<dim> > >::const_iterator i = c.begin(), end = c.end();
00146 
00147   assert(i != end);
00148 
00149   Point<dim> low = i->lowCorner(), high = i->highCorner();
00150   bool low_valid = low.isValid(), high_valid = high.isValid();
00151 
00152   while(++i != end) {
00153     const Point<dim> &new_low = i->lowCorner(), &new_high = i->highCorner();
00154     low_valid = low_valid && new_low.isValid();
00155     high_valid = high_valid && new_high.isValid();
00156     for(int j = 0; j < dim; ++j) {
00157       low[j] = FloatMin(low[j], new_low[j]);
00158       high[j] = FloatMax(high[j], new_high[j]);
00159     }
00160   }
00161 
00162   low.setValid(low_valid);
00163   high.setValid(high_valid);
00164 
00165   return AxisBox<dim>(low, high, true);
00166 }
00167 
00168 template<const int dim, template<class, class> class container>
00169 AxisBox<dim> BoundingBox(const container<Point<dim>, std::allocator<Point<dim> > >& c)
00170 {
00171   typename container<Point<dim>, std::allocator<Point<dim> > >::const_iterator i = c.begin(), end = c.end();
00172 
00173   assert(i != end);
00174 
00175   Point<dim> low = *i, high = *i;
00176   bool valid = i->isValid();
00177 
00178   while(++i != end) {
00179     valid = valid && i->isValid();
00180     for(int j = 0; j < dim; ++j) {
00181       low[j] = FloatMin(low[j], (*i)[j]);
00182       high[j] = FloatMax(high[j], (*i)[j]);
00183     }
00184   }
00185 
00186   low.setValid(valid);
00187   high.setValid(valid);
00188 
00189   return AxisBox<dim>(low, high, true);
00190 }
00191 #endif
00192 
00193 // This is here, instead of defined in the class, to
00194 // avoid include order problems
00195 
00196 template<const int dim>
00197 inline AxisBox<dim> Point<dim>::boundingBox() const
00198 {
00199   return AxisBox<dim>(*this, *this, true);
00200 }
00201 
00202 template<const int dim>
00203 Point<dim> Point<dim>::toParentCoords(const AxisBox<dim>& coords) const
00204 {
00205   return coords.lowCorner() + (*this - Point().setToOrigin());
00206 }
00207 
00208 template<const int dim>
00209 Point<dim> Point<dim>::toLocalCoords(const AxisBox<dim>& coords) const
00210 {
00211   return Point().setToOrigin() + (*this - coords.lowCorner());
00212 }
00213 
00214 } // namespace WFMath
00215 
00216 #endif  // WFMATH_AXIS_BOX_FUNCS_H

Generated on Sun Dec 9 22:25:31 2007 for WFMath by  doxygen 1.5.4