6#include "point_array.h"
10template < prototype_number NUMBER >
17 using BASE_ARRAY = point_array_base < NUMBER >;
21 using UNIT_TYPE = NUMBER;
28 bool m_bDirtyBoundingRect;
29 ::rectangle_type < NUMBER > m_rectangleBounding;
33 polygon_base(
const polygon_base & polygon);
34 polygon_base(polygon_base&& polygon);
37 template < prototype_rectangle RECTANGLE >
38 polygon_base & operator = (
const RECTANGLE & rectangle)
41 m_rectangleBounding = rectangle;
45 this->element_at(0) = m_rectangleBounding.top_left();
46 this->element_at(1) = m_rectangleBounding.top_right();
47 this->element_at(2) = m_rectangleBounding.bottom_right();
48 this->element_at(3) = m_rectangleBounding.bottom_left();
51 m_bDirtyBoundingRect =
false;
58 void rotate(::f64 dAngle)
61 point_array_base < NUMBER >::rotate(dAngle);
62 m_bDirtyBoundingRect =
true;
67 void rotate(::f64 dAngle, ::point_type < UNIT_TYPE > pointCenter)
70 point_array_base < NUMBER >::rotate(dAngle, pointCenter);
72 m_bDirtyBoundingRect =
true;
84 m_bDirtyBoundingRect =
true;
90 const ::rectangle_type < NUMBER > & bounding_rect()
const;
92 bool overlaps(
const polygon_base & i32_polygon)
const;
94 polygon_base convex_intersection(
const polygon_base & polygon)
const;
99 bool bounding_rectangle_contains(const ::point_type < NUMBER > & point)
const;
101 bool contains(const ::point_type < NUMBER > & point)
const
104 return point_array_base < NUMBER >::polygon_contains_winding(point);
108 bool contains_alternate(const ::point_type < NUMBER > & point)
const
111 return point_array_base < NUMBER >::polygon_contains_alternate(point);
115 polygon_base& operator = (
const polygon_base& i32_polygon);
116 polygon_base& operator = (polygon_base&& i32_polygon);
123template < prototype_number NUMBER >
124inline polygon_base < NUMBER >::polygon_base(
const polygon_base& polygon) :
130template < prototype_number NUMBER >
131inline polygon_base < NUMBER >::polygon_base(
polygon_base&& polygon) :
132 point_array_base < NUMBER >(::transfer(polygon))
135 m_bDirty = polygon.m_bDirty;
136 m_bDirtyBoundingRect = polygon.m_bDirtyBoundingRect;
137 m_rectangleBounding = polygon.m_rectangleBounding;
141template < prototype_number NUMBER >
142inline bool polygon_base < NUMBER >::bounding_rectangle_contains(const ::point_type < NUMBER > & point)
const
145 return this->bounding_rect().contains(point);
150inline ::f64 atan(const ::f64_point & point, ::f64 x, ::f64 y)
153 return ::atan2(point.y - y, point.x - x);
159template < prototype_number NUMBER >
160void polygon_base < NUMBER >::sort()
166 for (
auto & point : *
this)
172 x /= this->get_count();
173 y /= this->get_count();
175 this->predicate_sort([x, y](
auto & point1,
auto & point2) {
return atan(point1, x, y) >= atan(point2, x, y); });
180template < prototype_number NUMBER >
181polygon_base < NUMBER > & polygon_base < NUMBER >::operator = (
const polygon_base& polygon)
184 if (&polygon !=
this)
187 point_array_base < NUMBER >::operator = (polygon);
188 m_bDirty = polygon.m_bDirty;
189 m_bDirtyBoundingRect = polygon.m_bDirtyBoundingRect;
190 m_rectangleBounding = polygon.m_rectangleBounding;
199template < prototype_number NUMBER >
200polygon_base < NUMBER > & polygon_base < NUMBER >::operator = (
polygon_base&& polygon)
203 if (&polygon !=
this)
206 point_array_base < NUMBER >::operator = (::transfer(polygon));
207 m_bDirty = polygon.m_bDirty;
208 m_bDirtyBoundingRect = polygon.m_bDirtyBoundingRect;
209 if(!m_bDirtyBoundingRect)
211 m_rectangleBounding = polygon.m_rectangleBounding;
221inline bool i32_lineersection(::f64_point & point, const ::f64_point & pt1, const ::f64_point & pt2, const ::f64_point & pt3, const ::f64_point & pt4);
227inline bool inBoundedBox(const ::f64_point & pt1, const ::f64_point & pt2, const ::f64_point & pt3)
235 if (!(pt1.x - dSpan <= pt3.x && pt3.x <= pt2.x + dSpan))
246 if (!(pt2.x - dSpan <= pt3.x && pt3.x <= pt1.x + dSpan))
258 if (!(pt1.y - dSpan <= pt3.y && pt3.y <= pt2.y + dSpan))
269 if (!(pt2.y - dSpan <= pt3.y && pt3.y <= pt1.y + dSpan))
282inline bool inBoundedBox1(const ::f64_point & pt1, const ::f64_point & pt2, const ::f64_point & pt3)
288 if (!(pt1.x <= pt3.x && pt3.x <= pt2.x))
299 if (!(pt2.x <= pt3.x && pt3.x <= pt1.x))
311 if (!(pt1.y <= pt3.y && pt3.y <= pt2.y))
322 if (!(pt2.y <= pt3.y && pt3.y <= pt1.y))
337inline bool i32_lineersection(::f64_point & point, const ::f64_point & pt1, const ::f64_point & pt2, const ::f64_point & pt3, const ::f64_point & pt4)
341 ::f64 A1 = pt2.x - pt1.x;
342 ::f64 B1 = pt1.y - pt2.y;
343 ::f64 C1 = A1 * pt1.y + B1 * pt1.x;
346 ::f64 A2 = pt4.x - pt3.x;
347 ::f64 B2 = pt3.y - pt4.y;
348 ::f64 C2 = A2 * pt3.y + B2 * pt3.x;
350 ::f64 determinant = A1 * B2 - A2 * B1;
352 if (determinant != 0.0)
355 point.y = (B2 * C1 - B1 * C2) / determinant;
357 point.x = (A1 * C2 - A2 * C1) / determinant;
359 return inBoundedBox(pt1, pt2, point) && inBoundedBox(pt3, pt4, point);
369inline void get_intersection_points(f64_point_array_base & pa, const ::f64_point & point1, const ::f64_point & point2,
const f64_point_array_base & paPolygon)
374 for (iptr i = 0; i < paPolygon.get_count(); i++)
377 if (i32_lineersection(point, point1, point2, i % paPolygon, (i + 1) % paPolygon))
389template < prototype_number NUMBER >
390polygon_base < NUMBER >::polygon_base()
395 m_bDirtyBoundingRect =
false;
400template < prototype_number NUMBER >
401polygon_base < NUMBER >::~polygon_base()
426template < prototype_number NUMBER >
427const ::rectangle_type < NUMBER > & polygon_base < NUMBER >::bounding_rect()
const
432 if (m_bDirtyBoundingRect && this->has_elements())
437 ((
polygon_base *)
this)->m_rectangleBounding.maximum_minimum();
458 return m_rectangleBounding;
463template < prototype_number NUMBER >
464bool polygon_base < NUMBER >::overlaps(
const polygon_base & polygon)
const
467 if (this->get_count() >= 3 && polygon.get_count() >= 3)
470 auto & r1 = bounding_rect();
472 auto & r2 = polygon.bounding_rect();
474 if (!r1.intersects(r2))
481 ::collection::count c1 = this->get_count();
483 ::collection::count c2 = polygon.get_count();
485 for (::i32 i = 0; i < c1; i++)
488 if (polygon.contains(this->element_at(i)))
497 for (::i32 i = 0; i < c2; i++)
500 if (this->contains(polygon[i]))
511 for (::i32 i = 0; i < c1; i++)
514 for (::i32 k = 0; k < c2; k++)
517 if (i32_lineersection(point, this->element_at(i), this->element_at((i + 1) % c1), polygon[k], polygon[(k + 1) % c2]))
535template < prototype_number NUMBER >
536polygon_base < NUMBER > polygon_base < NUMBER >::convex_intersection(
const polygon_base & polygon)
const
539 ::collection::count c1 = this->get_count();
541 ::collection::count c2 = polygon.get_count();
545 if (c1 >= 3 && c2 >= 3)
549 for (::i32 i = 0; i < c1; i++)
552 if (polygon.contains(this->element_at(i)))
561 for (::i32 i = 0; i < c2; i++)
564 if (this->contains(polygon[i]))
573 for (::i32 i = 0; i < this->get_count(); i++)
576 get_intersection_points(polygonResult, i % *
this, (i + 1) % *
this, polygon);
580 polygonResult.sort();
582 polygonResult.m_bDirty = polygonResult.has_elements();
586 return polygonResult;
591template < prototype_number NUMBER >
593 public ::pointer_array < ::array_particle < ::polygon_base < NUMBER > > >
598 using UNIT_TYPE = NUMBER;
601 using ::pointer_array < ::array_particle < ::polygon_base < NUMBER > > >
::pointer_array;
604 void expand_bounding_box(::point_type < UNIT_TYPE > & top_left, ::point_type < UNIT_TYPE > & bottom_right)
607 for(
auto & ppolygon : *
this)
610 ppolygon->expand_bounding_box(top_left, bottom_right);
Definition point_array.h:25
inline ::collection::index tolerance_add_unique(UNIT_TYPE tolerance, const ::point_type< NUMBER > &pointAdd)
Definition point_array.h:67
Definition pointer_array.h:1882