00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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 container,
00161 template<class> class container2>
00162 Point<dim> Barycenter(const container<Point<dim> >& c,
00163 const container2<CoordType>& weights)
00164 {
00165
00166
00167 typename container<Point<dim> >::const_iterator c_i = c.begin(), c_end = c.end();
00168 typename container2<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
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 container>
00205 Point<dim> Barycenter(const container<Point<dim> >& c)
00206 {
00207
00208
00209 typename container<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 }
00331
00332 #endif // WFMATH_POINT_FUNCS_H