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