wfmath  1.0.3
A math library for the Worldforge system.
point_funcs.h
1 // point_funcs.h (point class copied from libCoal, subsequently modified)
2 //
3 // The WorldForge Project
4 // Copyright (C) 2000, 2001, 2002 The WorldForge Project
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 //
20 // For information about WorldForge and its authors, please contact
21 // the Worldforge Web Site at http://www.worldforge.org.
22 //
23 
24 // Author: Ron Steinke
25 
26 
27 #ifndef WFMATH_POINT_FUNCS_H
28 #define WFMATH_POINT_FUNCS_H
29 
30 #include <wfmath/point.h>
31 
32 #include <wfmath/vector.h>
33 #include <wfmath/zero.h>
34 
35 #include <cmath>
36 
37 namespace WFMath {
38 
39 template<int dim>
40 inline Point<dim>::Point(const Vector<dim>& v) : m_valid(v.isValid())
41 {
42  for(int i = 0; i < dim; ++i) {
43  m_elem[i] = v.elements()[i];
44  }
45 }
46 
47 template<int dim>
49 {
50  static ZeroPrimitive<Point<dim> > zeroPoint(dim);
51  return zeroPoint.getShape();
52 }
53 
54 
55 template<int dim>
57 {
58  for(int i = 0; i < dim; ++i) {
59  m_elem[i] = 0;
60  }
61 
62  m_valid = true;
63 
64  return *this;
65 }
66 
67 template<int dim>
68 inline bool Point<dim>::isEqualTo(const Point<dim> &p, CoordType epsilon) const
69 {
70  //If anyone is invalid they are never equal
71  if (!p.m_valid || !m_valid) {
72  return false;
73  }
74 
75  CoordType delta = _ScaleEpsilon(m_elem, p.m_elem, dim, epsilon);
76  for(int i = 0; i < dim; ++i) {
77  if(std::fabs(m_elem[i] - p.m_elem[i]) > delta) {
78  return false;
79  }
80  }
81 
82  return true;
83 }
84 
85 template<int dim>
86 inline Vector<dim> operator-(const Point<dim>& c1, const Point<dim>& c2)
87 {
88  Vector<dim> out;
89 
90  for(int i = 0; i < dim; ++i) {
91  out.m_elem[i] = c1.m_elem[i] - c2.m_elem[i];
92  }
93 
94  out.m_valid = c1.m_valid && c2.m_valid;
95 
96  return out;
97 }
98 
99 template<int dim>
100 inline Point<dim>& operator+=(Point<dim>& p, const Vector<dim> &rhs)
101 {
102  for(int i = 0; i < dim; ++i) {
103  p.m_elem[i] += rhs.m_elem[i];
104  }
105 
106  p.m_valid = p.m_valid && rhs.m_valid;
107 
108  return p;
109 }
110 
111 template<int dim>
112 inline Point<dim>& operator-=(Point<dim>& p, const Vector<dim> &rhs)
113 {
114  for(int i = 0; i < dim; ++i) {
115  p.m_elem[i] -= rhs.m_elem[i];
116  }
117 
118  p.m_valid = p.m_valid && rhs.m_valid;
119 
120  return p;
121 }
122 
123 template<int dim>
124 inline CoordType SquaredDistance(const Point<dim>& p1, const Point<dim>& p2)
125 {
126  CoordType ans = 0;
127 
128  for(int i = 0; i < dim; ++i) {
129  CoordType diff = p1.m_elem[i] - p2.m_elem[i];
130  ans += diff * diff;
131  }
132 
133  return (std::fabs(ans) >= _ScaleEpsilon(p1.m_elem, p2.m_elem, dim)) ? ans : 0;
134 }
135 
136 template<int dim, template<class, class> class container,
137  template<class, class> class container2>
138 Point<dim> Barycenter(const container<Point<dim>, std::allocator<Point<dim> > >& c,
139  const container2<CoordType, std::allocator<CoordType> >& weights)
140 {
141  // FIXME become friend
142 
143  typename container<Point<dim>, std::allocator<Point<dim> > >::const_iterator c_i = c.begin(), c_end = c.end();
144  typename container2<CoordType, std::allocator<CoordType> >::const_iterator w_i = weights.begin(),
145  w_end = weights.end();
146 
147  Point<dim> out;
148 
149  if (c_i == c_end || w_i == w_end) {
150  return out;
151  }
152 
153  bool valid = c_i->isValid();
154 
155  CoordType tot_weight = *w_i, max_weight = std::fabs(*w_i);
156  for(int j = 0; j < dim; ++j) {
157  out[j] = (*c_i)[j] * *w_i;
158  }
159 
160  while(++c_i != c_end && ++w_i != w_end) {
161  tot_weight += *w_i;
162  CoordType val = std::fabs(*w_i);
163  if(val > max_weight)
164  max_weight = val;
165  if(!c_i->isValid())
166  valid = false;
167  for(int j = 0; j < dim; ++j)
168  out[j] += (*c_i)[j] * *w_i;
169  }
170 
171  // Make sure the weights don't add up to zero
172  if (max_weight <= 0 || std::fabs(tot_weight) <= max_weight * numeric_constants<CoordType>::epsilon()) {
173  return out;
174  }
175 
176  for(int j = 0; j < dim; ++j) {
177  out[j] /= tot_weight;
178  }
179 
180  out.setValid(valid);
181 
182  return out;
183 }
184 
185 template<int dim, template<class, class> class container>
186 Point<dim> Barycenter(const container<Point<dim>, std::allocator<Point<dim> > >& c)
187 {
188  // FIXME become friend
189 
190  typename container<Point<dim>, std::allocator<Point<dim> > >::const_iterator i = c.begin(), end = c.end();
191 
192  if (i == end) {
193  return Point<dim>();
194  }
195 
196  Point<dim> out = *i;
197  CoordType num_points = 1;
198 
199  bool valid = i->isValid();
200 
201  while(++i != end) {
202  ++num_points;
203  if(!i->isValid())
204  valid = false;
205  for(int j = 0; j < dim; ++j)
206  out[j] += (*i)[j];
207  }
208 
209  for(int j = 0; j < dim; ++j) {
210  out[j] /= num_points;
211  }
212 
213  out.setValid(valid);
214 
215  return out;
216 }
217 
218 template<int dim>
219 inline Point<dim> Midpoint(const Point<dim>& p1, const Point<dim>& p2, CoordType dist)
220 {
221  Point<dim> out;
222  CoordType conj_dist = 1 - dist;
223 
224  for(int i = 0; i < dim; ++i) {
225  out.m_elem[i] = p1.m_elem[i] * conj_dist + p2.m_elem[i] * dist;
226  }
227 
228  out.m_valid = p1.m_valid && p2.m_valid;
229 
230  return out;
231 }
232 
233 template<> Point<2>& Point<2>::polar(CoordType r, CoordType theta);
234 template<> void Point<2>::asPolar(CoordType& r, CoordType& theta) const;
235 
236 template<> Point<3>& Point<3>::polar(CoordType r, CoordType theta,
237  CoordType z);
238 template<> void Point<3>::asPolar(CoordType& r, CoordType& theta,
239  CoordType& z) const;
240 template<> Point<3>& Point<3>::spherical(CoordType r, CoordType theta,
241  CoordType phi);
242 template<> void Point<3>::asSpherical(CoordType& r, CoordType& theta,
243  CoordType& phi) const;
244 
245 } // namespace WFMath
246 
247 #endif // WFMATH_POINT_FUNCS_H
WFMath::Midpoint
Point< dim > Midpoint(const Point< dim > &p1, const Point< dim > &p2, CoordType dist=0.5)
Definition: point_funcs.h:219
WFMath::Point::setValid
void setValid(bool valid=true)
make isValid() return true if you've initialized the point by hand
Definition: point.h:129
WFMath::Point::polar
Point & polar(CoordType r, CoordType theta)
2D only: construct a vector from polar coordinates
WFMath::Point::Point
Point()
Construct an uninitialized point.
Definition: point.h:100
WFMath::Point::setToOrigin
Point & setToOrigin()
Set point to (0,0,...,0)
Definition: point_funcs.h:56
WFMath::Barycenter
Point< dim > Barycenter(const container< Point< dim >, std::allocator< Point< dim > > > &c)
Find the center of a set of points, all weighted equally.
Definition: point_funcs.h:186
WFMath::ZeroPrimitive::getShape
const Shape & getShape() const
Gets the zeroed shape.
Definition: zero.h:53
WFMath
Generic library namespace.
Definition: shape.h:41
WFMath::Vector
A dim dimensional vector.
Definition: const.h:55
WFMath::CoordType
double CoordType
Basic floating point type.
Definition: const.h:140
WFMath::numeric_constants
Definition: const.h:65
WFMath::Point::asPolar
void asPolar(CoordType &r, CoordType &theta) const
2D only: convert a vector to polar coordinates
WFMath::ZeroPrimitive
Utility class for providing zero primitives. This class will only work with simple structures such as...
Definition: point.h:87
WFMath::Point::ZERO
static const Point< dim > & ZERO()
Provides a global instance preset to zero.
Definition: point_funcs.h:48
WFMath::Point::spherical
Point & spherical(CoordType r, CoordType theta, CoordType phi)
3D only: construct a vector from spherical coordinates
WFMath::Point::asSpherical
void asSpherical(CoordType &r, CoordType &theta, CoordType &phi) const
3D only: convert a vector to spherical coordinates
WFMath::Point
A dim dimensional point.
Definition: const.h:50