WFMath  0.3.12
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<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<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<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<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<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<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<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 template<int dim, template<class, class> class container>
00137 AxisBox<dim> BoundingBox(const container<AxisBox<dim>, std::allocator<AxisBox<dim> > >& c)
00138 {
00139   // FIXME become friend
00140 
00141   typename container<AxisBox<dim>, std::allocator<AxisBox<dim> > >::const_iterator i = c.begin(), end = c.end();
00142 
00143   if(i == end) {
00144     return AxisBox<dim>();
00145   }
00146 
00147   Point<dim> low = i->lowCorner(), high = i->highCorner();
00148   bool low_valid = low.isValid(), high_valid = high.isValid();
00149 
00150   while(++i != end) {
00151     const Point<dim> &new_low = i->lowCorner(), &new_high = i->highCorner();
00152     low_valid = low_valid && new_low.isValid();
00153     high_valid = high_valid && new_high.isValid();
00154     for(int j = 0; j < dim; ++j) {
00155       low[j] = FloatMin(low[j], new_low[j]);
00156       high[j] = FloatMax(high[j], new_high[j]);
00157     }
00158   }
00159 
00160   low.setValid(low_valid);
00161   high.setValid(high_valid);
00162 
00163   return AxisBox<dim>(low, high, true);
00164 }
00165 
00166 template<int dim, template<class, class> class container>
00167 AxisBox<dim> BoundingBox(const container<Point<dim>, std::allocator<Point<dim> > >& c)
00168 {
00169   typename container<Point<dim>, std::allocator<Point<dim> > >::const_iterator i = c.begin(), end = c.end();
00170 
00171   if(i == end) {
00172     return AxisBox<dim>();
00173   }
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 
00192 // This is here, instead of defined in the class, to
00193 // avoid include order problems
00194 
00195 template<int dim>
00196 inline AxisBox<dim> Point<dim>::boundingBox() const
00197 {
00198   return AxisBox<dim>(*this, *this, true);
00199 }
00200 
00201 template<int dim>
00202 Point<dim> Point<dim>::toParentCoords(const AxisBox<dim>& coords) const
00203 {
00204   return coords.lowCorner() + (*this - Point().setToOrigin());
00205 }
00206 
00207 template<int dim>
00208 Point<dim> Point<dim>::toLocalCoords(const AxisBox<dim>& coords) const
00209 {
00210   return Point().setToOrigin() + (*this - coords.lowCorner());
00211 }
00212 
00213 } // namespace WFMath
00214 
00215 #endif  // WFMATH_AXIS_BOX_FUNCS_H