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
37namespace WFMath {
38
39template<int dim>
40inline 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
47template<int dim>
49{
50 static ZeroPrimitive<Point<dim> > zeroPoint(dim);
51 return zeroPoint.getShape();
52}
53
54
55template<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
67template<int dim>
68inline 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
85template<int dim>
86inline 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
99template<int dim>
100inline 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
111template<int dim>
112inline 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
123template<int dim>
124inline 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 }
133 return (std::fabs(ans) >= _ScaleEpsilon(p1.m_elem, p2.m_elem, dim)) ? ans : 0;
134}
135
136template<int dim, template<class, class> class container,
137 template<class, class> class container2>
138Point<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
185template<int dim, template<class, class> class container>
186Point<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
218template<int dim>
219inline 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
233template<> Point<2>& Point<2>::polar(CoordType r, CoordType theta);
234template<> void Point<2>::asPolar(CoordType& r, CoordType& theta) const;
235
236template<> Point<3>& Point<3>::polar(CoordType r, CoordType theta,
237 CoordType z);
238template<> void Point<3>::asPolar(CoordType& r, CoordType& theta,
239 CoordType& z) const;
241 CoordType phi);
242template<> void Point<3>::asSpherical(CoordType& r, CoordType& theta,
243 CoordType& phi) const;
244
245} // namespace WFMath
246
247#endif // WFMATH_POINT_FUNCS_H
friend Point< dim > Midpoint(const Point &p1, const Point &p2, CoordType dist)
Find a point on the line containing p1 and p2, by default the midpoint.
Definition: point_funcs.h:219
void setValid(bool valid=true)
make isValid() return true if you've initialized the point by hand
Definition: point.h:129
static const Point< dim > & ZERO()
Provides a global instance preset to zero.
Definition: point_funcs.h:48
Point()
Construct an uninitialized point.
Definition: point.h:100
Utility class for providing zero primitives. This class will only work with simple structures such as...
Definition: zero.h:35
const Shape & getShape() const
Gets the zeroed shape.
Definition: zero.h:53
Generic library namespace.
Definition: shape.h:41
double CoordType
Basic floating point type.
Definition: const.h:140
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