Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
polygon.H
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
31
84# ifndef POLYGON_H
85# define POLYGON_H
86
87# include <dlink.H>
88# include <point.H>
89# include <ah-errors.H>
90# include <ah-dry.H>
91# include <ahDry.H>
92# include <ah-iterator.H>
93# include <string>
94# include <utility>
95
96namespace Aleph
97{
98 using Aleph::Dlink;
99
118 class Vertex : public Point, public Dlink
119 {
120 public:
122 Vertex() = default;
123
126 Vertex(const Point & point) : Point(point)
127 { /* empty */
128 }
129
133 Vertex(const Vertex & vertex) : Point(vertex), Dlink()
134 { /* empty */
135 }
136
141 Vertex &operator=(const Vertex & vertex)
142 {
143 if (this != &vertex)
144 Point::operator=(vertex);
145 return *this;
146 }
147
151 {
152 return static_cast<const Point>(*this);
153 }
154
160 {
161 return static_cast<Vertex *>(link);
162 }
163
167 [[nodiscard]] static const Vertex * dlink_to_vertex(const Dlink *link)
168 {
169 return static_cast<const Vertex *>(link);
170 }
171
176 [[nodiscard]] const Vertex &prev_vertex() const
177 {
178 assert(not this->is_empty());
179
180 ah_domain_error_if(this->is_unitarian()) << "There is an only vertex";
181
182 return *dlink_to_vertex(this->get_prev());
183 }
184
189 [[nodiscard]] const Vertex &next_vertex() const
190 {
191 assert(not this->is_empty());
192
193 ah_domain_error_if(this->is_unitarian()) << "There is an only vertex";
194
195 return *dlink_to_vertex(this->get_next());
196 }
197
198 // TODO: Implement next_segment() and prev_segment() methods
199 };
200
201
202 class Regular_Polygon;
203
241 class Polygon : public Geom_Object,
242 public GenericTraverse<Polygon>,
243 public FunctionalMethods<Polygon, Point>,
244 public LocateFunctions<Polygon, Point>,
245 public StlAlephIterator<Polygon>
246 {
248 size_t num_vertex_;
250
255
258 void update_extreme_points(const Point & point)
259 {
260 if (num_vertex_ == 0)
261 {
262 leftmost_ = rightmost_ = lowest_ = highest_ = point;
263 return;
264 }
265
266 if (point.get_x() < leftmost_.get_x())
267 leftmost_ = point;
268
269 if (point.get_x() > rightmost_.get_x())
270 rightmost_ = point;
271
272 if (point.get_y() < lowest_.get_y())
273 lowest_ = point;
274
275 if (point.get_y() > highest_.get_y())
276 highest_ = point;
277 }
278
281 {
282 while (not vertex_list_.is_empty())
284
285 num_vertex_ = 0;
286 is_closed_ = false;
287 }
288
291 void copy_points(const Polygon & poly)
292 {
293 auto *list = const_cast<Dlink *>(&poly.vertex_list_);
294
295 for (Dlink::Iterator it(list); it.has_curr(); it.next_ne())
297 }
298
301 void copy_regular_polygon(const Regular_Polygon & poly);
302
303 public:
306
309
317 {
319
320 public:
322
325
326 [[nodiscard]] bool has_curr() const noexcept { return dit_.has_curr(); }
327
328 void next() { dit_.next(); }
329
331
332 void prev() { dit_.prev(); }
333
335
337
338 void end() noexcept { dit_.end(); }
339
340 [[nodiscard]] const Point &get_curr() const
341 {
343 }
344
346 {
347 return dit_.get_curr_ne();
348 }
349
350 [[nodiscard]] bool operator==(const Iterator & o) const noexcept
351 {
352 return dit_ == o.dit_;
353 }
354
355 [[nodiscard]] bool operator!=(const Iterator & o) const noexcept
356 {
357 return dit_ != o.dit_;
358 }
359 };
360
363 { /* empty */
364 }
365
368 {
370 }
371
374 Polygon(const Polygon & poly)
375 : Geom_Object(poly),
377 lowest_(poly.lowest_), highest_(poly.highest_),
379 {
380 copy_points(poly);
381 }
382
386 : Polygon()
387 {
388 vertex_list_.swap(poly.vertex_list_);
389 std::swap(num_vertex_, poly.num_vertex_);
390 std::swap(is_closed_, poly.is_closed_);
391 std::swap(lowest_, poly.lowest_);
392 std::swap(highest_, poly.highest_);
393 std::swap(leftmost_, poly.leftmost_);
394 std::swap(rightmost_, poly.rightmost_);
395 }
396
402 {
404 }
405
410 {
411 if (this == &poly)
412 return *this;
413
415
417 is_closed_ = poly.is_closed_;
418 lowest_ = poly.lowest_;
419 highest_ = poly.highest_;
420 leftmost_ = poly.leftmost_;
421 rightmost_ = poly.rightmost_;
422
423 copy_points(poly);
424
425 return *this;
426 }
427
431 Polygon &operator =(Polygon && poly) noexcept
432 {
433 vertex_list_.swap(poly.vertex_list_);
434 std::swap(num_vertex_, poly.num_vertex_);
435 std::swap(is_closed_, poly.is_closed_);
436 std::swap(lowest_, poly.lowest_);
437 std::swap(highest_, poly.highest_);
438 std::swap(leftmost_, poly.leftmost_);
439 std::swap(rightmost_, poly.rightmost_);
440
441 return *this;
442 }
443
448 {
451
452 return *this;
453 }
454
457 [[nodiscard]] const Point &lowest_point() const { return lowest_; }
458
461 [[nodiscard]] const Point &highest_point() const { return highest_; }
462
465 [[nodiscard]] const Point &leftmost_point() const { return leftmost_; }
466
469 [[nodiscard]] const Point &rightmost_point() const { return rightmost_; }
470
473 [[nodiscard]] const bool &is_closed() const { return is_closed_; }
474
477 [[nodiscard]] const size_t &size() const { return num_vertex_; }
478
489 {
494 {
495 ah_domain_error_if(poly.vertex_list_.is_empty()) << "Polygon has not any vertex";
496 }
497
501 {
503 }
504 };
505
520 {
522
523 public:
529 {
531 << "Polygon has less than two vertex";
532 }
533
537 [[nodiscard]] bool has_curr() const
538 {
539 if (this->is_in_last())
540 return poly_.is_closed() ? true : false;
541
543 }
544
549 {
551 << "Segment iterator is in the last point and it is not closed";
552
553 const Vertex *src = Vertex::dlink_to_vertex(this->get_curr());
554
555 // Determine target: if at last vertex, wrap to first; otherwise, next
556 const Vertex & tgt =
557 this->is_in_last() ? poly_.get_first_vertex() : src->next_vertex();
558
559 return {src->to_point(), tgt.to_point()};
560 }
561 };
562
566 [[nodiscard]] bool vertex_belong_polygon(const Vertex & v) const
567 {
568 for (Vertex_Iterator it(*this); it.has_curr(); it.next_ne())
569 if (&it.get_current_vertex() == &v)
570 return true;
571
572 return false;
573 }
574
579 {
580 ah_domain_error_if(vertex_list_.is_empty()) << "Polygon has not any vertex";
581
583 }
584
589 {
590 ah_domain_error_if(vertex_list_.is_empty()) << "Polygon has not any vertex";
591
593 }
594
601 [[nodiscard]] const Vertex &get_next_vertex(const Vertex & v) const
602 {
603 // If v is the last vertex (next points to sentinel), wrap to the first vertex
604 return v.get_next() == &vertex_list_ ?
606 v.next_vertex();
607 }
608
615 [[nodiscard]] const Vertex &get_prev_vertex(const Vertex & v) const
616 {
617 // If v is the first vertex (prev points to sentinel), wrap to last vertex
618 return v.get_prev() == &vertex_list_ ?
620 v.prev_vertex();
621 }
622
627 {
629 << "polygon has less than two vertex";
630
632
633 return {first_vertex.to_point(), first_vertex.next_vertex().to_point()};
634 }
635
640 {
642 << "polygon has less than two vertex";
643
645
646 return {last_vertex.prev_vertex().to_point(), last_vertex.to_point()};
647 }
648
652 [[nodiscard]] bool intersects_with(const Segment & sg) const
653 {
654 // Traverse all edges and check for intersection
655 for (Segment_Iterator it(*this); it.has_curr(); it.next_ne())
656 if (const Segment & curr_side = it.get_current_segment(); curr_side.intersects_with(sg))
657 return true;
658
659 return false;
660 }
661
677 void add_vertex(const Point & point)
678 {
679 ah_domain_error_if(is_closed_) << "Polygon is already closed";
680
681 // Check if the new point is colinear with the last segment
682 if (num_vertex_ > 1)
684 {
686 << "new vertex is inside of last polygon's segment";
687
688 // Colinear point: replace the last vertex with this new one
689 auto & last_vertex = const_cast<Vertex &>(get_last_vertex());
690 Point old_point = last_vertex.to_point(); // Store old point before replacing
692 last_point = point;
693
694 // Recalculate extremes if the old point was an extreme point
697
698 if (was_extreme)
699 {
700 // We need a full recalculation of extremes
702
703 for (Vertex_Iterator it(*this); it.has_curr(); it.next_ne())
704 {
705 const Point p = it.get_current_vertex().to_point();
706
707 if (p.get_x() < leftmost_.get_x())
708 leftmost_ = p;
709 if (p.get_x() > rightmost_.get_x())
710 rightmost_ = p;
711 if (p.get_y() < lowest_.get_y())
712 lowest_ = p;
713 if (p.get_y() > highest_.get_y())
714 highest_ = p;
715 }
716 }
717 else
718 {
719 // Just check if the new point is an extreme
721 }
722
723 return;
724 }
725
726 // If we have at least 3 vertices, verify no self-intersection
727 if (num_vertex_ >= 3)
728 {
729 // New edge that would be formed by adding this point
730 const Segment new_side(get_last_vertex().to_point(), point);
731
732 // Check for intersection with all edges except the last one
733 // (which shares a vertex with the new edge)
734 for (Segment_Iterator it(*this); true; it.next_ne())
735 {
736 const Segment curr_side = it.get_current_segment();
737
739 break;
740
741 ah_domain_error_if(curr_side.intersects_with(new_side)) << "new side intersects";
742 }
743 }
744
745 // Insert new vertex
746 vertex_list_.append(new Vertex(point));
748 ++num_vertex_;
749 }
750
756 void add_vertex(const Geom_Number & x, const Geom_Number & y)
757 {
758 add_vertex(Point(x, y));
759 }
760
764 void append(const Point & point) { add_vertex(point); }
765
767
777 void remove_vertex(const Vertex & v)
778 {
779 Vertex *victim = nullptr;
780 for (Vertex_Iterator it(*this); it.has_curr(); it.next_ne())
781 if (&it.get_current_vertex() == &v)
782 {
783 victim = &const_cast<Vertex &>(it.get_current_vertex());
784 break;
785 }
786
787 ah_domain_error_if(victim == nullptr) << "Vertex does not belong to polygon";
788
789 // Store point for later comparison with extremes
790 const Point victim_point = victim->to_point();
791
792 // Delete the vertex
793 victim->del();
794 --num_vertex_;
795 delete victim;
796
797 // Recalculate extremes if needed
800 {
801 if (num_vertex_ == 0)
802 // No vertices left, reset extremes
804 else
805 {
806 // Recalculate extremes from remaining vertices
809
810 for (Vertex_Iterator it(*this); it.has_curr(); it.next_ne())
811 {
812 const Point point = it.get_current_vertex().to_point();
813 if (point.get_x() < leftmost_.get_x())
814 leftmost_ = point;
815 if (point.get_x() > rightmost_.get_x())
816 rightmost_ = point;
817 if (point.get_y() < lowest_.get_y())
818 lowest_ = point;
819 if (point.get_y() > highest_.get_y())
820 highest_ = point;
821 }
822 }
823 }
824
825 // Reset the closed state if the polygon now has fewer than 3 vertices
826 if (is_closed_ && num_vertex_ < 3)
827 is_closed_ = false;
828 }
829
840 void close()
841 {
842 ah_domain_error_if(is_closed_) << "Polygon is already closed";
844 << "Polygon needs at least 3 vertices to close (has " << num_vertex_ << ")";
845
846 if (num_vertex_ >= 4)
847 {
848 // Check for intersection with all edges except the first
849 // and last (which share endpoints with the closing edge)
850 const Segment last_side(get_first_vertex().to_point(), get_last_vertex().to_point());
851
852 Segment_Iterator it(*this);
853
854 for (it.next(); true; it.next_ne())
855 {
857
859 break;
860
861 ah_domain_error_if(curr_side.intersects_with(last_side))
862 << "closing causes an intersection";
863 }
864 }
865
866 is_closed_ = true;
867 }
868
869 enum class PointLocation
870 {
871 Outside,
872 Boundary,
873 Inside
874 };
875
885 {
886 ah_domain_error_if(not is_closed_) << "Polygon is not closed";
887
888 int winding = 0;
889
890 for (Segment_Iterator it(*this); it.has_curr(); it.next_ne())
891 {
892 const Segment edge = it.get_current_segment();
893 const Point & a = edge.get_src_point();
894 const Point & b = edge.get_tgt_point();
895
896 if (on_segment(edge, p))
898
899 if (a.get_y() <= p.get_y())
900 {
901 if (b.get_y() > p.get_y() and
902 orientation(a, b, p) == Orientation::CCW)
903 ++winding;
904 }
905 else
906 {
907 if (b.get_y() <= p.get_y() and
908 orientation(a, b, p) == Orientation::CW)
909 --winding;
910 }
911 }
912
914 }
915
926 [[nodiscard]] bool contains(const Point & p) const
927 {
929 }
930
932 [[deprecated("Use contains() instead")]]
933 [[nodiscard]] bool contains_to(const Point & p) const { return contains(p); }
934
944 {
945 ah_domain_error_if(num_vertex_ < 3) << "Polygon must have at least 3 vertices";
946
947 Geom_Number sum = 0;
948 for (Segment_Iterator it(*this); it.has_curr(); it.next_ne())
949 {
950 const Segment seg = it.get_current_segment();
951 const Point & a = seg.get_src_point();
952 const Point & b = seg.get_tgt_point();
953 sum += a.get_x() * b.get_y() - a.get_y() * b.get_x();
954 }
955 return sum / 2;
956 }
957
964 {
966 return a < 0 ? Geom_Number(-a) : a;
967 }
968
977 {
978 ah_domain_error_if(num_vertex_ < 2) << "Polygon must have at least 2 vertices";
979
980 Geom_Number sum = 0;
981 for (Segment_Iterator it(*this); it.has_curr(); it.next_ne())
982 sum += it.get_current_segment().length();
983 return sum;
984 }
985
994 {
995 ah_domain_error_if(num_vertex_ < 3) << "Polygon must have at least 3 vertices";
996
997 Geom_Number cx = 0, cy = 0, a6 = 0;
998 for (Segment_Iterator it(*this); it.has_curr(); it.next_ne())
999 {
1000 const Segment seg = it.get_current_segment();
1001 const Point & p = seg.get_src_point();
1002 const Point & q = seg.get_tgt_point();
1003 const Geom_Number cross = p.get_x() * q.get_y() - q.get_x() * p.get_y();
1004 cx += (p.get_x() + q.get_x()) * cross;
1005 cy += (p.get_y() + q.get_y()) * cross;
1006 a6 += cross;
1007 }
1008
1009 ah_domain_error_if(a6 == 0) << "Polygon has zero area";
1010 return {cx / (3 * a6), cy / (3 * a6)};
1011 }
1012
1021 [[nodiscard]] bool is_convex() const
1022 {
1023 ah_domain_error_if(num_vertex_ < 3) << "Polygon must have at least 3 vertices";
1024
1025 // Check turn direction at each vertex using segment iterator
1026 int sign = 0;
1027 Segment_Iterator it(*this);
1029 it.next_ne();
1030
1031 while (it.has_curr())
1032 {
1034 // Turn at the shared vertex (prev_seg.tgt == curr_seg.src)
1036 prev_seg.get_src_point(), prev_seg.get_tgt_point(),
1037 curr_seg.get_tgt_point());
1038
1039 if (turn != 0)
1040 {
1041 const int curr_sign = turn > 0 ? 1 : -1;
1042 if (sign == 0)
1043 sign = curr_sign;
1044 else if (sign != curr_sign)
1045 return false;
1046 }
1047
1049 it.next_ne();
1050 }
1051
1052 // Check the wrap-around turn (last vertex to first)
1055 prev_seg.get_src_point(), prev_seg.get_tgt_point(),
1056 first_seg.get_tgt_point());
1057
1058 if (turn != 0)
1059 if (const int curr_sign = turn > 0 ? 1 : -1; sign != 0 and sign != curr_sign)
1060 return false;
1061
1062 return true;
1063 }
1064
1073 {
1074 add_vertex(tr.get_p1());
1075 add_vertex(tr.get_p2());
1076 add_vertex(tr.get_p3());
1077
1078 close();
1079 }
1080 };
1081
1082
1132 {
1134 double side_size_;
1136 double angle_;
1137 double r_;
1138 double beta_;
1139
1140 public:
1143 { /* empty */
1144 }
1145
1155 const double & side_sz,
1156 const size_t & n,
1157 const double & ang = 0)
1158 : center_(std::move(c)), side_size_(side_sz), num_vertex_(n), angle_(ang), beta_(2 * PI / n)
1159 {
1160 ah_domain_error_if(n < 3) << "Polygon sides is less than 3";
1161
1162 // Calculate radius using law of sines with angles between vertices
1163 // and the angle between radius and side
1164 const double alpha = (PI - beta_) / 2; // angle between radius and side
1165 r_ = side_size_ * sin(alpha) / sin(beta_);
1166 }
1167
1170 [[nodiscard]] const double &get_side_size() const { return side_size_; }
1171
1174 [[nodiscard]] const Point &get_center() const { return center_; }
1175
1178 [[nodiscard]] const size_t &size() const { return num_vertex_; }
1179
1182 [[nodiscard]] const double &radius() const { return r_; }
1183
1186 static bool is_closed() { return true; }
1187
1197 [[nodiscard]] Point get_vertex(const size_t & i) const
1198 {
1200 << "vertex " << i << " is greater than " << num_vertex_;
1201
1202 // The first segment is the negative vertical from center
1203 // Initial point is the target of this segment with origin at center
1204 Segment sg(center_, center_ - Point(0, r_));
1205
1206 sg.rotate(i * beta_ + angle_);
1207
1208 return sg.get_tgt_point();
1209 }
1210
1213 [[nodiscard]] Point get_first_vertex() const { return get_vertex(0); }
1214
1218
1222 {
1223 return {get_vertex(0), get_vertex(1)};
1224 }
1225
1229 {
1230 return {get_vertex(num_vertex_ - 2), get_vertex(num_vertex_ - 1)};
1231 }
1232
1245 {
1247 size_t curr_;
1249
1250 public:
1254 : poly_(poly), curr_(0)
1255 {
1256 // empty
1257 }
1258
1261 [[nodiscard]] bool has_curr() const { return curr_ < poly_.size(); }
1262
1267 {
1268 ah_overflow_error_if(not has_curr()) << "Iterator has not current";
1269
1271
1272 return vertex_;
1273 }
1274
1276 void next_ne() noexcept { ++curr_; }
1277
1280 void next()
1281 {
1282 ah_overflow_error_if(not has_curr()) << "Iterator has not current";
1283 next_ne();
1284 }
1285
1288 void prev()
1289 {
1290 --curr_;
1291
1292 ah_underflow_error_if(not has_curr()) << "Iterator has not current";
1293 }
1294 };
1295
1308 {
1310 size_t curr_;
1311
1312 public:
1316 : poly_(poly), curr_(0)
1317 {
1318 // empty
1319 }
1320
1323 [[nodiscard]] bool has_curr() const { return curr_ < poly_.size(); }
1324
1329 {
1330 ah_overflow_error_if(not has_curr()) << "Iterator has not current";
1331
1332 return {poly_.get_vertex(curr_), poly_.get_vertex((curr_ + 1) % poly_.size())};
1333 }
1334
1336 void next_ne() noexcept { ++curr_; }
1337
1340 void next()
1341 {
1342 ah_overflow_error_if(not has_curr()) << "Iterator has not current";
1343 next_ne();
1344 }
1345
1348 void prev()
1349 {
1350 --curr_;
1351
1352 ah_underflow_error_if(not has_curr()) << "Iterator has not current";
1353 }
1354 };
1355
1360 [[nodiscard]] Point lowest_point() const { return center_ + Point(0, -r_); }
1361
1364 [[nodiscard]] Point highest_point() const { return center_ + Point(0, r_); }
1365
1368 [[nodiscard]] Point leftmost_point() const { return center_ + Point(-r_, 0); }
1369
1372 [[nodiscard]] Point rightmost_point() const { return center_ + Point(r_, 0); }
1373 };
1374
1380 {
1382
1383 for (size_t i = 0; i < poly.size(); ++i)
1384 add_vertex(poly.get_vertex(i));
1385
1386 close();
1387 }
1388
1389 // ============================================================================
1390 // Stream output operators for polygon classes
1391 // ============================================================================
1392
1399 inline std::ostream &operator<<(std::ostream & o, const Polygon & p)
1400 {
1401 o << "Polygon(n=" << p.size() << ", "
1402 << (p.is_closed() ? "closed" : "open") << ", [";
1403 size_t count = 0;
1404 for (Polygon::Vertex_Iterator it(p); it.has_curr(); it.next_ne())
1405 {
1406 if (count > 0) o << ", ";
1407 o << it.get_current_vertex();
1408 ++count;
1409 }
1410 o << "])";
1411 return o;
1412 }
1413
1420 inline std::ostream &operator<<(std::ostream & o, const Regular_Polygon & p)
1421 {
1422 o << "Regular_Polygon(center=" << p.get_center()
1423 << ", n=" << p.size()
1424 << ", radius=" << p.radius() << ")";
1425 return o;
1426 }
1427} // namespace Aleph
1428
1429#endif // POLYGON_H
Container traversal and functional operation mixins.
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:579
#define ah_underflow_error_if(C)
Throws std::underflow_error if condition holds.
Definition ah-errors.H:368
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
Definition ah-errors.H:463
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
STL-compatible iterator adapters for Aleph containers.
DRY (Don't Repeat Yourself) utilities and macros.
#define Special_Ctors(Set_Type, Type)
Generates special constructors for containers.
Definition ahDry.H:113
Represents a point with rectangular coordinates in a 2D plane.
Definition point.H:229
bool is_inside(const Segment &s) const
Checks if this point is contained within a segment.
Definition point.H:1423
const Geom_Number & get_x() const noexcept
Gets the x-coordinate value.
Definition point.H:457
const Geom_Number & get_y() const noexcept
Gets the y-coordinate value.
Definition point.H:466
bool is_colinear_with(const Point &p1, const Point &p2) const
Checks if this point is collinear with two other points.
Definition point.H:477
STL/Aleph-compatible iterator over polygon vertices as Points.
Definition polygon.H:317
void prev_ne() noexcept
Definition polygon.H:334
const Point & get_curr() const
Definition polygon.H:340
Dlink::Iterator dit_
Definition polygon.H:318
bool operator==(const Iterator &o) const noexcept
Definition polygon.H:350
Iterator() noexcept=default
void next_ne() noexcept
Definition polygon.H:330
Dlink * get_pos() const noexcept
Definition polygon.H:345
bool operator!=(const Iterator &o) const noexcept
Definition polygon.H:355
void end() noexcept
Definition polygon.H:338
bool has_curr() const noexcept
Definition polygon.H:326
void reset_first() noexcept
Definition polygon.H:336
Iterator over the edges (segments) of a polygon.
Definition polygon.H:520
Polygon & poly_
Reference to the polygon being iterated.
Definition polygon.H:521
Segment get_current_segment() const
Get the current segment (edge).
Definition polygon.H:548
bool has_curr() const
Check if there is a current segment.
Definition polygon.H:537
Segment_Iterator(const Polygon &poly)
Construct a segment iterator from a polygon.
Definition polygon.H:527
A general (irregular) 2D polygon defined by a sequence of vertices.
Definition polygon.H:246
const Point & rightmost_point() const
Get the vertex with the maximum x-coordinate.
Definition polygon.H:469
void copy_points(const Polygon &poly)
Copy all vertices from another polygon.
Definition polygon.H:291
void delete_points()
Delete all vertices and reset the polygon state.
Definition polygon.H:280
Polygon(Polygon &&poly) noexcept
Move constructor.
Definition polygon.H:385
bool contains_to(const Point &p) const
Definition polygon.H:933
Point lowest_
Vertex with minimum y-coordinate.
Definition polygon.H:251
void copy_regular_polygon(const Regular_Polygon &poly)
Copy vertices from a regular polygon.
Definition polygon.H:1379
Geom_Number signed_area() const
Compute the signed area of the polygon using the shoelace formula.
Definition polygon.H:943
Point centroid() const
Compute the centroid (center of mass) of the polygon.
Definition polygon.H:993
bool is_closed_
True if the polygon has been closed.
Definition polygon.H:249
Geom_Number perimeter() const
Compute the perimeter of the polygon.
Definition polygon.H:976
void update_extreme_points(const Point &point)
Update extreme points after adding a new vertex.
Definition polygon.H:258
const Point & highest_point() const
Get the vertex with the maximum y-coordinate.
Definition polygon.H:461
const Vertex & get_next_vertex(const Vertex &v) const
Get the vertex following v in the polygon.
Definition polygon.H:601
Polygon & operator=(const Polygon &poly)
Copy assignment operator.
Definition polygon.H:409
const Vertex & get_prev_vertex(const Vertex &v) const
Get the vertex preceding v in the polygon.
Definition polygon.H:615
Geom_Number area() const
Compute the absolute area of the polygon.
Definition polygon.H:963
void remove_vertex(const Vertex &v)
Remove a vertex from the polygon.
Definition polygon.H:777
void append(const Point &point)
Append a vertex (Aleph container protocol).
Definition polygon.H:764
size_t num_vertex_
Number of vertices in the polygon.
Definition polygon.H:248
PointLocation locate_point(const Point &p) const
Classify a point against this closed polygon.
Definition polygon.H:884
Point rightmost_
Vertex with maximum x-coordinate.
Definition polygon.H:254
const Vertex & get_first_vertex() const
Get the first vertex of the polygon.
Definition polygon.H:578
Polygon(const Regular_Polygon &poly)
Construct from a Regular_Polygon.
Definition polygon.H:400
const Vertex & get_last_vertex() const
Get the last vertex of the polygon.
Definition polygon.H:588
Segment get_last_segment() const
Get the last edge (segment) of the polygon.
Definition polygon.H:639
bool is_convex() const
Check if the polygon is convex.
Definition polygon.H:1021
~Polygon()
Destructor. Frees all vertices.
Definition polygon.H:367
void add_vertex(const Geom_Number &x, const Geom_Number &y)
Add a vertex using coordinates.
Definition polygon.H:756
void add_vertex(const Point &point)
Add a vertex to the polygon.
Definition polygon.H:677
Point leftmost_
Vertex with minimum x-coordinate.
Definition polygon.H:253
Segment get_first_segment() const
Get the first edge (segment) of the polygon.
Definition polygon.H:626
Polygon(const Polygon &poly)
Copy constructor.
Definition polygon.H:374
Point highest_
Vertex with maximum y-coordinate.
Definition polygon.H:252
void close()
Close the polygon.
Definition polygon.H:840
const Point & leftmost_point() const
Get the vertex with the minimum x-coordinate.
Definition polygon.H:465
const bool & is_closed() const
Check if the polygon is closed.
Definition polygon.H:473
bool vertex_belong_polygon(const Vertex &v) const
Check if a vertex belongs to this polygon.
Definition polygon.H:566
Dlink vertex_list_
Doubly linked list of vertices.
Definition polygon.H:247
const size_t & size() const
Get the number of vertices.
Definition polygon.H:477
bool intersects_with(const Segment &sg) const
Check if a segment intersects with any edge of the polygon.
Definition polygon.H:652
Polygon(const Triangle &tr)
Construct a polygon from a Triangle.
Definition polygon.H:1071
const Point & lowest_point() const
Get the vertex with the minimum y-coordinate.
Definition polygon.H:457
Polygon()
Default constructor. Creates an empty, open polygon.
Definition polygon.H:362
bool contains(const Point &p) const
Check if a point is inside the polygon (or on its boundary).
Definition polygon.H:926
Iterator over the edges (segments) of a regular polygon.
Definition polygon.H:1308
void prev()
Move to the previous segment.
Definition polygon.H:1348
void next()
Advance to the next segment.
Definition polygon.H:1340
Segment get_current_segment() const
Get the current segment (edge).
Definition polygon.H:1328
bool has_curr() const
Check if there is a current segment.
Definition polygon.H:1323
const Regular_Polygon & poly_
Reference to the polygon.
Definition polygon.H:1309
Segment_Iterator(const Regular_Polygon &poly)
Construct segment iterator from a regular polygon.
Definition polygon.H:1315
size_t curr_
Current segment index.
Definition polygon.H:1310
void next_ne() noexcept
Advance to the next segment (no exception on overflow).
Definition polygon.H:1336
Iterator over the vertices of a regular polygon.
Definition polygon.H:1245
const Regular_Polygon & poly_
Reference to the polygon.
Definition polygon.H:1246
Vertex & get_current_vertex()
Get the current vertex.
Definition polygon.H:1266
size_t curr_
Current vertex index.
Definition polygon.H:1247
bool has_curr() const
Check if there is a current vertex.
Definition polygon.H:1261
void next()
Advance to the next vertex.
Definition polygon.H:1280
void prev()
Move to previous vertex.
Definition polygon.H:1288
void next_ne() noexcept
Advance to the next vertex (no exception on overflow).
Definition polygon.H:1276
Vertex vertex_
Cache for compatibility with Polygon::Vertex_Iterator.
Definition polygon.H:1248
Vertex_Iterator(const Regular_Polygon &poly)
Construct iterator from a regular polygon.
Definition polygon.H:1253
A regular polygon defined by center, side length, and vertex count.
Definition polygon.H:1132
Point get_last_vertex() const
Get the last vertex (index size()-1).
Definition polygon.H:1217
Point get_vertex(const size_t &i) const
Get the i-th vertex of the polygon.
Definition polygon.H:1197
Point get_first_vertex() const
Get the first vertex (index 0).
Definition polygon.H:1213
double r_
Circumradius (distance from center to vertices)
Definition polygon.H:1137
const size_t & size() const
Get the number of vertices.
Definition polygon.H:1178
const double & get_side_size() const
Get the side length.
Definition polygon.H:1170
double angle_
Rotation angle in radians.
Definition polygon.H:1136
Point lowest_point() const
Get the lowest point of the bounding circle.
Definition polygon.H:1360
Regular_Polygon(Point c, const double &side_sz, const size_t &n, const double &ang=0)
Construct a regular polygon.
Definition polygon.H:1154
Point highest_point() const
Get the highest point of the bounding circle.
Definition polygon.H:1364
const Point & get_center() const
Get the center point.
Definition polygon.H:1174
double side_size_
Length of each side (double due to trig limitations)
Definition polygon.H:1134
Regular_Polygon()
Default constructor. Creates an invalid empty polygon.
Definition polygon.H:1142
Segment get_first_segment() const
Get the first segment (edge).
Definition polygon.H:1221
Segment get_last_segment() const
Get the last segment (closing edge).
Definition polygon.H:1228
Point center_
Center point of the polygon.
Definition polygon.H:1133
size_t num_vertex_
Number of vertices (sides)
Definition polygon.H:1135
double beta_
Central angle between adjacent vertices (2π/n)
Definition polygon.H:1138
Point leftmost_point() const
Get the leftmost point of the bounding circle.
Definition polygon.H:1368
const double & radius() const
Get the circumradius.
Definition polygon.H:1182
Point rightmost_point() const
Get the rightmost point of the bounding circle.
Definition polygon.H:1372
static bool is_closed()
Check if the polygon is closed.
Definition polygon.H:1186
Represents a line segment between two points.
Definition point.H:827
void rotate(const Geom_Number &angle)
Rotates the segment by a given angle around its source point.
Definition point.H:1398
const Point & get_tgt_point() const noexcept
Gets the target point of the segment.
Definition point.H:921
const Point & get_src_point() const noexcept
Gets the source point of the segment.
Definition point.H:915
A non-degenerate triangle defined by three points.
Definition point.H:1478
A vertex in a polygon's doubly linked vertex list.
Definition polygon.H:119
Vertex(const Vertex &vertex)
Copy constructor.
Definition polygon.H:133
Vertex(const Point &point)
Construct a vertex from a Point.
Definition polygon.H:126
const Vertex & prev_vertex() const
Get the previous vertex in the polygon.
Definition polygon.H:176
Vertex()=default
Default constructor. Creates a vertex at origin (0, 0).
static const Vertex * dlink_to_vertex(const Dlink *link)
Convert a const Dlink pointer to a const Vertex pointer.
Definition polygon.H:167
static Vertex * dlink_to_vertex(Dlink *link)
Convert a Dlink pointer to a Vertex pointer.
Definition polygon.H:159
Vertex & operator=(const Vertex &vertex)
Copy assignment operator.
Definition polygon.H:141
const Vertex & next_vertex() const
Get the next vertex in the polygon.
Definition polygon.H:189
Point to_point() const
Return this vertex as a plain Point value.
Definition polygon.H:150
Common methods to the Aleph-w ( ) containers.
Definition ah-dry.H:642
Common sequential searching methods on containers.
Definition ah-dry.H:196
Mixin that adds STL begin()/end() and cbegin()/cend() to Aleph containers.
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_sin_function > > sin(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4070
static mpfr_t y
Definition mpfr_mul_d.c:3
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
Geom_Number area_of_parallelogram(const Point &a, const Point &b, const Point &c)
Compute the signed area of the parallelogram defined by vectors a->b and a->c.
Definition point.H:2803
bool on_segment(const Segment &s, const Point &p)
Return true if p lies on segment s (exact).
Definition point.H:2876
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
Orientation orientation(const Point &a, const Point &b, const Point &c)
Return the orientation of the triple (a, b, c).
Definition point.H:2821
mpq_class Geom_Number
Numeric type used by the geometry module.
Definition point.H:115
std::ostream & operator<<(std::ostream &osObject, const Field< T > &rightOp)
Definition ahField.H:121
constexpr double PI
Definition point.H:132
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
STL namespace.
2D point and geometric utilities.
Base class for all geometric objects.
Definition point.H:214
Iterator over the vertices of a polygon.
Definition polygon.H:489
Vertex_Iterator(const Polygon &poly)
Construct iterator from a polygon.
Definition polygon.H:493
Vertex & get_current_vertex() const
Get the current vertex.
Definition polygon.H:500
Generic traversal of the container through its iterator.
Definition ah-dry.H:67