Main Page | Namespace List | Class List | File List | Namespace Members | Class Members

point_funcs.h

00001 // point_funcs.h (point class copied from libCoal, subsequently modified) 00002 // 00003 // The WorldForge Project 00004 // Copyright (C) 2000, 2001, 2002 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 00027 #ifndef WFMATH_POINT_FUNCS_H 00028 #define WFMATH_POINT_FUNCS_H 00029 00030 #include <wfmath/const.h> 00031 #include <wfmath/vector.h> 00032 #include <wfmath/point.h> 00033 00034 namespace WFMath { 00035 00036 template<const int dim> 00037 inline Point<dim>::Point(const Point<dim>& p) : m_valid(p.m_valid) 00038 { 00039 for(int i = 0; i < dim; ++i) 00040 m_elem[i] = p.m_elem[i]; 00041 } 00042 00043 template<const int dim> 00044 inline Point<dim>& Point<dim>::setToOrigin() 00045 { 00046 for(int i = 0; i < dim; ++i) 00047 m_elem[i] = 0; 00048 00049 m_valid = true; 00050 00051 return *this; 00052 } 00053 00054 template<const int dim> 00055 inline bool Point<dim>::isEqualTo(const Point<dim> &p, double epsilon) const 00056 { 00057 CoordType delta = (CoordType) _ScaleEpsilon(m_elem, p.m_elem, dim, epsilon); 00058 00059 for(int i = 0; i < dim; ++i) 00060 if(fabs(m_elem[i] - p.m_elem[i]) > delta) 00061 return false; 00062 00063 return true; 00064 } 00065 00066 template<const int dim> 00067 inline Vector<dim> operator-(const Point<dim>& c1, const Point<dim>& c2) 00068 { 00069 Vector<dim> out; 00070 00071 for(int i = 0; i < dim; ++i) 00072 out.m_elem[i] = c1.m_elem[i] - c2.m_elem[i]; 00073 00074 out.m_valid = c1.m_valid && c2.m_valid; 00075 00076 return out; 00077 } 00078 00079 template<const int dim> 00080 inline Point<dim> operator+(const Point<dim>& c, const Vector<dim>& v) 00081 { 00082 Point<dim> out; 00083 00084 for(int i = 0; i < dim; ++i) 00085 out.m_elem[i] = c.m_elem[i] + v.m_elem[i]; 00086 00087 out.m_valid = c.m_valid && v.m_valid; 00088 00089 return out; 00090 } 00091 00092 template<const int dim> 00093 inline Point<dim> operator-(const Point<dim>& c, const Vector<dim>& v) 00094 { 00095 Point<dim> out; 00096 00097 for(int i = 0; i < dim; ++i) 00098 out.m_elem[i] = c.m_elem[i] - v.m_elem[i]; 00099 00100 out.m_valid = c.m_valid && v.m_valid; 00101 00102 return out; 00103 } 00104 00105 template<const int dim> 00106 inline Point<dim> operator+(const Vector<dim>& v, const Point<dim>& c) 00107 { 00108 Point<dim> out; 00109 00110 for(int i = 0; i < dim; ++i) 00111 out.m_elem[i] = c.m_elem[i] + v.m_elem[i]; 00112 00113 out.m_valid = c.m_valid && v.m_valid; 00114 00115 return out; 00116 } 00117 00118 template<const int dim> 00119 inline Point<dim>& Point<dim>::operator=(const Point<dim>& rhs) 00120 { 00121 // Compare pointer addresses 00122 if (this == &rhs) 00123 return *this; 00124 00125 for(int i = 0; i < dim; ++i) 00126 m_elem[i] = rhs.m_elem[i]; 00127 00128 m_valid = rhs.m_valid; 00129 00130 return *this; 00131 } 00132 00133 template<const int dim> 00134 inline Point<dim>& operator+=(Point<dim>& p, const Vector<dim> &rhs) 00135 { 00136 for(int i = 0; i < dim; ++i) 00137 p.m_elem[i] += rhs.m_elem[i]; 00138 00139 p.m_valid = p.m_valid && rhs.m_valid; 00140 00141 return p; 00142 } 00143 00144 template<const int dim> 00145 inline Point<dim>& operator-=(Point<dim>& p, const Vector<dim> &rhs) 00146 { 00147 for(int i = 0; i < dim; ++i) 00148 p.m_elem[i] -= rhs.m_elem[i]; 00149 00150 p.m_valid = p.m_valid && rhs.m_valid; 00151 00152 return p; 00153 } 00154 00155 template<const int dim> 00156 inline CoordType SquaredDistance(const Point<dim>& p1, const Point<dim>& p2) 00157 { 00158 CoordType ans = 0; 00159 00160 for(int i = 0; i < dim; ++i) { 00161 CoordType diff = p1.m_elem[i] - p2.m_elem[i]; 00162 ans += diff * diff; 00163 } 00164 00165 return (fabs(ans) >= _ScaleEpsilon(p1.m_elem, p2.m_elem, dim)) ? ans : 0; 00166 } 00167 00168 #ifndef WFMATH_NO_TEMPLATES_AS_TEMPLATE_PARAMETERS 00169 template<const int dim, template<class> class container, 00170 template<class> class container2> 00171 Point<dim> Barycenter(const container<Point<dim> >& c, 00172 const container2<CoordType>& weights) 00173 { 00174 // FIXME become friend 00175 00176 typename container<Point<dim> >::const_iterator c_i = c.begin(), c_end = c.end(); 00177 typename container2<CoordType>::const_iterator w_i = weights.begin(), 00178 w_end = weights.end(); 00179 00180 assert("nonempty list of points" && c_i != c_end); 00181 assert("nonempty list of weights" && w_i != w_end); 00182 00183 bool valid = c_i->isValid(); 00184 00185 CoordType tot_weight = *w_i, max_weight = fabs(*w_i); 00186 Point<dim> out; 00187 for(int j = 0; j < dim; ++j) 00188 out[j] = (*c_i)[j] * *w_i; 00189 00190 while(++c_i != c_end && ++w_i != w_end) { 00191 tot_weight += *w_i; 00192 CoordType val = fabs(*w_i); 00193 if(val > max_weight) 00194 max_weight = val; 00195 if(!c_i->isValid()) 00196 valid = false; 00197 for(int j = 0; j < dim; ++j) 00198 out[j] += (*c_i)[j] * *w_i; 00199 } 00200 00201 // Make sure the weights don't add up to zero 00202 assert("sum of weights must be nonzero" && max_weight > 0 00203 && fabs(tot_weight) > max_weight * WFMATH_EPSILON); 00204 00205 for(int j = 0; j < dim; ++j) 00206 out[j] /= tot_weight; 00207 00208 out.setValid(valid); 00209 00210 return out; 00211 } 00212 00213 template<const int dim, template<class> class container> 00214 Point<dim> Barycenter(const container<Point<dim> >& c) 00215 { 00216 // FIXME become friend 00217 00218 typename container<Point<dim> >::const_iterator i = c.begin(), end = c.end(); 00219 00220 assert("nonempty list of points" && i != end); 00221 00222 Point<dim> out = *i; 00223 int num_points = 1; 00224 00225 bool valid = i->isValid(); 00226 00227 while(++i != end) { 00228 ++num_points; 00229 if(!i->isValid()) 00230 valid = false; 00231 for(int j = 0; j < dim; ++j) 00232 out[j] += (*i)[j]; 00233 } 00234 00235 for(int j = 0; j < dim; ++j) 00236 out[j] /= num_points; 00237 00238 out.setValid(valid); 00239 00240 return out; 00241 } 00242 #endif 00243 00244 template<const int dim> 00245 inline Point<dim> Midpoint(const Point<dim>& p1, const Point<dim>& p2, CoordType dist) 00246 { 00247 Point<dim> out; 00248 CoordType conj_dist = 1 - dist; 00249 00250 for(int i = 0; i < dim; ++i) 00251 out.m_elem[i] = p1.m_elem[i] * conj_dist + p2.m_elem[i] * dist; 00252 00253 out.m_valid = p1.m_valid && p2.m_valid; 00254 00255 return out; 00256 } 00257 00258 template<> inline Point<2>::Point(CoordType x, CoordType y) : m_valid(true) 00259 { 00260 m_elem[0] = x; 00261 m_elem[1] = y; 00262 } 00263 00264 template<> inline Point<3>::Point(CoordType x, CoordType y, CoordType z) : m_valid(true) 00265 { 00266 m_elem[0] = x; 00267 m_elem[1] = y; 00268 m_elem[2] = z; 00269 } 00270 00271 #ifndef WFMATH_NO_CLASS_FUNCTION_SPECIALIZATION 00272 template<> Point<2>& Point<2>::polar(CoordType r, CoordType theta); 00273 template<> void Point<2>::asPolar(CoordType& r, CoordType& theta) const; 00274 00275 template<> Point<3>& Point<3>::polar(CoordType r, CoordType theta, 00276 CoordType z); 00277 template<> void Point<3>::asPolar(CoordType& r, CoordType& theta, 00278 CoordType& z) const; 00279 template<> Point<3>& Point<3>::spherical(CoordType r, CoordType theta, 00280 CoordType phi); 00281 template<> void Point<3>::asSpherical(CoordType& r, CoordType& theta, 00282 CoordType& phi) const; 00283 #else 00284 void _NCFS_Point2_polar(CoordType *m_elem, CoordType r, CoordType theta); 00285 void _NCFS_Point2_asPolar(CoordType *m_elem, CoordType& r, CoordType& theta); 00286 00287 void _NCFS_Point3_polar(CoordType *m_elem, CoordType r, CoordType theta, 00288 CoordType z); 00289 void _NCFS_Point3_asPolar(CoordType *m_elem, CoordType& r, CoordType& theta, 00290 CoordType& z); 00291 void _NCFS_Point3_spherical(CoordType *m_elem, CoordType r, CoordType theta, 00292 CoordType phi); 00293 void _NCFS_Point3_asSpherical(CoordType *m_elem, CoordType& r, CoordType& theta, 00294 CoordType& phi); 00295 00296 template<> 00297 inline Point<2>& Point<2>::polar(CoordType r, CoordType theta) 00298 { 00299 _NCFS_Point2_polar((CoordType*) m_elem, r, theta); 00300 m_valid = true; 00301 return *this; 00302 } 00303 00304 template<> 00305 inline void Point<2>::asPolar(CoordType& r, CoordType& theta) const 00306 { 00307 _NCFS_Point2_asPolar((CoordType*) m_elem, r, theta); 00308 } 00309 00310 template<> 00311 inline Point<3>& Point<3>::polar(CoordType r, CoordType theta, CoordType z) 00312 { 00313 _NCFS_Point3_polar((CoordType*) m_elem, r, theta, z); 00314 m_valid = true; 00315 return *this; 00316 } 00317 00318 template<> 00319 inline void Point<3>::asPolar(CoordType& r, CoordType& theta, CoordType& z) const 00320 { 00321 _NCFS_Point3_asPolar((CoordType*) m_elem, r, theta, z); 00322 } 00323 00324 template<> 00325 inline Point<3>& Point<3>::spherical(CoordType r, CoordType theta, CoordType phi) 00326 { 00327 _NCFS_Point3_spherical((CoordType*) m_elem, r, theta, phi); 00328 m_valid = true; 00329 return *this; 00330 } 00331 00332 template<> 00333 inline void Point<3>::asSpherical(CoordType& r, CoordType& theta, CoordType& phi) const 00334 { 00335 _NCFS_Point3_asSpherical((CoordType*) m_elem, r, theta, phi); 00336 } 00337 #endif 00338 00339 } // namespace WFMath 00340 00341 #endif // WFMATH_POINT_FUNCS_H

Generated on Thu Jul 29 07:09:56 2004 for WFMath by doxygen 1.3.7