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 <cmath>
94# include <string>
95# include <utility>
96
97namespace Aleph
98{
99 using Aleph::Dlink;
100
119 class Vertex : public Point, public Dlink
120 {
121 public:
123 Vertex() = default;
124
127 Vertex(const Point & point) : Point(point)
128 { /* empty */
129 }
130
134 Vertex(const Vertex & vertex) : Point(vertex), Dlink()
135 { /* empty */
136 }
137
142 Vertex &operator=(const Vertex & vertex)
143 {
144 if (this != &vertex)
145 Point::operator=(vertex);
146 return *this;
147 }
148
152 {
153 return static_cast<const Point>(*this);
154 }
155
161 {
162 return static_cast<Vertex *>(link);
163 }
164
168 [[nodiscard]] static const Vertex * dlink_to_vertex(const Dlink *link)
169 {
170 return static_cast<const Vertex *>(link);
171 }
172
177 [[nodiscard]] const Vertex &prev_vertex() const
178 {
179 assert(not this->is_empty());
180
181 ah_domain_error_if(this->is_unitarian()) << "There is an only vertex";
182
183 return *dlink_to_vertex(this->get_prev());
184 }
185
190 [[nodiscard]] const Vertex &next_vertex() const
191 {
192 assert(not this->is_empty());
193
194 ah_domain_error_if(this->is_unitarian()) << "There is an only vertex";
195
196 return *dlink_to_vertex(this->get_next());
197 }
198
199 // TODO: Implement next_segment() and prev_segment() methods
200 };
201
202
203 class Regular_Polygon;
204
242 class Polygon : public Geom_Object,
243 public GenericTraverse<Polygon>,
244 public FunctionalMethods<Polygon, Point>,
245 public LocateFunctions<Polygon, Point>,
246 public StlAlephIterator<Polygon>
247 {
249 size_t num_vertex_;
251
256
259 void update_extreme_points(const Point & point)
260 {
261 if (num_vertex_ == 0)
262 {
263 leftmost_ = rightmost_ = lowest_ = highest_ = point;
264 return;
265 }
266
267 if (point.get_x() < leftmost_.get_x())
268 leftmost_ = point;
269
270 if (point.get_x() > rightmost_.get_x())
271 rightmost_ = point;
272
273 if (point.get_y() < lowest_.get_y())
274 lowest_ = point;
275
276 if (point.get_y() > highest_.get_y())
277 highest_ = point;
278 }
279
282 {
283 while (not vertex_list_.is_empty())
285
286 num_vertex_ = 0;
287 is_closed_ = false;
288 }
289
292 void copy_points(const Polygon & poly)
293 {
294 auto *list = const_cast<Dlink *>(&poly.vertex_list_);
295
296 for (Dlink::Iterator it(list); it.has_curr(); it.next_ne())
298 }
299
302 void copy_regular_polygon(const Regular_Polygon & poly);
303
304 public:
307
310
318 {
320
321 public:
323
326
327 [[nodiscard]] bool has_curr() const noexcept { return dit_.has_curr(); }
328
329 void next() { dit_.next(); }
330
332
333 void prev() { dit_.prev(); }
334
336
338
339 void end() noexcept { dit_.end(); }
340
341 [[nodiscard]] const Point &get_curr() const
342 {
344 }
345
347 {
348 return dit_.get_curr_ne();
349 }
350
351 [[nodiscard]] bool operator==(const Iterator & o) const noexcept
352 {
353 return dit_ == o.dit_;
354 }
355
356 [[nodiscard]] bool operator!=(const Iterator & o) const noexcept
357 {
358 return dit_ != o.dit_;
359 }
360 };
361
364 { /* empty */
365 }
366
369 {
371 }
372
375 Polygon(const Polygon & poly)
376 : Geom_Object(poly),
378 lowest_(poly.lowest_), highest_(poly.highest_),
380 {
381 copy_points(poly);
382 }
383
387 : Polygon()
388 {
389 vertex_list_.swap(poly.vertex_list_);
390 std::swap(num_vertex_, poly.num_vertex_);
391 std::swap(is_closed_, poly.is_closed_);
392 std::swap(lowest_, poly.lowest_);
393 std::swap(highest_, poly.highest_);
394 std::swap(leftmost_, poly.leftmost_);
395 std::swap(rightmost_, poly.rightmost_);
396 }
397
403 {
405 }
406
411 {
412 if (this == &poly)
413 return *this;
414
416
418 is_closed_ = poly.is_closed_;
419 lowest_ = poly.lowest_;
420 highest_ = poly.highest_;
421 leftmost_ = poly.leftmost_;
422 rightmost_ = poly.rightmost_;
423
424 copy_points(poly);
425
426 return *this;
427 }
428
432 Polygon &operator =(Polygon && poly) noexcept
433 {
434 vertex_list_.swap(poly.vertex_list_);
435 std::swap(num_vertex_, poly.num_vertex_);
436 std::swap(is_closed_, poly.is_closed_);
437 std::swap(lowest_, poly.lowest_);
438 std::swap(highest_, poly.highest_);
439 std::swap(leftmost_, poly.leftmost_);
440 std::swap(rightmost_, poly.rightmost_);
441
442 return *this;
443 }
444
449 {
452
453 return *this;
454 }
455
458 [[nodiscard]] const Point &lowest_point() const { return lowest_; }
459
462 [[nodiscard]] const Point &highest_point() const { return highest_; }
463
466 [[nodiscard]] const Point &leftmost_point() const { return leftmost_; }
467
470 [[nodiscard]] const Point &rightmost_point() const { return rightmost_; }
471
474 [[nodiscard]] const bool &is_closed() const { return is_closed_; }
475
478 [[nodiscard]] const size_t &size() const { return num_vertex_; }
479
490 {
495 {
496 ah_domain_error_if(poly.vertex_list_.is_empty()) << "Polygon has not any vertex";
497 }
498
502 {
504 }
505 };
506
521 {
523
524 public:
530 {
532 << "Polygon has less than two vertex";
533 }
534
538 [[nodiscard]] bool has_curr() const
539 {
540 if (this->is_in_last())
541 return poly_.is_closed() ? true : false;
542
544 }
545
550 {
552 << "Segment iterator is in the last point and it is not closed";
553
554 const Vertex *src = Vertex::dlink_to_vertex(this->get_curr());
555
556 // Determine target: if at last vertex, wrap to first; otherwise, next
557 const Vertex & tgt =
558 this->is_in_last() ? poly_.get_first_vertex() : src->next_vertex();
559
560 return {src->to_point(), tgt.to_point()};
561 }
562 };
563
567 [[nodiscard]] bool vertex_belong_polygon(const Vertex & v) const
568 {
569 for (Vertex_Iterator it(*this); it.has_curr(); it.next_ne())
570 if (&it.get_current_vertex() == &v)
571 return true;
572
573 return false;
574 }
575
580 {
581 ah_domain_error_if(vertex_list_.is_empty()) << "Polygon has not any vertex";
582
584 }
585
590 {
591 ah_domain_error_if(vertex_list_.is_empty()) << "Polygon has not any vertex";
592
594 }
595
602 [[nodiscard]] const Vertex &get_next_vertex(const Vertex & v) const
603 {
604 // If v is the last vertex (next points to sentinel), wrap to the first vertex
605 return v.get_next() == &vertex_list_ ?
607 v.next_vertex();
608 }
609
616 [[nodiscard]] const Vertex &get_prev_vertex(const Vertex & v) const
617 {
618 // If v is the first vertex (prev points to sentinel), wrap to last vertex
619 return v.get_prev() == &vertex_list_ ?
621 v.prev_vertex();
622 }
623
628 {
630 << "polygon has less than two vertex";
631
633
634 return {first_vertex.to_point(), first_vertex.next_vertex().to_point()};
635 }
636
641 {
643 << "polygon has less than two vertex";
644
646
647 return {last_vertex.prev_vertex().to_point(), last_vertex.to_point()};
648 }
649
653 [[nodiscard]] bool intersects_with(const Segment & sg) const
654 {
655 // Traverse all edges and check for intersection
656 for (Segment_Iterator it(*this); it.has_curr(); it.next_ne())
657 if (const Segment & curr_side = it.get_current_segment(); curr_side.intersects_with(sg))
658 return true;
659
660 return false;
661 }
662
678 void add_vertex(const Point & point)
679 {
680 ah_domain_error_if(is_closed_) << "Polygon is already closed";
681
682 // Check if the new point is colinear with the last segment
683 if (num_vertex_ > 1)
685 {
687 << "new vertex is inside of last polygon's segment";
688
689 // Colinear point: replace the last vertex with this new one
690 auto & last_vertex = const_cast<Vertex &>(get_last_vertex());
691 Point old_point = last_vertex.to_point(); // Store old point before replacing
693 last_point = point;
694
695 // Recalculate extremes if the old point was an extreme point
698
699 if (was_extreme)
700 {
701 // We need a full recalculation of extremes
703
704 for (Vertex_Iterator it(*this); it.has_curr(); it.next_ne())
705 {
706 const Point p = it.get_current_vertex().to_point();
707
708 if (p.get_x() < leftmost_.get_x())
709 leftmost_ = p;
710 if (p.get_x() > rightmost_.get_x())
711 rightmost_ = p;
712 if (p.get_y() < lowest_.get_y())
713 lowest_ = p;
714 if (p.get_y() > highest_.get_y())
715 highest_ = p;
716 }
717 }
718 else
719 {
720 // Just check if the new point is an extreme
722 }
723
724 return;
725 }
726
727 // If we have at least 3 vertices, verify no self-intersection
728 if (num_vertex_ >= 3)
729 {
730 // New edge that would be formed by adding this point
731 const Segment new_side(get_last_vertex().to_point(), point);
732
733 // Check for intersection with all edges except the last one
734 // (which shares a vertex with the new edge)
735 for (Segment_Iterator it(*this); true; it.next_ne())
736 {
737 const Segment curr_side = it.get_current_segment();
738
740 break;
741
742 ah_domain_error_if(curr_side.intersects_with(new_side)) << "new side intersects";
743 }
744 }
745
746 // Insert new vertex
747 vertex_list_.append(new Vertex(point));
749 ++num_vertex_;
750 }
751
757 void add_vertex(const Geom_Number & x, const Geom_Number & y)
758 {
759 add_vertex(Point(x, y));
760 }
761
765 void append(const Point & point) { add_vertex(point); }
766
768
778 void remove_vertex(const Vertex & v)
779 {
780 Vertex *victim = nullptr;
781 for (Vertex_Iterator it(*this); it.has_curr(); it.next_ne())
782 if (&it.get_current_vertex() == &v)
783 {
784 victim = &const_cast<Vertex &>(it.get_current_vertex());
785 break;
786 }
787
788 ah_domain_error_if(victim == nullptr) << "Vertex does not belong to polygon";
789
790 // Store point for later comparison with extremes
791 // cppcheck-suppress nullPointer
792 const Point victim_point = victim->to_point();
793
794 // Delete the vertex
795 // cppcheck-suppress nullPointer
796 victim->del();
797 --num_vertex_;
798 delete victim;
799
800 // Recalculate extremes if needed
803 {
804 if (num_vertex_ == 0)
805 // No vertices left, reset extremes
807 else
808 {
809 // Recalculate extremes from remaining vertices
812
813 for (Vertex_Iterator it(*this); it.has_curr(); it.next_ne())
814 {
815 const Point point = it.get_current_vertex().to_point();
816 if (point.get_x() < leftmost_.get_x())
817 leftmost_ = point;
818 if (point.get_x() > rightmost_.get_x())
819 rightmost_ = point;
820 if (point.get_y() < lowest_.get_y())
821 lowest_ = point;
822 if (point.get_y() > highest_.get_y())
823 highest_ = point;
824 }
825 }
826 }
827
828 // Reset the closed state if the polygon now has fewer than 3 vertices
829 if (is_closed_ && num_vertex_ < 3)
830 is_closed_ = false;
831 }
832
843 void close()
844 {
845 ah_domain_error_if(is_closed_) << "Polygon is already closed";
847 << "Polygon needs at least 3 vertices to close (has " << num_vertex_ << ")";
848
849 if (num_vertex_ >= 4)
850 {
851 // Check for intersection with all edges except the first
852 // and last (which share endpoints with the closing edge)
853 const Segment last_side(get_first_vertex().to_point(), get_last_vertex().to_point());
854
855 Segment_Iterator it(*this);
856
857 for (it.next(); true; it.next_ne())
858 {
860
862 break;
863
864 ah_domain_error_if(curr_side.intersects_with(last_side))
865 << "closing causes an intersection";
866 }
867 }
868
869 is_closed_ = true;
870 }
871
872 enum class PointLocation
873 {
874 Outside,
875 Boundary,
876 Inside
877 };
878
888 {
889 ah_domain_error_if(not is_closed_) << "Polygon is not closed";
890
891 int winding = 0;
892
893 for (Segment_Iterator it(*this); it.has_curr(); it.next_ne())
894 {
895 const Segment edge = it.get_current_segment();
896 const Point & a = edge.get_src_point();
897 const Point & b = edge.get_tgt_point();
898
899 if (on_segment(edge, p))
901
902 if (a.get_y() <= p.get_y())
903 {
904 if (b.get_y() > p.get_y() and
905 orientation(a, b, p) == Orientation::CCW)
906 ++winding;
907 }
908 else
909 {
910 if (b.get_y() <= p.get_y() and
911 orientation(a, b, p) == Orientation::CW)
912 --winding;
913 }
914 }
915
917 }
918
929 [[nodiscard]] bool contains(const Point & p) const
930 {
932 }
933
935 [[deprecated("Use contains() instead")]]
936 [[nodiscard]] bool contains_to(const Point & p) const { return contains(p); }
937
947 {
948 ah_domain_error_if(num_vertex_ < 3) << "Polygon must have at least 3 vertices";
949
950 Geom_Number sum = 0;
951 for (Segment_Iterator it(*this); it.has_curr(); it.next_ne())
952 {
953 const Segment seg = it.get_current_segment();
954 const Point & a = seg.get_src_point();
955 const Point & b = seg.get_tgt_point();
956 sum += a.get_x() * b.get_y() - a.get_y() * b.get_x();
957 }
958 return sum / 2;
959 }
960
967 {
969 return a < 0 ? Geom_Number(-a) : a;
970 }
971
980 {
981 ah_domain_error_if(num_vertex_ < 2) << "Polygon must have at least 2 vertices";
982
983 Geom_Number sum = 0;
984 for (Segment_Iterator it(*this); it.has_curr(); it.next_ne())
985 sum += it.get_current_segment().length();
986 return sum;
987 }
988
997 {
998 ah_domain_error_if(num_vertex_ < 3) << "Polygon must have at least 3 vertices";
999
1000 Geom_Number cx = 0, cy = 0, a6 = 0;
1001 for (Segment_Iterator it(*this); it.has_curr(); it.next_ne())
1002 {
1003 const Segment seg = it.get_current_segment();
1004 const Point & p = seg.get_src_point();
1005 const Point & q = seg.get_tgt_point();
1006 const Geom_Number cross = p.get_x() * q.get_y() - q.get_x() * p.get_y();
1007 cx += (p.get_x() + q.get_x()) * cross;
1008 cy += (p.get_y() + q.get_y()) * cross;
1009 a6 += cross;
1010 }
1011
1012 ah_domain_error_if(a6 == 0) << "Polygon has zero area";
1013 return {cx / (3 * a6), cy / (3 * a6)};
1014 }
1015
1024 [[nodiscard]] bool is_convex() const
1025 {
1026 ah_domain_error_if(num_vertex_ < 3) << "Polygon must have at least 3 vertices";
1027
1028 // Check turn direction at each vertex using segment iterator
1029 int sign = 0;
1030 Segment_Iterator it(*this);
1032 it.next_ne();
1033
1034 while (it.has_curr())
1035 {
1037 // Turn at the shared vertex (prev_seg.tgt == curr_seg.src)
1039 prev_seg.get_src_point(), prev_seg.get_tgt_point(),
1040 curr_seg.get_tgt_point());
1041
1042 if (turn != 0)
1043 {
1044 const int curr_sign = turn > 0 ? 1 : -1;
1045 if (sign == 0)
1046 sign = curr_sign;
1047 else if (sign != curr_sign)
1048 return false;
1049 }
1050
1052 it.next_ne();
1053 }
1054
1055 // Check the wrap-around turn (last vertex to first)
1058 prev_seg.get_src_point(), prev_seg.get_tgt_point(),
1059 first_seg.get_tgt_point());
1060
1061 if (turn != 0)
1062 if (const int curr_sign = turn > 0 ? 1 : -1; sign != 0 and sign != curr_sign)
1063 return false;
1064
1065 return true;
1066 }
1067
1076 {
1077 add_vertex(tr.get_p1());
1078 add_vertex(tr.get_p2());
1079 add_vertex(tr.get_p3());
1080
1081 close();
1082 }
1083 };
1084
1085
1135 {
1137 double side_size_;
1139 double angle_;
1140 double r_;
1141 double beta_;
1142
1143 public:
1149 : center_(0, 0), side_size_(0), num_vertex_(0), angle_(0), r_(0), beta_(0)
1150 { /* empty */
1151 }
1152
1164 const double & side_sz,
1165 const size_t & n,
1166 const double & ang = 0)
1167 : center_(std::move(c)), side_size_(side_sz), num_vertex_(n), angle_(ang),
1168 r_(0), beta_(0)
1169 {
1170 ah_domain_error_if(n < 3) << "Regular polygon must have at least 3 sides";
1171 ah_domain_error_if(not std::isfinite(side_sz) or side_sz <= 0)
1172 << "Regular polygon side length must be positive and finite";
1173 ah_domain_error_if(not std::isfinite(ang))
1174 << "Regular polygon angle must be finite";
1175
1176 beta_ = 2 * PI / static_cast<double>(n);
1177
1178 // Calculate radius using law of sines with angles between vertices
1179 // and the angle between radius and side
1180 const double alpha = (PI - beta_) / 2; // angle between radius and side
1181 r_ = side_size_ * sin(alpha) / sin(beta_);
1182 ah_domain_error_if(not std::isfinite(r_) or r_ <= 0)
1183 << "Regular polygon circumradius is not representable";
1184 }
1185
1188 [[nodiscard]] const double &get_side_size() const { return side_size_; }
1189
1192 [[nodiscard]] const Point &get_center() const { return center_; }
1193
1196 [[nodiscard]] const size_t &size() const { return num_vertex_; }
1197
1200 [[nodiscard]] const double &radius() const { return r_; }
1201
1207 [[nodiscard]] bool is_closed() const noexcept { return num_vertex_ >= 3; }
1208
1218 [[nodiscard]] Point get_vertex(const size_t & i) const
1219 {
1221 << "vertex " << i << " is greater than " << num_vertex_;
1222
1223 // The first segment is the negative vertical from center
1224 // Initial point is the target of this segment with origin at center
1225 Segment sg(center_, center_ - Point(0, r_));
1226
1227 sg.rotate(i * beta_ + angle_);
1228
1229 return sg.get_tgt_point();
1230 }
1231
1234 [[nodiscard]] Point get_first_vertex() const { return get_vertex(0); }
1235
1239
1243 {
1244 return {get_vertex(0), get_vertex(1)};
1245 }
1246
1250 {
1251 return {get_vertex(num_vertex_ - 1), get_vertex(0)};
1252 }
1253
1266 {
1268 size_t curr_;
1270
1271 public:
1275 : poly_(poly), curr_(0)
1276 {
1277 // empty
1278 }
1279
1282 [[nodiscard]] bool has_curr() const { return curr_ < poly_.size(); }
1283
1288 {
1289 ah_overflow_error_if(not has_curr()) << "Iterator has not current";
1290
1292
1293 return vertex_;
1294 }
1295
1297 void next_ne() noexcept { ++curr_; }
1298
1301 void next()
1302 {
1303 ah_overflow_error_if(not has_curr()) << "Iterator has not current";
1304 next_ne();
1305 }
1306
1309 void prev()
1310 {
1311 --curr_;
1312
1313 ah_underflow_error_if(not has_curr()) << "Iterator has not current";
1314 }
1315 };
1316
1329 {
1331 size_t curr_;
1332
1333 public:
1337 : poly_(poly), curr_(0)
1338 {
1339 // empty
1340 }
1341
1344 [[nodiscard]] bool has_curr() const { return curr_ < poly_.size(); }
1345
1350 {
1351 ah_overflow_error_if(not has_curr()) << "Iterator has not current";
1352
1353 return {poly_.get_vertex(curr_), poly_.get_vertex((curr_ + 1) % poly_.size())};
1354 }
1355
1357 void next_ne() noexcept { ++curr_; }
1358
1361 void next()
1362 {
1363 ah_overflow_error_if(not has_curr()) << "Iterator has not current";
1364 next_ne();
1365 }
1366
1369 void prev()
1370 {
1371 --curr_;
1372
1373 ah_underflow_error_if(not has_curr()) << "Iterator has not current";
1374 }
1375 };
1376
1381 [[nodiscard]] Point lowest_point() const { return center_ + Point(0, -r_); }
1382
1385 [[nodiscard]] Point highest_point() const { return center_ + Point(0, r_); }
1386
1389 [[nodiscard]] Point leftmost_point() const { return center_ + Point(-r_, 0); }
1390
1393 [[nodiscard]] Point rightmost_point() const { return center_ + Point(r_, 0); }
1394 };
1395
1401 {
1403
1404 for (size_t i = 0; i < poly.size(); ++i)
1405 add_vertex(poly.get_vertex(i));
1406
1407 close();
1408 }
1409
1410 // ============================================================================
1411 // Stream output operators for polygon classes
1412 // ============================================================================
1413
1420 inline std::ostream &operator<<(std::ostream & o, const Polygon & p)
1421 {
1422 o << "Polygon(n=" << p.size() << ", "
1423 << (p.is_closed() ? "closed" : "open") << ", [";
1424 size_t count = 0;
1425 for (Polygon::Vertex_Iterator it(p); it.has_curr(); it.next_ne())
1426 {
1427 if (count > 0) o << ", ";
1428 o << it.get_current_vertex();
1429 ++count;
1430 }
1431 o << "])";
1432 return o;
1433 }
1434
1441 inline std::ostream &operator<<(std::ostream & o, const Regular_Polygon & p)
1442 {
1443 o << "Regular_Polygon(center=" << p.get_center()
1444 << ", n=" << p.size()
1445 << ", radius=" << p.radius() << ")";
1446 return o;
1447 }
1448} // namespace Aleph
1449
1450#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:584
#define ah_underflow_error_if(C)
Throws std::underflow_error if condition holds.
Definition ah-errors.H:373
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
Definition ah-errors.H:468
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:527
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:221
bool is_inside(const Segment &s) const
Checks if this point is contained within a segment.
Definition point.H:1460
const Geom_Number & get_x() const noexcept
Gets the x-coordinate value.
Definition point.H:448
const Geom_Number & get_y() const noexcept
Gets the y-coordinate value.
Definition point.H:457
bool is_colinear_with(const Point &p1, const Point &p2) const
Checks if this point is collinear with two other points.
Definition point.H:468
STL/Aleph-compatible iterator over polygon vertices as Points.
Definition polygon.H:318
void prev_ne() noexcept
Definition polygon.H:335
const Point & get_curr() const
Definition polygon.H:341
Dlink::Iterator dit_
Definition polygon.H:319
bool operator==(const Iterator &o) const noexcept
Definition polygon.H:351
Iterator() noexcept=default
void next_ne() noexcept
Definition polygon.H:331
Dlink * get_pos() const noexcept
Definition polygon.H:346
bool operator!=(const Iterator &o) const noexcept
Definition polygon.H:356
void end() noexcept
Definition polygon.H:339
bool has_curr() const noexcept
Definition polygon.H:327
void reset_first() noexcept
Definition polygon.H:337
Iterator over the edges (segments) of a polygon.
Definition polygon.H:521
Polygon & poly_
Reference to the polygon being iterated.
Definition polygon.H:522
Segment get_current_segment() const
Get the current segment (edge).
Definition polygon.H:549
bool has_curr() const
Check if there is a current segment.
Definition polygon.H:538
Segment_Iterator(const Polygon &poly)
Construct a segment iterator from a polygon.
Definition polygon.H:528
A general (irregular) 2D polygon defined by a sequence of vertices.
Definition polygon.H:247
const Point & rightmost_point() const
Get the vertex with the maximum x-coordinate.
Definition polygon.H:470
void copy_points(const Polygon &poly)
Copy all vertices from another polygon.
Definition polygon.H:292
void delete_points()
Delete all vertices and reset the polygon state.
Definition polygon.H:281
Polygon(Polygon &&poly) noexcept
Move constructor.
Definition polygon.H:386
bool contains_to(const Point &p) const
Definition polygon.H:936
Point lowest_
Vertex with minimum y-coordinate.
Definition polygon.H:252
void copy_regular_polygon(const Regular_Polygon &poly)
Copy vertices from a regular polygon.
Definition polygon.H:1400
Geom_Number signed_area() const
Compute the signed area of the polygon using the shoelace formula.
Definition polygon.H:946
Point centroid() const
Compute the centroid (center of mass) of the polygon.
Definition polygon.H:996
bool is_closed_
True if the polygon has been closed.
Definition polygon.H:250
Geom_Number perimeter() const
Compute the perimeter of the polygon.
Definition polygon.H:979
void update_extreme_points(const Point &point)
Update extreme points after adding a new vertex.
Definition polygon.H:259
const Point & highest_point() const
Get the vertex with the maximum y-coordinate.
Definition polygon.H:462
const Vertex & get_next_vertex(const Vertex &v) const
Get the vertex following v in the polygon.
Definition polygon.H:602
Polygon & operator=(const Polygon &poly)
Copy assignment operator.
Definition polygon.H:410
const Vertex & get_prev_vertex(const Vertex &v) const
Get the vertex preceding v in the polygon.
Definition polygon.H:616
Geom_Number area() const
Compute the absolute area of the polygon.
Definition polygon.H:966
void remove_vertex(const Vertex &v)
Remove a vertex from the polygon.
Definition polygon.H:778
void append(const Point &point)
Append a vertex (Aleph container protocol).
Definition polygon.H:765
size_t num_vertex_
Number of vertices in the polygon.
Definition polygon.H:249
PointLocation locate_point(const Point &p) const
Classify a point against this closed polygon.
Definition polygon.H:887
Point rightmost_
Vertex with maximum x-coordinate.
Definition polygon.H:255
const Vertex & get_first_vertex() const
Get the first vertex of the polygon.
Definition polygon.H:579
Polygon(const Regular_Polygon &poly)
Construct from a Regular_Polygon.
Definition polygon.H:401
const Vertex & get_last_vertex() const
Get the last vertex of the polygon.
Definition polygon.H:589
Segment get_last_segment() const
Get the last edge (segment) of the polygon.
Definition polygon.H:640
bool is_convex() const
Check if the polygon is convex.
Definition polygon.H:1024
~Polygon()
Destructor. Frees all vertices.
Definition polygon.H:368
void add_vertex(const Geom_Number &x, const Geom_Number &y)
Add a vertex using coordinates.
Definition polygon.H:757
void add_vertex(const Point &point)
Add a vertex to the polygon.
Definition polygon.H:678
Point leftmost_
Vertex with minimum x-coordinate.
Definition polygon.H:254
Segment get_first_segment() const
Get the first edge (segment) of the polygon.
Definition polygon.H:627
Polygon(const Polygon &poly)
Copy constructor.
Definition polygon.H:375
Point highest_
Vertex with maximum y-coordinate.
Definition polygon.H:253
void close()
Close the polygon.
Definition polygon.H:843
const Point & leftmost_point() const
Get the vertex with the minimum x-coordinate.
Definition polygon.H:466
const bool & is_closed() const
Check if the polygon is closed.
Definition polygon.H:474
bool vertex_belong_polygon(const Vertex &v) const
Check if a vertex belongs to this polygon.
Definition polygon.H:567
Dlink vertex_list_
Doubly linked list of vertices.
Definition polygon.H:248
const size_t & size() const
Get the number of vertices.
Definition polygon.H:478
bool intersects_with(const Segment &sg) const
Check if a segment intersects with any edge of the polygon.
Definition polygon.H:653
Polygon(const Triangle &tr)
Construct a polygon from a Triangle.
Definition polygon.H:1074
const Point & lowest_point() const
Get the vertex with the minimum y-coordinate.
Definition polygon.H:458
Polygon()
Default constructor. Creates an empty, open polygon.
Definition polygon.H:363
bool contains(const Point &p) const
Check if a point is inside the polygon (or on its boundary).
Definition polygon.H:929
Iterator over the edges (segments) of a regular polygon.
Definition polygon.H:1329
void prev()
Move to the previous segment.
Definition polygon.H:1369
void next()
Advance to the next segment.
Definition polygon.H:1361
Segment get_current_segment() const
Get the current segment (edge).
Definition polygon.H:1349
bool has_curr() const
Check if there is a current segment.
Definition polygon.H:1344
const Regular_Polygon & poly_
Reference to the polygon.
Definition polygon.H:1330
Segment_Iterator(const Regular_Polygon &poly)
Construct segment iterator from a regular polygon.
Definition polygon.H:1336
size_t curr_
Current segment index.
Definition polygon.H:1331
void next_ne() noexcept
Advance to the next segment (no exception on overflow).
Definition polygon.H:1357
Iterator over the vertices of a regular polygon.
Definition polygon.H:1266
const Regular_Polygon & poly_
Reference to the polygon.
Definition polygon.H:1267
Vertex & get_current_vertex()
Get the current vertex.
Definition polygon.H:1287
size_t curr_
Current vertex index.
Definition polygon.H:1268
bool has_curr() const
Check if there is a current vertex.
Definition polygon.H:1282
void next()
Advance to the next vertex.
Definition polygon.H:1301
void prev()
Move to previous vertex.
Definition polygon.H:1309
void next_ne() noexcept
Advance to the next vertex (no exception on overflow).
Definition polygon.H:1297
Vertex vertex_
Cache for compatibility with Polygon::Vertex_Iterator.
Definition polygon.H:1269
Vertex_Iterator(const Regular_Polygon &poly)
Construct iterator from a regular polygon.
Definition polygon.H:1274
A regular polygon defined by center, side length, and vertex count.
Definition polygon.H:1135
Point get_last_vertex() const
Get the last vertex (index size()-1).
Definition polygon.H:1238
Point get_vertex(const size_t &i) const
Get the i-th vertex of the polygon.
Definition polygon.H:1218
Point get_first_vertex() const
Get the first vertex (index 0).
Definition polygon.H:1234
double r_
Circumradius (distance from center to vertices)
Definition polygon.H:1140
const size_t & size() const
Get the number of vertices.
Definition polygon.H:1196
const double & get_side_size() const
Get the side length.
Definition polygon.H:1188
double angle_
Rotation angle in radians.
Definition polygon.H:1139
Point lowest_point() const
Get the lowest point of the bounding circle.
Definition polygon.H:1381
Regular_Polygon(Point c, const double &side_sz, const size_t &n, const double &ang=0)
Construct a regular polygon.
Definition polygon.H:1163
Point highest_point() const
Get the highest point of the bounding circle.
Definition polygon.H:1385
const Point & get_center() const
Get the center point.
Definition polygon.H:1192
double side_size_
Length of each side (double due to trig limitations)
Definition polygon.H:1137
Regular_Polygon()
Default constructor.
Definition polygon.H:1148
Segment get_first_segment() const
Get the first segment (edge).
Definition polygon.H:1242
Segment get_last_segment() const
Get the last segment (closing edge).
Definition polygon.H:1249
Point center_
Center point of the polygon.
Definition polygon.H:1136
size_t num_vertex_
Number of vertices (sides)
Definition polygon.H:1138
double beta_
Central angle between adjacent vertices (2π/n)
Definition polygon.H:1141
Point leftmost_point() const
Get the leftmost point of the bounding circle.
Definition polygon.H:1389
bool is_closed() const noexcept
Check if the polygon is a valid closed regular polygon.
Definition polygon.H:1207
const double & radius() const
Get the circumradius.
Definition polygon.H:1200
Point rightmost_point() const
Get the rightmost point of the bounding circle.
Definition polygon.H:1393
Represents a line segment between two points.
Definition point.H:837
void rotate(const Geom_Number &angle)
Rotates the segment by a given angle around its source point.
Definition point.H:1431
const Point & get_tgt_point() const noexcept
Gets the target point of the segment.
Definition point.H:933
const Point & get_src_point() const noexcept
Gets the source point of the segment.
Definition point.H:924
A non-degenerate triangle defined by three points.
Definition point.H:1512
A vertex in a polygon's doubly linked vertex list.
Definition polygon.H:120
Vertex(const Vertex &vertex)
Copy constructor.
Definition polygon.H:134
Vertex(const Point &point)
Construct a vertex from a Point.
Definition polygon.H:127
const Vertex & prev_vertex() const
Get the previous vertex in the polygon.
Definition polygon.H:177
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:168
static Vertex * dlink_to_vertex(Dlink *link)
Convert a Dlink pointer to a Vertex pointer.
Definition polygon.H:160
Vertex & operator=(const Vertex &vertex)
Copy assignment operator.
Definition polygon.H:142
const Vertex & next_vertex() const
Get the next vertex in the polygon.
Definition polygon.H:190
Point to_point() const
Return this vertex as a plain Point value.
Definition polygon.H:151
Common methods to the Aleph-w ( ) containers.
Definition ah-dry.H:658
and
Conditional mapping of the elements of the container.
Definition ah-dry.H:1137
Common sequential searching methods on containers.
Definition ah-dry.H:200
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:4081
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
static mpfr_t y
Definition mpfr_mul_d.c:3
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
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:2886
bool on_segment(const Segment &s, const Point &p)
Return true if p lies on segment s (exact).
Definition point.H:2961
Orientation orientation(const Point &a, const Point &b, const Point &c)
Return the orientation of the triple (a, b, c).
Definition point.H:2902
mpq_class Geom_Number
Numeric type used by the geometry module.
Definition point.H:113
std::ostream & operator<<(std::ostream &osObject, const Field< T > &rightOp)
Definition ahField.H:121
constexpr double PI
Definition point.H:129
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:206
Iterator over the vertices of a polygon.
Definition polygon.H:490
Vertex_Iterator(const Polygon &poly)
Construct iterator from a polygon.
Definition polygon.H:494
Vertex & get_current_vertex() const
Get the current vertex.
Definition polygon.H:501
Generic traversal of the container through its iterator.
Definition ah-dry.H:71