WFMath 0.3.11
|
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