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