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 _Poly2Orient<dim>& _Poly2Orient<dim>::operator=(
const _Poly2Orient<dim>& a)
45 m_origin = a.m_origin;
47 for(
int i = 0; i < 2; ++i)
48 m_axes[i] = a.m_axes[i];
54 inline bool Polygon<dim>::isEqualTo(
const Polygon<dim>& p,
CoordType epsilon)
const
59 size_t size = m_poly.numCorners();
60 if(size != p.m_poly.numCorners())
63 for(
size_t i = 0; i < size; ++i)
64 if(!
Equal(getCorner(i), p.getCorner(i), epsilon))
71 inline Point<dim> _Poly2Orient<dim>::convert(
const Point<2>& p)
const
73 assert(m_origin.isValid());
75 Point<dim> out = m_origin;
77 for(
int j = 0; j < 2; ++j) {
78 if(m_axes[j].isValid())
79 out += m_axes[j] * p[j];
84 out.setValid(p.isValid());
90 bool _Poly2Orient<dim>::expand(
const Point<dim>& pd, Point<2>& p2,
CoordType epsilon)
95 if(!m_origin.isValid()) {
101 Vector<dim> shift = pd - m_origin, start_shift = shift;
103 CoordType bound = shift.sqrMag() * epsilon;
108 if(Dot(shift, start_shift) <= bound)
116 if(!m_axes[j].isValid()) {
118 m_axes[j] = shift / p2[j];
119 m_axes[j].setValid();
123 p2[j] = Dot(shift, m_axes[j]);
124 shift -= m_axes[j] * p2[j];
130 _Poly2Reorient _Poly2Orient<dim>::reduce(
const Polygon<2>& poly,
size_t skip)
132 if(poly.numCorners() <= ((skip == 0) ? 1 : 0)) {
133 m_origin.setValid(
false);
134 m_axes[0].setValid(
false);
135 m_axes[1].setValid(
false);
136 return _WFMATH_POLY2REORIENT_NONE;
139 assert(m_origin.isValid());
141 if(!m_axes[0].isValid())
142 return _WFMATH_POLY2REORIENT_NONE;
146 bool still_valid[2] = {
false,}, got_ratio =
false;
147 CoordType ratio = std::numeric_limits<CoordType>::max();
148 CoordType size = std::numeric_limits<CoordType>::max();
150 size_t i, end = poly.numCorners();
153 for(i = 0; i < end; ++i) {
156 const Point<2> &p = poly[i];
159 max = (x > y) ? x : y;
160 if(i == 0 || max < size)
164 (void) std::frexp(size, &exponent);
165 epsilon = std::ldexp(numeric_constants<CoordType>::epsilon(), exponent);
171 Point<2> first_point = poly[i];
172 first_point.setValid();
178 Vector<2> diff = poly[i] - first_point;
179 if(diff.sqrMag() < epsilon * epsilon)
181 if(!m_axes[1].isValid())
182 return _WFMATH_POLY2REORIENT_NONE;
183 for(
int j = 0; j < 2; ++j) {
184 if(std::fabs(diff[j]) < epsilon) {
185 assert(diff[j ? 0 : 1] >= epsilon);
186 if(still_valid[j ? 0 : 1] || got_ratio)
187 return _WFMATH_POLY2REORIENT_NONE;
188 still_valid[j] =
true;
192 if(still_valid[0] || still_valid[1])
193 return _WFMATH_POLY2REORIENT_NONE;
200 if(!
Equal(ratio, new_ratio))
201 return _WFMATH_POLY2REORIENT_NONE;
207 assert(m_axes[1].isValid());
208 assert(!still_valid[1]);
211 m_origin += m_axes[1] * first_point[1];
212 m_axes[1].setValid(
false);
213 return _WFMATH_POLY2REORIENT_CLEAR_AXIS2;
217 assert(m_axes[1].isValid());
220 m_origin += m_axes[0] * first_point[0];
221 m_axes[0] = m_axes[1];
222 m_axes[1].setValid(
false);
223 return _WFMATH_POLY2REORIENT_MOVE_AXIS2_TO_AXIS1;
228 m_origin += m_axes[0] * first_point[0];
229 if(m_axes[1].isValid())
230 m_origin += m_axes[1] * first_point[1];
231 m_axes[0].setValid(
false);
232 m_axes[1].setValid(
false);
233 return _WFMATH_POLY2REORIENT_CLEAR_BOTH_AXES;
236 assert(m_axes[1].isValid());
242 new0 = m_axes[0] + m_axes[1] * ratio;
252 m_origin += m_axes[1] * (first_point[1] - ratio * first_point[0]);
255 m_axes[1].setValid(
false);
256 return _Poly2Reorient(_WFMATH_POLY2REORIENT_SCALE1_CLEAR2, norm);
260 inline void _Poly2Orient<dim>::rotate(
const RotMatrix<dim>& m,
const Point<dim>& p)
262 m_origin.rotate(m, p);
264 for(
int j = 0; j < 2; ++j)
265 m_axes[j] =
Prod(m_axes[j], m);
269 void _Poly2Orient<dim>::rotate2(
const RotMatrix<dim>& m,
const Point<2>& p)
271 assert(m_origin.isValid());
273 if(!m_axes[0].isValid()) {
274 assert(p[0] == 0 && p[1] == 0);
278 Vector<dim> shift = m_axes[0] * p[0];
279 m_axes[0] =
Prod(m_axes[0], m);
281 if(m_axes[1].isValid()) {
282 shift += m_axes[1] * p[1];
283 m_axes[1] =
Prod(m_axes[1], m);
288 m_origin += shift -
Prod(shift, m);
292 inline void _Poly2Orient<3>::rotate(
const Quaternion& q,
const Point<3>& p)
294 m_origin.rotate(q, p);
296 for(
int j = 0; j < 2; ++j)
301 inline void _Poly2Orient<3>::rotate2(
const Quaternion& q,
const Point<2>& p)
303 assert(m_origin.isValid());
305 if(!m_axes[0].isValid()) {
306 assert(p[0] == 0 && p[1] == 0);
310 Vector<3> shift = m_axes[0] * p[0];
313 if(m_axes[1].isValid()) {
314 shift += m_axes[1] * p[1];
320 m_origin += shift - shift.rotate(q);
324 AxisBox<dim> Polygon<dim>::boundingBox()
const
326 assert(m_poly.numCorners() > 0);
328 Point<dim> min = m_orient.convert(m_poly[0]), max = min;
329 bool valid = min.isValid();
331 for(
size_t i = 1; i != m_poly.numCorners(); ++i) {
332 Point<dim> p = m_orient.convert(m_poly[i]);
333 valid = valid && p.isValid();
334 for(
int j = 0; j < dim; ++j) {
345 return AxisBox<dim>(min, max,
true);
349 inline Ball<dim> Polygon<dim>::boundingSphere()
const
351 Ball<2> b = m_poly.boundingSphere();
353 return Ball<dim>(m_orient.convert(b.center()), b.radius());
357 inline Ball<dim> Polygon<dim>::boundingSphereSloppy()
const
359 Ball<2> b = m_poly.boundingSphereSloppy();
361 return Ball<dim>(m_orient.convert(b.center()), b.radius());
366 #endif // WFMATH_POLYGON_FUNCS_H