WFMath 0.3.11
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/axisbox.h>
00033 
00034 #include <wfmath/point.h>
00035 #include <wfmath/ball.h>
00036 
00037 namespace WFMath {
00038 
00039 template<const int dim>
00040 inline bool AxisBox<dim>::isEqualTo(const AxisBox<dim>& b, double epsilon) const
00041 {
00042   return Equal(m_low, b.m_low, epsilon)
00043        && Equal(m_high, b.m_high, epsilon);
00044 }
00045 
00046 template<const int dim>
00047 bool Intersection(const AxisBox<dim>& a1, const AxisBox<dim>& a2, AxisBox<dim>& out)
00048 {
00049   for(int i = 0; i < dim; ++i) {
00050     out.m_low[i] = FloatMax(a1.m_low[i], a2.m_low[i]);
00051     out.m_high[i] = FloatMin(a1.m_high[i], a2.m_high[i]);
00052     if(out.m_low[i] > out.m_high[i])
00053       return false;
00054   }
00055 
00056   out.m_low.setValid(a1.m_low.isValid() && a2.m_low.isValid());
00057   out.m_high.setValid(a1.m_high.isValid() && a2.m_high.isValid());
00058 
00059   return true;
00060 }
00061 
00062 template<const int dim>
00063 AxisBox<dim> Union(const AxisBox<dim>& a1, const AxisBox<dim>& a2)
00064 {
00065   AxisBox<dim> out;
00066 
00067   for(int i = 0; i < dim; ++i) {
00068     out.m_low[i] = FloatMin(a1.m_low[i], a2.m_low[i]);
00069     out.m_high[i] = FloatMax(a1.m_high[i], a2.m_high[i]);
00070   }
00071 
00072   out.m_low.setValid(a1.m_low.isValid() && a2.m_low.isValid());
00073   out.m_high.setValid(a1.m_high.isValid() && a2.m_high.isValid());
00074 
00075   return out;
00076 }
00077 
00078 template<const int dim>
00079 AxisBox<dim>& AxisBox<dim>::setCorners(const Point<dim>& p1, const Point<dim>& p2,
00080                                        bool ordered)
00081 {
00082   if(ordered) {
00083     m_low = p1;
00084     m_high = p2;
00085     return *this;
00086   }
00087 
00088   for(int i = 0; i < dim; ++i) {
00089     if(p1[i] > p2[i]) {
00090       m_low[i] = p2[i];
00091       m_high[i] = p1[i];
00092     }
00093     else {
00094       m_low[i] = p1[i];
00095       m_high[i] = p2[i];
00096     }
00097   }
00098 
00099   m_low.setValid();
00100   m_high.setValid();
00101 
00102   return *this;
00103 }
00104 
00105 template<const int dim>
00106 Point<dim> AxisBox<dim>::getCorner(int i) const
00107 {
00108   if(i < 1)
00109     return m_low;
00110   if(i >= (1 << dim) - 1)
00111     return m_high;
00112 
00113   Point<dim> out;
00114 
00115   for(int j = 0; j < dim; ++j)
00116     out[j] = (i & (1 << j)) ? m_high[j] : m_low[j];
00117 
00118   out.setValid(m_low.isValid() && m_high.isValid());
00119 
00120   return out;
00121 }
00122 
00123 template<const int dim>
00124 inline Ball<dim> AxisBox<dim>::boundingSphere() const
00125 {
00126   return Ball<dim>(getCenter(), Distance(m_low, m_high) / 2);
00127 }
00128 
00129 template<const int dim>
00130 inline Ball<dim> AxisBox<dim>::boundingSphereSloppy() const
00131 {
00132   return Ball<dim>(getCenter(), SloppyDistance(m_low, m_high) / 2);
00133 }
00134 
00135 
00136 #ifndef WFMATH_NO_TEMPLATES_AS_TEMPLATE_PARAMETERS
00137 template<const int dim, template<class, class> class container>
00138 AxisBox<dim> BoundingBox(const container<AxisBox<dim>, std::allocator<AxisBox<dim> > >& c)
00139 {
00140   // FIXME become friend
00141 
00142   typename container<AxisBox<dim>, std::allocator<AxisBox<dim> > >::const_iterator i = c.begin(), end = c.end();
00143 
00144   if(i == end) {
00145     return AxisBox<dim>();
00146   }
00147 
00148   Point<dim> low = i->lowCorner(), high = i->highCorner();
00149   bool low_valid = low.isValid(), high_valid = high.isValid();
00150 
00151   while(++i != end) {
00152     const Point<dim> &new_low = i->lowCorner(), &new_high = i->highCorner();
00153     low_valid = low_valid && new_low.isValid();
00154     high_valid = high_valid && new_high.isValid();
00155     for(int j = 0; j < dim; ++j) {
00156       low[j] = FloatMin(low[j], new_low[j]);
00157       high[j] = FloatMax(high[j], new_high[j]);
00158     }
00159   }
00160 
00161   low.setValid(low_valid);
00162   high.setValid(high_valid);
00163 
00164   return AxisBox<dim>(low, high, true);
00165 }
00166 
00167 template<const int dim, template<class, class> class container>
00168 AxisBox<dim> BoundingBox(const container<Point<dim>, std::allocator<Point<dim> > >& c)
00169 {
00170   typename container<Point<dim>, std::allocator<Point<dim> > >::const_iterator i = c.begin(), end = c.end();
00171 
00172   if(i == end) {
00173     return AxisBox<dim>();
00174   }
00175 
00176   Point<dim> low = *i, high = *i;
00177   bool valid = i->isValid();
00178 
00179   while(++i != end) {
00180     valid = valid && i->isValid();
00181     for(int j = 0; j < dim; ++j) {
00182       low[j] = FloatMin(low[j], (*i)[j]);
00183       high[j] = FloatMax(high[j], (*i)[j]);
00184     }
00185   }
00186 
00187   low.setValid(valid);
00188   high.setValid(valid);
00189 
00190   return AxisBox<dim>(low, high, true);
00191 }
00192 #endif
00193 
00194 // This is here, instead of defined in the class, to
00195 // avoid include order problems
00196 
00197 template<const int dim>
00198 inline AxisBox<dim> Point<dim>::boundingBox() const
00199 {
00200   return AxisBox<dim>(*this, *this, true);
00201 }
00202 
00203 template<const int dim>
00204 Point<dim> Point<dim>::toParentCoords(const AxisBox<dim>& coords) const
00205 {
00206   return coords.lowCorner() + (*this - Point().setToOrigin());
00207 }
00208 
00209 template<const int dim>
00210 Point<dim> Point<dim>::toLocalCoords(const AxisBox<dim>& coords) const
00211 {
00212   return Point().setToOrigin() + (*this - coords.lowCorner());
00213 }
00214 
00215 } // namespace WFMath
00216 
00217 #endif  // WFMATH_AXIS_BOX_FUNCS_H