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