26 #ifndef WFMATH_POLYGON_FUNCS_H
27 #define WFMATH_POLYGON_FUNCS_H
29 #include <wfmath/polygon.h>
31 #include <wfmath/vector.h>
32 #include <wfmath/point.h>
33 #include <wfmath/ball.h>
43 inline bool Polygon<dim>::isEqualTo(
const Polygon<dim>& p,
CoordType epsilon)
const
48 size_t size = m_poly.numCorners();
49 if(size != p.m_poly.numCorners())
52 for(
size_t i = 0; i < size; ++i)
53 if(!Equal(getCorner(i), p.getCorner(i), epsilon))
60 inline Point<dim> Poly2Orient<dim>::convert(
const Point<2>& p)
const
62 assert(m_origin.isValid());
64 Point<dim> out = m_origin;
66 for(
int j = 0; j < 2; ++j) {
67 if(m_axes[j].isValid())
68 out += m_axes[j] * p[j];
73 out.setValid(p.isValid());
79 bool Poly2Orient<dim>::expand(
const Point<dim>& pd, Point<2>& p2,
CoordType epsilon)
84 if(!m_origin.isValid()) {
90 Vector<dim> shift = pd - m_origin, start_shift = shift;
92 CoordType bound = shift.sqrMag() * epsilon;
97 if(Dot(shift, start_shift) <= bound)
105 if(!m_axes[j].isValid()) {
107 m_axes[j] = shift / p2[j];
108 m_axes[j].setValid();
112 p2[j] = Dot(shift, m_axes[j]);
113 shift -= m_axes[j] * p2[j];
119 Poly2Reorient Poly2Orient<dim>::reduce(
const Polygon<2>& poly,
size_t skip)
121 if(poly.numCorners() <= ((skip == 0) ? 1 : 0)) {
122 m_origin.setValid(
false);
123 m_axes[0].setValid(
false);
124 m_axes[1].setValid(
false);
125 return Poly2Reorient(WFMATH_POLY2REORIENT_NONE);
128 assert(m_origin.isValid());
130 if(!m_axes[0].isValid())
131 return Poly2Reorient(WFMATH_POLY2REORIENT_NONE);
135 bool still_valid[2] = {
false,}, got_ratio =
false;
136 CoordType ratio = std::numeric_limits<CoordType>::max();
137 CoordType size = std::numeric_limits<CoordType>::max();
139 size_t i, end = poly.numCorners();
142 for(i = 0; i < end; ++i) {
145 const Point<2> &p = poly[i];
148 max = (x > y) ? x : y;
149 if(i == 0 || max < size)
153 (void) std::frexp(size, &exponent);
160 Point<2> first_point = poly[i];
161 first_point.setValid();
167 Vector<2> diff = poly[i] - first_point;
168 if(diff.sqrMag() < epsilon * epsilon)
170 if(!m_axes[1].isValid())
171 return Poly2Reorient(WFMATH_POLY2REORIENT_NONE);
172 for(
int j = 0; j < 2; ++j) {
173 if(std::fabs(diff[j]) < epsilon) {
174 assert(diff[j ? 0 : 1] >= epsilon);
175 if(still_valid[j ? 0 : 1] || got_ratio)
176 return Poly2Reorient(WFMATH_POLY2REORIENT_NONE);
177 still_valid[j] =
true;
181 if(still_valid[0] || still_valid[1])
182 return Poly2Reorient(WFMATH_POLY2REORIENT_NONE);
189 if(!Equal(ratio, new_ratio))
190 return Poly2Reorient(WFMATH_POLY2REORIENT_NONE);
196 assert(m_axes[1].isValid());
197 assert(!still_valid[1]);
200 m_origin += m_axes[1] * first_point[1];
201 m_axes[1].setValid(
false);
202 return Poly2Reorient(WFMATH_POLY2REORIENT_CLEAR_AXIS2);
206 assert(m_axes[1].isValid());
209 m_origin += m_axes[0] * first_point[0];
210 m_axes[0] = m_axes[1];
211 m_axes[1].setValid(
false);
212 return Poly2Reorient(WFMATH_POLY2REORIENT_MOVE_AXIS2_TO_AXIS1);
217 m_origin += m_axes[0] * first_point[0];
218 if(m_axes[1].isValid())
219 m_origin += m_axes[1] * first_point[1];
220 m_axes[0].setValid(
false);
221 m_axes[1].setValid(
false);
222 return Poly2Reorient(WFMATH_POLY2REORIENT_CLEAR_BOTH_AXES);
225 assert(m_axes[1].isValid());
231 new0 = m_axes[0] + m_axes[1] * ratio;
241 m_origin += m_axes[1] * (first_point[1] - ratio * first_point[0]);
244 m_axes[1].setValid(
false);
245 return Poly2Reorient(WFMATH_POLY2REORIENT_SCALE1_CLEAR2, norm);
249 inline void Poly2Orient<dim>::rotate(
const RotMatrix<dim>& m,
const Point<dim>& p)
251 m_origin.rotate(m, p);
253 for(
int j = 0; j < 2; ++j)
254 m_axes[j] =
Prod(m_axes[j], m);
258 void Poly2Orient<dim>::rotate2(
const RotMatrix<dim>& m,
const Point<2>& p)
260 assert(m_origin.isValid());
262 if(!m_axes[0].isValid()) {
263 assert(p[0] == 0 && p[1] == 0);
267 Vector<dim> shift = m_axes[0] * p[0];
268 m_axes[0] =
Prod(m_axes[0], m);
270 if(m_axes[1].isValid()) {
271 shift += m_axes[1] * p[1];
272 m_axes[1] =
Prod(m_axes[1], m);
277 m_origin += shift -
Prod(shift, m);
281 inline void Poly2Orient<3>::rotate(
const Quaternion& q,
const Point<3>& p)
283 m_origin.rotate(q, p);
285 for(
int j = 0; j < 2; ++j)
290 inline void Poly2Orient<3>::rotate2(
const Quaternion& q,
const Point<2>& p)
292 assert(m_origin.isValid());
294 if(!m_axes[0].isValid()) {
295 assert(p[0] == 0 && p[1] == 0);
299 Vector<3> shift = m_axes[0] * p[0];
302 if(m_axes[1].isValid()) {
303 shift += m_axes[1] * p[1];
309 m_origin += shift - shift.rotate(q);
313 AxisBox<dim> Polygon<dim>::boundingBox()
const
315 assert(m_poly.numCorners() > 0);
317 Point<dim> min = m_orient.convert(m_poly[0]), max = min;
318 bool valid = min.isValid();
320 for(
size_t i = 1; i != m_poly.numCorners(); ++i) {
321 Point<dim> p = m_orient.convert(m_poly[i]);
322 valid = valid && p.isValid();
323 for(
int j = 0; j < dim; ++j) {
334 return AxisBox<dim>(min, max,
true);
338 inline Ball<dim> Polygon<dim>::boundingSphere()
const
340 Ball<2> b = m_poly.boundingSphere();
342 return Ball<dim>(m_orient.convert(b.center()), b.radius());
346 inline Ball<dim> Polygon<dim>::boundingSphereSloppy()
const
348 Ball<2> b = m_poly.boundingSphereSloppy();
350 return Ball<dim>(m_orient.convert(b.center()), b.radius());
Generic library namespace.
double CoordType
Basic floating point type.
RotMatrix< dim > Prod(const RotMatrix< dim > &m1, const RotMatrix< dim > &m2)
returns m1 * m2
static FloatType epsilon()
This is the attempted precision of the library.