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 Point<dim>& p) : m_valid(p.m_valid)
41 {
42  for(int i = 0; i < dim; ++i) {
43  m_elem[i] = p.m_elem[i];
44  }
45 }
46 
47 template<int dim>
48 inline Point<dim>::Point(const Vector<dim>& v) : m_valid(v.isValid())
49 {
50  for(int i = 0; i < dim; ++i) {
51  m_elem[i] = v.elements()[i];
52  }
53 }
54 
55 template<int dim>
57 {
58  static ZeroPrimitive<Point<dim> > zeroPoint(dim);
59  return zeroPoint.getShape();
60 }
61 
62 
63 template<int dim>
65 {
66  for(int i = 0; i < dim; ++i) {
67  m_elem[i] = 0;
68  }
69 
70  m_valid = true;
71 
72  return *this;
73 }
74 
75 template<int dim>
76 inline bool Point<dim>::isEqualTo(const Point<dim> &p, CoordType epsilon) const
77 {
78  //If anyone is invalid they are never equal
79  if (!p.m_valid || !m_valid) {
80  return false;
81  }
82 
83  CoordType delta = _ScaleEpsilon(m_elem, p.m_elem, dim, epsilon);
84  for(int i = 0; i < dim; ++i) {
85  if(std::fabs(m_elem[i] - p.m_elem[i]) > delta) {
86  return false;
87  }
88  }
89 
90  return true;
91 }
92 
93 template<int dim>
94 inline Vector<dim> operator-(const Point<dim>& c1, const Point<dim>& c2)
95 {
96  Vector<dim> out;
97 
98  for(int i = 0; i < dim; ++i) {
99  out.m_elem[i] = c1.m_elem[i] - c2.m_elem[i];
100  }
101 
102  out.m_valid = c1.m_valid && c2.m_valid;
103 
104  return out;
105 }
106 
107 template<int dim>
108 inline Point<dim>& operator+=(Point<dim>& p, const Vector<dim> &rhs)
109 {
110  for(int i = 0; i < dim; ++i) {
111  p.m_elem[i] += rhs.m_elem[i];
112  }
113 
114  p.m_valid = p.m_valid && rhs.m_valid;
115 
116  return p;
117 }
118 
119 template<int dim>
120 inline Point<dim>& operator-=(Point<dim>& p, const Vector<dim> &rhs)
121 {
122  for(int i = 0; i < dim; ++i) {
123  p.m_elem[i] -= rhs.m_elem[i];
124  }
125 
126  p.m_valid = p.m_valid && rhs.m_valid;
127 
128  return p;
129 }
130 
131 template<int dim>
132 inline Point<dim>& Point<dim>::operator=(const Point<dim>& rhs)
133 {
134  // Compare pointer addresses
135  if (this == &rhs) {
136  return *this;
137  }
138 
139  for(int i = 0; i < dim; ++i) {
140  m_elem[i] = rhs.m_elem[i];
141  }
142 
143  m_valid = rhs.m_valid;
144 
145  return *this;
146 }
147 
148 template<int dim>
149 inline CoordType SquaredDistance(const Point<dim>& p1, const Point<dim>& p2)
150 {
151  CoordType ans = 0;
152 
153  for(int i = 0; i < dim; ++i) {
154  CoordType diff = p1.m_elem[i] - p2.m_elem[i];
155  ans += diff * diff;
156  }
157 
158  return (std::fabs(ans) >= _ScaleEpsilon(p1.m_elem, p2.m_elem, dim)) ? ans : 0;
159 }
160 
161 template<int dim, template<class, class> class container,
162  template<class, class> class container2>
163 Point<dim> Barycenter(const container<Point<dim>, std::allocator<Point<dim> > >& c,
164  const container2<CoordType, std::allocator<CoordType> >& weights)
165 {
166  // FIXME become friend
167 
168  typename container<Point<dim>, std::allocator<Point<dim> > >::const_iterator c_i = c.begin(), c_end = c.end();
169  typename container2<CoordType, std::allocator<CoordType> >::const_iterator w_i = weights.begin(),
170  w_end = weights.end();
171 
172  Point<dim> out;
173 
174  if (c_i == c_end || w_i == w_end) {
175  return out;
176  }
177 
178  bool valid = c_i->isValid();
179 
180  CoordType tot_weight = *w_i, max_weight = std::fabs(*w_i);
181  for(int j = 0; j < dim; ++j) {
182  out[j] = (*c_i)[j] * *w_i;
183  }
184 
185  while(++c_i != c_end && ++w_i != w_end) {
186  tot_weight += *w_i;
187  CoordType val = std::fabs(*w_i);
188  if(val > max_weight)
189  max_weight = val;
190  if(!c_i->isValid())
191  valid = false;
192  for(int j = 0; j < dim; ++j)
193  out[j] += (*c_i)[j] * *w_i;
194  }
195 
196  // Make sure the weights don't add up to zero
197  if (max_weight <= 0 || std::fabs(tot_weight) <= max_weight * numeric_constants<CoordType>::epsilon()) {
198  return out;
199  }
200 
201  for(int j = 0; j < dim; ++j) {
202  out[j] /= tot_weight;
203  }
204 
205  out.setValid(valid);
206 
207  return out;
208 }
209 
210 template<int dim, template<class, class> class container>
211 Point<dim> Barycenter(const container<Point<dim>, std::allocator<Point<dim> > >& c)
212 {
213  // FIXME become friend
214 
215  typename container<Point<dim>, std::allocator<Point<dim> > >::const_iterator i = c.begin(), end = c.end();
216 
217  if (i == end) {
218  return Point<dim>();
219  }
220 
221  Point<dim> out = *i;
222  CoordType num_points = 1;
223 
224  bool valid = i->isValid();
225 
226  while(++i != end) {
227  ++num_points;
228  if(!i->isValid())
229  valid = false;
230  for(int j = 0; j < dim; ++j)
231  out[j] += (*i)[j];
232  }
233 
234  for(int j = 0; j < dim; ++j) {
235  out[j] /= num_points;
236  }
237 
238  out.setValid(valid);
239 
240  return out;
241 }
242 
243 template<int dim>
244 inline Point<dim> Midpoint(const Point<dim>& p1, const Point<dim>& p2, CoordType dist)
245 {
246  Point<dim> out;
247  CoordType conj_dist = 1 - dist;
248 
249  for(int i = 0; i < dim; ++i) {
250  out.m_elem[i] = p1.m_elem[i] * conj_dist + p2.m_elem[i] * dist;
251  }
252 
253  out.m_valid = p1.m_valid && p2.m_valid;
254 
255  return out;
256 }
257 
258 template<> Point<2>& Point<2>::polar(CoordType r, CoordType theta);
259 template<> void Point<2>::asPolar(CoordType& r, CoordType& theta) const;
260 
261 template<> Point<3>& Point<3>::polar(CoordType r, CoordType theta,
262  CoordType z);
263 template<> void Point<3>::asPolar(CoordType& r, CoordType& theta,
264  CoordType& z) const;
265 template<> Point<3>& Point<3>::spherical(CoordType r, CoordType theta,
266  CoordType phi);
267 template<> void Point<3>::asSpherical(CoordType& r, CoordType& theta,
268  CoordType& phi) const;
269 
270 } // namespace WFMath
271 
272 #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:244
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< 2 >::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::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:211
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:64
WFMath::Point< 2 >::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
A dim dimensional point.
Definition: const.h:50