26 #ifndef WFMATH_POLYGON_H
27 #define WFMATH_POLYGON_H
29 #include <wfmath/const.h>
30 #include <wfmath/axisbox.h>
31 #include <wfmath/ball.h>
32 #include <wfmath/quaternion.h>
38 template<
int dim>
class Polygon;
41 std::ostream& operator<<(std::ostream& os,
const Polygon<dim>& r);
43 std::istream& operator>>(std::istream& is, Polygon<dim>& r);
57 friend std::ostream& operator<< <2>(std::ostream& os,
const Polygon& p);
58 friend std::istream&
operator>> <2>(std::istream& is,
Polygon& p);
70 bool operator==(
const Polygon& p)
const {
return isEqualTo(p);}
71 bool operator!=(
const Polygon& p)
const {
return !isEqualTo(p);}
77 size_t numCorners()
const {
return m_points.size();}
78 Point<2> getCorner(
size_t i)
const {
return m_points[i];}
79 Point<2> getCenter()
const {
return Barycenter(m_points);}
87 {m_points.insert(m_points.begin() + i, p);
return true;}
90 void removeCorner(
size_t i) {m_points.erase(m_points.begin() + i);}
94 {m_points[i] = p;
return true;}
97 void clear() {m_points.clear();}
99 const Point<2>& operator[](
size_t i)
const {
return m_points[i];}
100 Point<2>& operator[](
size_t i) {
return m_points[i];}
102 void resize(std::vector<Point<2> >::size_type size) {m_points.resize(size);}
106 Polygon& shift(
const Vector<2>& v);
107 Polygon& moveCornerTo(
const Point<2>& p,
size_t corner)
108 {
return shift(p - getCorner(corner));}
109 Polygon& moveCenterTo(
const Point<2>& p)
110 {
return shift(p - getCenter());}
112 Polygon& rotateCorner(
const RotMatrix<2>& m,
size_t corner)
113 {rotatePoint(m, getCorner(corner));
return *
this;}
114 Polygon& rotateCenter(
const RotMatrix<2>& m)
115 {rotatePoint(m, getCenter());
return *
this;}
116 Polygon& rotatePoint(
const RotMatrix<2>& m,
const Point<2>& p);
120 AxisBox<2> boundingBox()
const {
return BoundingBox(m_points);}
124 Polygon toParentCoords(
const Point<2>& origin,
125 const RotMatrix<2>& rotation = RotMatrix<2>().identity())
const;
126 Polygon toParentCoords(
const AxisBox<2>& coords)
const;
127 Polygon toParentCoords(
const RotBox<2>& coords)
const;
133 Polygon toLocalCoords(
const Point<2>& origin,
134 const RotMatrix<2>& rotation = RotMatrix<2>().identity())
const;
135 Polygon toLocalCoords(
const AxisBox<2>& coords)
const;
136 Polygon toLocalCoords(
const RotBox<2>& coords)
const;
138 friend bool Intersect<2>(
const Polygon& r,
const Point<2>& p,
bool proper);
139 friend bool Contains<2>(
const Point<2>& p,
const Polygon& r,
bool proper);
141 friend bool Intersect<2>(
const Polygon& p,
const AxisBox<2>& b,
bool proper);
142 friend bool Contains<2>(
const Polygon& p,
const AxisBox<2>& b,
bool proper);
143 friend bool Contains<2>(
const AxisBox<2>& b,
const Polygon& p,
bool proper);
145 friend bool Intersect<2>(
const Polygon& p,
const Ball<2>& b,
bool proper);
146 friend bool Contains<2>(
const Polygon& p,
const Ball<2>& b,
bool proper);
147 friend bool Contains<2>(
const Ball<2>& b,
const Polygon& p,
bool proper);
149 friend bool Intersect<2>(
const Polygon& p,
const Segment<2>& s,
bool proper);
150 friend bool Contains<2>(
const Polygon& p,
const Segment<2>& s,
bool proper);
151 friend bool Contains<2>(
const Segment<2>& s,
const Polygon& p,
bool proper);
153 friend bool Intersect<2>(
const Polygon& p,
const RotBox<2>& r,
bool proper);
154 friend bool Contains<2>(
const Polygon& p,
const RotBox<2>& r,
bool proper);
155 friend bool Contains<2>(
const RotBox<2>& r,
const Polygon& p,
bool proper);
157 friend bool Intersect<2>(
const Polygon& p1,
const Polygon& p2,
bool proper);
158 friend bool Contains<2>(
const Polygon& outer,
const Polygon& inner,
bool proper);
161 std::vector<Point<2> > m_points;
162 typedef std::vector<Point<2> >::iterator theIter;
163 typedef std::vector<Point<2> >::const_iterator theConstIter;
171 WFMATH_POLY2REORIENT_NONE,
172 WFMATH_POLY2REORIENT_CLEAR_AXIS2,
173 WFMATH_POLY2REORIENT_CLEAR_BOTH_AXES,
174 WFMATH_POLY2REORIENT_MOVE_AXIS2_TO_AXIS1,
175 WFMATH_POLY2REORIENT_SCALE1_CLEAR2
184 : m_type(type), m_scale(scale) {}
187 void reorient(
Polygon<2>& poly,
size_t skip = std::numeric_limits<size_t>::max())
const;
190 Poly2ReorientType m_type;
200 bool o1_is_line, o2_is_line;
218 ~Poly2Orient() =
default;
220 Poly2Orient& operator=(
const Poly2Orient& p) =
default;
223 Point<dim> convert(
const Point<2>& p)
const;
233 Poly2Reorient reduce(
const Polygon<2>& poly,
size_t skip = std::numeric_limits<size_t>::max());
235 void shift(
const Vector<dim>& v) {
if(m_origin.isValid()) m_origin += v;}
236 void rotate(
const RotMatrix<dim>& m,
const Point<dim>& p);
238 void rotate2(
const RotMatrix<dim>& m,
const Point<2>& p);
241 void rotate(
const Quaternion& q,
const Point<3>& p);
243 void rotate2(
const Quaternion& q,
const Point<2>& p);
245 Poly2Orient toParentCoords(
const Point<dim>& origin,
246 const RotMatrix<dim>& rotation = RotMatrix<dim>().identity())
const
247 {Poly2Orient p(*
this); p.m_origin = m_origin.toParentCoords(origin, rotation);
248 p.m_axes[0].rotate(rotation); p.m_axes[1].rotate(rotation);
return p;}
249 Poly2Orient toParentCoords(
const AxisBox<dim>& coords)
const
250 {Poly2Orient p(*
this); p.m_origin = m_origin.toParentCoords(coords);
return p;}
251 Poly2Orient toParentCoords(
const RotBox<dim>& coords)
const
252 {Poly2Orient p(*
this); p.m_origin = m_origin.toParentCoords(coords);
253 p.m_axes[0].rotate(coords.orientation());
254 p.m_axes[1].rotate(coords.orientation());
return p;}
260 Poly2Orient toLocalCoords(
const Point<dim>& origin,
261 const RotMatrix<dim>& rotation = RotMatrix<dim>().identity())
const
262 {Poly2Orient p(*
this); p.m_origin = m_origin.toLocalCoords(origin, rotation);
263 p.m_axes[0] = rotation * p.m_axes[0];
264 p.m_axes[1] = rotation * p.m_axes[1];
return p;}
265 Poly2Orient toLocalCoords(
const AxisBox<dim>& coords)
const
266 {Poly2Orient p(*
this); p.m_origin = m_origin.toLocalCoords(coords);
return p;}
267 Poly2Orient toLocalCoords(
const RotBox<dim>& coords)
const
268 {Poly2Orient p(*
this); p.m_origin = m_origin.toLocalCoords(coords);
269 p.m_axes[0] = coords.orientation() * p.m_axes[0];
270 p.m_axes[1] = coords.orientation() * p.m_axes[1];
return p;}
273 Poly2Orient<3> toParentCoords(
const Point<3>& origin,
const Quaternion& rotation)
const
274 {Poly2Orient p(*
this); p.m_origin = m_origin.toParentCoords(origin, rotation);
275 p.m_axes[0].rotate(rotation); p.m_axes[0].rotate(rotation);
return p;}
276 Poly2Orient<3> toLocalCoords(
const Point<3>& origin,
const Quaternion& rotation)
const
277 {Poly2Orient p(*
this); p.m_origin = m_origin.toLocalCoords(origin, rotation);
278 p.m_axes[0].rotate(rotation.inverse());
279 p.m_axes[0].rotate(rotation.inverse());
return p;}
283 Vector<dim> offset(
const Point<dim>& pd, Point<2>& p2)
const;
286 bool checkContained(
const Point<dim>& pd, Point<2> & p2)
const;
290 bool checkIntersect(
const AxisBox<dim>& b, Point<2>& p2,
bool proper)
const;
292 friend int Intersect<dim>(
const Poly2Orient<dim> &,
const Poly2Orient<dim> &,
293 Poly2OrientIntersectData &);
297 bool checkIntersectPlane(
const AxisBox<dim>& b, Point<2>& p2,
bool proper)
const;
300 Vector<dim> m_axes[2];
304 template<
int dim = 3>
308 Polygon() : m_orient(), m_poly() {}
309 Polygon(
const Polygon& p) : m_orient(p.m_orient), m_poly(p.m_poly) {}
311 ~Polygon() =
default;
313 friend std::ostream& operator<< <dim>(std::ostream& os,
const Polygon& p);
314 friend std::istream&
operator>> <dim>(std::istream& is, Polygon& p);
316 Polygon& operator=(
const Polygon& p)
317 {m_orient = p.m_orient; m_poly = p.m_poly;
return *
this;}
321 bool operator==(
const Polygon& p)
const {
return isEqualTo(p);}
322 bool operator!=(
const Polygon& p)
const {
return !isEqualTo(p);}
324 bool isValid()
const {
return m_poly.isValid();}
328 size_t numCorners()
const {
return m_poly.numCorners();}
329 Point<dim> getCorner(
size_t i)
const {
return m_orient.convert(m_poly[i]);}
330 Point<dim> getCenter()
const {
return m_orient.convert(m_poly.getCenter());}
340 void removeCorner(
size_t i);
349 void clear() {m_poly.clear(); m_orient = Poly2Orient<dim>();}
353 Polygon& shift(
const Vector<dim>& v)
354 {m_orient.shift(v);
return *
this;}
355 Polygon& moveCornerTo(
const Point<dim>& p,
size_t corner)
356 {
return shift(p - getCorner(corner));}
357 Polygon& moveCenterTo(
const Point<dim>& p)
358 {
return shift(p - getCenter());}
360 Polygon& rotateCorner(
const RotMatrix<dim>& m,
size_t corner)
361 {m_orient.rotate2(m, m_poly[corner]);
return *
this;}
362 Polygon& rotateCenter(
const RotMatrix<dim>& m)
363 {
if(m_poly.numCorners() > 0)
364 m_orient.rotate2(m, m_poly.getCenter());
366 Polygon& rotatePoint(
const RotMatrix<dim>& m,
const Point<dim>& p)
367 {m_orient.rotate(m, p);
return *
this;}
370 Polygon<3>& rotateCorner(
const Quaternion& q,
size_t corner)
371 {m_orient.rotate2(q, m_poly[corner]);
return *
this;}
372 Polygon<3>& rotateCenter(
const Quaternion& q)
373 {
if(m_poly.numCorners() > 0)
374 m_orient.rotate2(q, m_poly.getCenter());
376 Polygon<3>& rotatePoint(
const Quaternion& q,
const Point<3>& p)
377 {m_orient.rotate(q, p);
return *
this;}
381 AxisBox<dim> boundingBox()
const;
382 Ball<dim> boundingSphere()
const;
383 Ball<dim> boundingSphereSloppy()
const;
385 Polygon toParentCoords(
const Point<dim>& origin,
386 const RotMatrix<dim>& rotation = RotMatrix<dim>().identity())
const
387 {Polygon p(*
this); p.m_orient = m_orient.toParentCoords(origin, rotation);
return p;}
388 Polygon toParentCoords(
const AxisBox<dim>& coords)
const
389 {Polygon p(*
this); p.m_orient = m_orient.toParentCoords(coords);
return p;}
390 Polygon toParentCoords(
const RotBox<dim>& coords)
const
391 {Polygon p(*
this); p.m_orient = m_orient.toParentCoords(coords);
return p;}
397 Polygon toLocalCoords(
const Point<dim>& origin,
398 const RotMatrix<dim>& rotation = RotMatrix<dim>().identity())
const
399 {Polygon p(*
this); p.m_orient = m_orient.toLocalCoords(origin, rotation);
return p;}
400 Polygon toLocalCoords(
const AxisBox<dim>& coords)
const
401 {Polygon p(*
this); p.m_orient = m_orient.toLocalCoords(coords);
return p;}
402 Polygon toLocalCoords(
const RotBox<dim>& coords)
const
403 {Polygon p(*
this); p.m_orient = m_orient.toLocalCoords(coords);
return p;}
406 Polygon<3> toParentCoords(
const Point<3>& origin,
const Quaternion& rotation)
const
407 {Polygon<3> p(*
this); p.m_orient = m_orient.toParentCoords(origin, rotation);
return p;}
408 Polygon<3> toLocalCoords(
const Point<3>& origin,
const Quaternion& rotation)
const
409 {Polygon<3> p(*
this); p.m_orient = m_orient.toLocalCoords(origin, rotation);
return p;}
411 friend bool Intersect<dim>(
const Polygon& r,
const Point<dim>& p,
bool proper);
412 friend bool Contains<dim>(
const Point<dim>& p,
const Polygon& r,
bool proper);
414 friend bool Intersect<dim>(
const Polygon& p,
const AxisBox<dim>& b,
bool proper);
415 friend bool Contains<dim>(
const Polygon& p,
const AxisBox<dim>& b,
bool proper);
416 friend bool Contains<dim>(
const AxisBox<dim>& b,
const Polygon& p,
bool proper);
418 friend bool Intersect<dim>(
const Polygon& p,
const Ball<dim>& b,
bool proper);
419 friend bool Contains<dim>(
const Polygon& p,
const Ball<dim>& b,
bool proper);
420 friend bool Contains<dim>(
const Ball<dim>& b,
const Polygon& p,
bool proper);
422 friend bool Intersect<dim>(
const Polygon& p,
const Segment<dim>& s,
bool proper);
423 friend bool Contains<dim>(
const Polygon& p,
const Segment<dim>& s,
bool proper);
424 friend bool Contains<dim>(
const Segment<dim>& s,
const Polygon& p,
bool proper);
426 friend bool Intersect<dim>(
const Polygon& p,
const RotBox<dim>& r,
bool proper);
427 friend bool Contains<dim>(
const Polygon& p,
const RotBox<dim>& r,
bool proper);
428 friend bool Contains<dim>(
const RotBox<dim>& r,
const Polygon& p,
bool proper);
430 friend bool Intersect<dim>(
const Polygon& p1,
const Polygon& p2,
bool proper);
431 friend bool Contains<dim>(
const Polygon& outer,
const Polygon& inner,
bool proper);
435 Poly2Orient<dim> m_orient;
440 inline bool Polygon<dim>::addCorner(
size_t i,
const Point<dim>& p,
CoordType epsilon)
443 bool succ = m_orient.expand(p, p2, epsilon);
445 m_poly.addCorner(i, p2, epsilon);
450 inline void Polygon<dim>::removeCorner(
size_t i)
452 m_poly.removeCorner(i);
453 Poly2Reorient r = m_orient.reduce(m_poly);
458 inline bool Polygon<dim>::moveCorner(
size_t i,
const Point<dim>& p,
CoordType epsilon)
460 Poly2Orient<dim> try_orient = m_orient;
461 Poly2Reorient r = try_orient.reduce(m_poly, i);
464 if(!try_orient.expand(p, p2, epsilon))
467 r.reorient(m_poly, i);
469 m_orient = try_orient;
476 #endif // WFMATH_POLYGON_H