16inline bool tolerance_is_equal(::f64 tolerance, ::f64 d1, ::f64 d2)
18 return ::abs(d1 - d2) <= tolerance;
22template < prototype_number NUMBER >
24 public ::array_base < ::point_type < NUMBER > >
29 using BASE_ARRAY = ::array_base < ::point_type < NUMBER > >;
31 using UNIT_TYPE = NUMBER;
36 using BASE_ARRAY::BASE_ARRAY;
37 using BASE_ARRAY::operator =;
49 void offset(UNIT_TYPE x, UNIT_TYPE y);
50 void offset(::point_type < UNIT_TYPE > point) { offset(point.x, point.y); }
52 void rotate(::f64 dAngle);
54 void rotate(::f64 dAngle, ::point_type < UNIT_TYPE > pointCenter);
56 void expand_bounding_box(::point_type < UNIT_TYPE > & top_left, ::point_type < UNIT_TYPE > & bottom_right)
const;
58 bool get_bounding_box(::point_type < UNIT_TYPE > & top_left, ::point_type < UNIT_TYPE > & bottom_right)
const;
60 bool polygon_contains_winding(const ::point_type < UNIT_TYPE > & point)
const;
61 bool polygon_contains_alternate(const ::point_type < UNIT_TYPE > & point)
const;
63 inline ::collection::index add(UNIT_TYPE x, UNIT_TYPE y) { return ::array_base < ::point_type < NUMBER > >::add({x, y}); }
64 inline ::collection::index add(const ::point_type < NUMBER > & point) { return ::array_base < ::point_type < NUMBER > >::add(point); }
67 inline ::collection::index
tolerance_add_unique(UNIT_TYPE tolerance, const ::point_type < NUMBER > & pointAdd)
70 for (
auto & point : *
this)
73 if (tolerance_is_equal(tolerance, point.x, pointAdd.x) && tolerance_is_equal(tolerance, point.y, pointAdd.y))
85 return ::array_base < ::point_type < NUMBER > >::add(pointAdd);
93 ::collection::count add_unique_range(const ::point_type < NUMBER > & pBeg, const ::point_type < NUMBER > & pointEnd, const ::size_type < NUMBER > & s = e_unit_size);
97 UNIT_TYPE polygon_area()
100 UNIT_TYPE area = (UNIT_TYPE) 0;
102 ::i32 n = (::i32) this->get_count();
107 for (::i32 i = 0; i < n; i++)
110 area += (this->element_at(j).x + this->element_at(i).x)
111 * (this->element_at(j).y - this->element_at(i).y);
122 auto points_beyond_right(UNIT_TYPE x)
const
125 return ::transfer(container_predicate_get(*
this, [x](const ::point_type < NUMBER > & p) {
return p.x > x; }));
130 auto points_beyond_left(UNIT_TYPE x)
const
133 return ::transfer(container_predicate_get(*
this, [x](const ::point_type < NUMBER > & p) {
return p.x < x; }));
138 auto points_beyond_top(UNIT_TYPE y)
const
141 return ::transfer(container_predicate_get(*
this, [y](const ::point_type < NUMBER > & p) {
return p.y < y; }));
146 auto points_beyond_bottom(UNIT_TYPE y)
const
149 return ::transfer(container_predicate_get(*
this, [y](const ::point_type < NUMBER > & p) {
return p.y > y; }));
154 auto points_beyond_right()
const
157 return this->points_beyond_right(this->first().x);
162 auto points_beyond_left()
const
165 return this->points_beyond_left(this->first().x);
170 auto points_beyond_top()
const
173 return this->points_beyond_top(this->first().y);
178 auto points_beyond_bottom()
const
181 return this->points_beyond_bottom(this->first().y);
192template < prototype_number NUMBER >
193void point_array_base < NUMBER >::offset(UNIT_TYPE x, UNIT_TYPE y)
195 for (::i32 i = 0; i < this->get_size(); i++)
197 this->element_at(i).x += x;
198 this->element_at(i).y += y;
203template < prototype_number NUMBER >
204void point_array_base < NUMBER >::rotate(::f64 dAngle)
209 ::f64 dCos = ::cos(dAngle);
210 ::f64 dSin = ::sin(dAngle);
212 for (::i32 i = 0; i < this->get_count(); i++)
214 x = this->element_at(i).x;
215 y = this->element_at(i).y;
216 this->element_at(i).x = (::i32)(x * dCos - y * dSin);
217 this->element_at(i).y = (::i32)(x * dSin + y * dCos);
236template < prototype_number NUMBER >
237void point_array_base < NUMBER >::rotate(::f64 dAngle, ::point_type < NUMBER > pointCenter)
242 ::f64 dCos = cos(dAngle);
243 ::f64 dSin = sin(dAngle);
245 for (::i32 i = 0; i < this->get_count(); i++)
247 this->element_at(i) -= pointCenter;
248 x = this->element_at(i).x;
249 y = this->element_at(i).y;
250 this->element_at(i).x = (::i32)(x * dCos - y * dSin);
251 this->element_at(i).y = (::i32)(x * dSin + y * dCos);
252 this->element_at(i) += pointCenter;
291template < prototype_number NUMBER >
292bool point_array_base < NUMBER >::polygon_contains_winding(const ::point_type < NUMBER > & point)
const
295 return ::polygon_contains_winding( this->data(), (::i32)this->size(), point);
300template < prototype_number NUMBER >
301bool point_array_base < NUMBER >::polygon_contains_alternate(const ::point_type < NUMBER > & point)
const
304 return ::polygon_contains_alternate(this->data(), (::i32)this->size(), point,
true);
309template < prototype_number NUMBER >
310::collection::count point_array_base < NUMBER >::add_unique_range(const ::point_type < NUMBER > & pointBeg, const ::point_type < NUMBER > & pointEnd, const ::size_type < NUMBER > & size)
313 auto x1 = pointBeg.x;
315 auto x2 = pointEnd.x;
317 auto y1 = pointBeg.y;
319 auto y2 = pointEnd.y;
325 ::collection::count c = 0;
327 for (
auto x = x1; x <= x2; x += size.cx)
330 for (
auto y = y1; y <= y2; y += size.cy)
333 if (this->add_unique(POINT_TYPE(x, y)))
349template < prototype_number NUMBER >
350void point_array_base < NUMBER >::expand_bounding_box(::point_type < UNIT_TYPE > & top_left, ::point_type < UNIT_TYPE > & bottom_right)
const
353 ::point_type < NUMBER > ::expand_bounding_box(top_left, bottom_right, this->data(), this->size());
358template < prototype_number NUMBER >
359bool point_array_base < NUMBER >::get_bounding_box(::point_type < UNIT_TYPE > & top_left, ::point_type < UNIT_TYPE > & bottom_right)
const
369 top_left = this->first();
371 bottom_right = this->first();
373 this->expand_bounding_box(top_left, bottom_right, this->element_at[1], this->count() - 1);
Definition point_array.h:25
inline ::collection::index tolerance_add_unique(UNIT_TYPE tolerance, const ::point_type< NUMBER > &pointAdd)
Definition point_array.h:67