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

Generated on Wed Aug 22 02:01:15 2007 for WFMath by  doxygen 1.5.2