Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
polygon_test.cc
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
46#include <gtest/gtest.h>
47#include <cmath>
48#include <vector>
49#include <polygon.H>
50
51using namespace Aleph;
52
53// Tolerance for floating-point comparisons
54constexpr double EPSILON = 1e-6;
55
56// Helper to compare Geom_Number with tolerance
57bool approx_equal(const Geom_Number & a, const Geom_Number & b,
58 double tol = EPSILON)
59{
60 return std::abs(a.get_d() - b.get_d()) < tol;
61}
62
63// Helper to compare Points
64bool points_equal(const Point & a, const Point & b, double tol = EPSILON)
65{
66 return approx_equal(a.get_x(), b.get_x(), tol) &&
67 approx_equal(a.get_y(), b.get_y(), tol);
68}
69
70//============================================================================
71// Vertex Class Tests
72//============================================================================
73
74class VertexTest : public ::testing::Test
75{
76protected:
77 void SetUp() override
78 {
79 p1 = Point(10, 20);
80 p2 = Point(30, 40);
81 }
82
83 Point p1, p2;
84};
85
87{
88 Vertex v;
89 EXPECT_EQ(v.get_x(), 0);
90 EXPECT_EQ(v.get_y(), 0);
91}
92
94{
95 Vertex v(p1);
96 EXPECT_EQ(v.get_x(), p1.get_x());
97 EXPECT_EQ(v.get_y(), p1.get_y());
98}
99
101{
102 Vertex v1(p1);
103 Vertex v2(v1);
104
105 EXPECT_EQ(v2.get_x(), v1.get_x());
106 EXPECT_EQ(v2.get_y(), v1.get_y());
107}
108
110{
111 Vertex v1(p1);
112 Vertex v2(p2);
113
114 v2 = v1;
115
116 EXPECT_EQ(v2.get_x(), v1.get_x());
117 EXPECT_EQ(v2.get_y(), v1.get_y());
118}
119
121{
122 Vertex v(p1);
123 v = v;
124
125 EXPECT_EQ(v.get_x(), p1.get_x());
126 EXPECT_EQ(v.get_y(), p1.get_y());
127}
128
130{
131 Vertex v(p1);
132 Dlink * link = &v;
133
135 EXPECT_EQ(recovered, &v);
136 EXPECT_EQ(recovered->get_x(), p1.get_x());
137}
138
140{
141 const Vertex v(p1);
142 const Dlink * link = &v;
143
145 EXPECT_EQ(recovered, &v);
146 EXPECT_EQ(recovered->get_x(), p1.get_x());
147}
148
149//============================================================================
150// Polygon Construction Tests
151//============================================================================
152
153class PolygonConstructionTest : public ::testing::Test
154{
155protected:
157 {
158 Polygon poly;
159 poly.add_vertex(Point(0, 0));
160 poly.add_vertex(Point(100, 0));
161 poly.add_vertex(Point(100, 100));
162 poly.add_vertex(Point(0, 100));
163 poly.close();
164 return poly;
165 }
166
168 {
169 Polygon poly;
170 poly.add_vertex(Point(0, 0));
171 poly.add_vertex(Point(100, 0));
172 poly.add_vertex(Point(50, 100));
173 poly.close();
174 return poly;
175 }
176};
177
184
186{
187 Polygon poly;
188 poly.add_vertex(Point(10, 20));
189
190 EXPECT_EQ(poly.size(), 1u);
191 EXPECT_FALSE(poly.is_closed());
192}
193
195{
196 Polygon poly;
197 poly.add_vertex(Point(0, 0));
198 poly.add_vertex(Point(100, 0));
199 poly.add_vertex(Point(100, 100));
200
201 EXPECT_EQ(poly.size(), 3u);
202 EXPECT_FALSE(poly.is_closed());
203}
204
206{
207 Polygon poly = create_triangle();
208
209 EXPECT_EQ(poly.size(), 3u);
210 EXPECT_TRUE(poly.is_closed());
211}
212
214{
215 Polygon poly = create_triangle();
216
217 EXPECT_THROW(poly.add_vertex(Point(50, 50)), std::domain_error);
218}
219
221{
222 Polygon poly = create_triangle();
223
224 EXPECT_THROW(poly.close(), std::domain_error);
225}
226
228{
229 Polygon original = create_square();
231
232 EXPECT_EQ(copy.size(), original.size());
233 EXPECT_EQ(copy.is_closed(), original.is_closed());
234 EXPECT_TRUE(points_equal(copy.lowest_point(), original.lowest_point()));
235}
236
238{
239 Polygon original = create_square();
240 size_t orig_size = original.size();
241
242 Polygon moved(std::move(original));
243
245 EXPECT_TRUE(moved.is_closed());
246 EXPECT_EQ(original.size(), 0u); // NOLINT - testing moved-from state
247}
248
250{
251 Polygon poly1 = create_square();
253
254 poly2 = poly1;
255
257 EXPECT_EQ(poly2.is_closed(), poly1.is_closed());
258}
259
261{
262 Polygon poly1 = create_square();
263 size_t orig_size = poly1.size();
265
266 poly2 = std::move(poly1);
267
269 EXPECT_TRUE(poly2.is_closed());
270}
271
273{
274 Polygon poly = create_square();
275 poly = poly;
276
277 EXPECT_EQ(poly.size(), 4u);
278 EXPECT_TRUE(poly.is_closed());
279}
280
282{
283 Polygon poly;
284 poly.add_vertex(Geom_Number(50), Geom_Number(75));
285
286 EXPECT_EQ(poly.size(), 1u);
287 EXPECT_EQ(poly.get_first_vertex().get_x(), 50);
288 EXPECT_EQ(poly.get_first_vertex().get_y(), 75);
289}
290
291//============================================================================
292// Polygon Extreme Points Tests
293//============================================================================
294
295class PolygonExtremePointsTest : public ::testing::Test {};
296
298{
299 Polygon poly;
300 poly.add_vertex(Point(50, 75));
301
302 EXPECT_EQ(poly.lowest_point().get_x(), 50);
303 EXPECT_EQ(poly.lowest_point().get_y(), 75);
304 EXPECT_EQ(poly.highest_point().get_y(), 75);
305 EXPECT_EQ(poly.leftmost_point().get_x(), 50);
306 EXPECT_EQ(poly.rightmost_point().get_x(), 50);
307}
308
310{
311 Polygon poly;
312 poly.add_vertex(Point(10, 20));
313 poly.add_vertex(Point(100, 5));
314 poly.add_vertex(Point(50, 150));
315 poly.add_vertex(Point(-20, 80));
316
317 EXPECT_EQ(poly.lowest_point().get_y(), 5);
318 EXPECT_EQ(poly.highest_point().get_y(), 150);
319 EXPECT_EQ(poly.leftmost_point().get_x(), -20);
320 EXPECT_EQ(poly.rightmost_point().get_x(), 100);
321}
322
324{
325 Polygon poly;
326 poly.add_vertex(Point(-100, -100));
327 poly.add_vertex(Point(100, -100));
328 poly.add_vertex(Point(100, 100));
329 poly.add_vertex(Point(-100, 100));
330
331 EXPECT_EQ(poly.lowest_point().get_y(), -100);
332 EXPECT_EQ(poly.highest_point().get_y(), 100);
333 EXPECT_EQ(poly.leftmost_point().get_x(), -100);
334 EXPECT_EQ(poly.rightmost_point().get_x(), 100);
335}
336
337//============================================================================
338// Polygon Vertex Access Tests
339//============================================================================
340
341class PolygonVertexAccessTest : public ::testing::Test
342{
343protected:
344 void SetUp() override
345 {
346 poly.add_vertex(Point(0, 0));
347 poly.add_vertex(Point(100, 0));
348 poly.add_vertex(Point(100, 100));
349 poly.add_vertex(Point(0, 100));
350 }
351
353};
354
356{
357 const Vertex & first = poly.get_first_vertex();
358 EXPECT_EQ(first.get_x(), 0);
359 EXPECT_EQ(first.get_y(), 0);
360}
361
363{
364 const Vertex & last = poly.get_last_vertex();
365 EXPECT_EQ(last.get_x(), 0);
366 EXPECT_EQ(last.get_y(), 100);
367}
368
374
380
382{
383 const Vertex & first = poly.get_first_vertex();
384 EXPECT_TRUE(poly.vertex_belong_polygon(first));
385}
386
388{
389 Vertex external(Point(999, 999));
390 EXPECT_FALSE(poly.vertex_belong_polygon(external));
391}
392
394{
395 const Vertex & first = poly.get_first_vertex();
396 const Vertex & next = poly.get_next_vertex(first);
397
398 EXPECT_EQ(next.get_x(), 100);
399 EXPECT_EQ(next.get_y(), 0);
400}
401
403{
404 const Vertex & last = poly.get_last_vertex();
405 const Vertex & prev = poly.get_prev_vertex(last);
406
407 EXPECT_EQ(prev.get_x(), 100);
408 EXPECT_EQ(prev.get_y(), 100);
409}
410
411//============================================================================
412// Polygon Segment Access Tests
413//============================================================================
414
415class PolygonSegmentAccessTest : public ::testing::Test
416{
417protected:
418 void SetUp() override
419 {
420 poly.add_vertex(Point(0, 0));
421 poly.add_vertex(Point(100, 0));
422 poly.add_vertex(Point(100, 100));
423 }
424
426};
427
429{
430 Segment first = poly.get_first_segment();
431
433 EXPECT_TRUE(points_equal(first.get_tgt_point(), Point(100, 0)));
434}
435
437{
438 Segment last = poly.get_last_segment();
439
441 EXPECT_TRUE(points_equal(last.get_tgt_point(), Point(100, 100)));
442}
443
445{
447 single.add_vertex(Point(0, 0));
448
449 EXPECT_THROW(single.get_first_segment(), std::domain_error);
450}
451
457
458//============================================================================
459// Polygon Vertex Iterator Tests
460//============================================================================
461
462class PolygonVertexIteratorTest : public ::testing::Test
463{
464protected:
465 void SetUp() override
466 {
467 poly.add_vertex(Point(0, 0));
468 poly.add_vertex(Point(100, 0));
469 poly.add_vertex(Point(100, 100));
470 poly.add_vertex(Point(0, 100));
471 }
472
474};
475
477{
478 size_t count = 0;
479 for (Polygon::Vertex_Iterator it(poly); it.has_curr(); it.next_ne())
480 ++count;
481
482 EXPECT_EQ(count, 4u);
483}
484
486{
488 Vertex & v = it.get_current_vertex();
489
490 EXPECT_EQ(v.get_x(), 0);
491 EXPECT_EQ(v.get_y(), 0);
492}
493
495{
496 Polygon empty;
497 EXPECT_THROW(Polygon::Vertex_Iterator it(empty), std::domain_error);
498}
499
500//============================================================================
501// Polygon Segment Iterator Tests
502//============================================================================
503
504class PolygonSegmentIteratorTest : public ::testing::Test
505{
506protected:
507 void SetUp() override
508 {
509 poly.add_vertex(Point(0, 0));
510 poly.add_vertex(Point(100, 0));
511 poly.add_vertex(Point(100, 100));
512 poly.add_vertex(Point(0, 100));
513 }
514
516};
517
519{
520 // poly is not closed, so 4 vertices = 3 segments
521 size_t count = 0;
522 for (Polygon::Segment_Iterator it(poly); it.has_curr(); it.next_ne())
523 ++count;
524
525 EXPECT_EQ(count, 3u);
526}
527
529{
530 poly.close();
531
532 size_t count = 0;
533 for (Polygon::Segment_Iterator it(poly); it.has_curr(); it.next_ne())
534 ++count;
535
536 EXPECT_EQ(count, 4u);
537}
538
547
553
561
562//============================================================================
563// Polygon Intersection Tests
564//============================================================================
565
566class PolygonIntersectionTest : public ::testing::Test
567{
568protected:
569 void SetUp() override
570 {
571 square.add_vertex(Point(0, 0));
572 square.add_vertex(Point(100, 0));
573 square.add_vertex(Point(100, 100));
574 square.add_vertex(Point(0, 100));
575 square.close();
576 }
577
579};
580
582{
583 Segment cross(Point(-50, 50), Point(150, 50));
584 EXPECT_TRUE(square.intersects_with(cross));
585}
586
588{
589 Segment outside(Point(200, 0), Point(200, 100));
590 EXPECT_FALSE(square.intersects_with(outside));
591}
592
594{
595 Segment inside(Point(25, 25), Point(75, 75));
596 EXPECT_FALSE(square.intersects_with(inside));
597}
598
599//============================================================================
600// Polygon Self-Intersection Prevention Tests
601//============================================================================
602
603class PolygonSelfIntersectionTest : public ::testing::Test {};
604
606{
607 Polygon poly;
609 poly.add_vertex(Point(0, 0));
610 poly.add_vertex(Point(100, 0));
611 poly.add_vertex(Point(100, 100));
612 poly.add_vertex(Point(0, 100));
613 poly.close();
614 });
615}
616
618{
619 Polygon poly;
620 poly.add_vertex(Point(0, 0));
621 poly.add_vertex(Point(100, 0));
622 poly.add_vertex(Point(100, 100));
623 poly.add_vertex(Point(0, 100));
624
625 // Adding a vertex that would create a crossing edge
626 EXPECT_THROW(poly.add_vertex(Point(150, -50)), std::domain_error);
627}
628
630{
631 // Create a polygon where adding a vertex causes self-intersection
632 // Shape: Start at (0,0), go right to (100,0), up to (100,100),
633 // then diagonally down-left toward (-50, 50)
634 Polygon poly;
635 poly.add_vertex(Point(0, 0));
636 poly.add_vertex(Point(100, 0));
637 poly.add_vertex(Point(100, 100));
638 poly.add_vertex(Point(-50, 50));
639
640 // Adding (50, -50) would create an edge from (-50, 50) to (50, -50)
641 // which crosses the edge (0, 0) -> (100, 0)
642 EXPECT_THROW(poly.add_vertex(Point(50, -50)), std::domain_error);
643}
644
645//============================================================================
646// Polygon Colinearity Tests
647//============================================================================
648
649class PolygonColinearityTest : public ::testing::Test {};
650
652{
653 Polygon poly;
654 poly.add_vertex(Point(0, 0));
655 poly.add_vertex(Point(50, 0)); // Will be replaced
656 poly.add_vertex(Point(100, 0)); // Colinear, replaces previous
657
658 // Only 2 vertices: colinear point replaced the previous one
659 EXPECT_EQ(poly.size(), 2u);
660}
661
663{
664 Polygon poly;
665 poly.add_vertex(Point(0, 0));
666 poly.add_vertex(Point(100, 0));
667
668 // Point inside the last segment
669 EXPECT_THROW(poly.add_vertex(Point(50, 0)), std::domain_error);
670}
671
672//============================================================================
673// Polygon Containment Tests
674//============================================================================
675
676class PolygonContainmentTest : public ::testing::Test
677{
678protected:
679 void SetUp() override
680 {
681 // Create a square 0-100 x 0-100
682 square.add_vertex(Point(0, 0));
683 square.add_vertex(Point(100, 0));
684 square.add_vertex(Point(100, 100));
685 square.add_vertex(Point(0, 100));
686 square.close();
687 }
688
690};
691
693{
694 Point inside(50, 50);
695 EXPECT_TRUE(square.contains_to(inside));
696}
697
699{
700 Point outside(200, 200);
701 EXPECT_FALSE(square.contains_to(outside));
702}
703
705{
706 Point near_edge(1, 50); // Just inside left edge
707 EXPECT_TRUE(square.contains_to(near_edge));
708}
709
711{
712 Polygon open;
713 open.add_vertex(Point(0, 0));
714 open.add_vertex(Point(100, 0));
715 open.add_vertex(Point(100, 100));
716
717 EXPECT_THROW(open.contains_to(Point(50, 50)), std::domain_error);
718}
719
720//============================================================================
721// Polygon Remove Vertex Tests
722//============================================================================
723
724class PolygonRemoveVertexTest : public ::testing::Test
725{
726protected:
727 void SetUp() override
728 {
729 poly.add_vertex(Point(0, 0));
730 poly.add_vertex(Point(100, 0));
731 poly.add_vertex(Point(100, 100));
732 poly.add_vertex(Point(0, 100));
733 }
734
736};
737
739{
740 const Vertex & v = poly.get_first_vertex();
741 poly.remove_vertex(v);
742
743 EXPECT_EQ(poly.size(), 3u);
744}
745
747{
748 Vertex external(Point(999, 999));
749 EXPECT_THROW(poly.remove_vertex(external), std::domain_error);
750}
751
752//============================================================================
753// Polygon from Triangle Tests
754//============================================================================
755
756class PolygonFromTriangleTest : public ::testing::Test {};
757
759{
760 Triangle tr(Point(0, 0), Point(100, 0), Point(50, 100));
761 Polygon poly(tr);
762
763 EXPECT_EQ(poly.size(), 3u);
764 EXPECT_TRUE(poly.is_closed());
765}
766
768{
769 // Use non-colinear points
770 Triangle tr(Point(0, 0), Point(100, 0), Point(50, 87));
771 Polygon poly(tr);
772
773 EXPECT_EQ(poly.size(), 3u);
774 EXPECT_TRUE(poly.is_closed());
775
776 // Verify that the polygon contains the centroid of the triangle
777 Point centroid(50, 29); // Approximately (0+100+50)/3, (0+0+87)/3
779}
780
781//============================================================================
782// Regular Polygon Construction Tests
783//============================================================================
784
785class RegularPolygonConstructionTest : public ::testing::Test {};
786
793
795{
796 Regular_Polygon tri(Point(0, 0), 100.0, 3);
797
798 EXPECT_EQ(tri.size(), 3u);
799 EXPECT_TRUE(tri.is_closed());
800 EXPECT_NEAR(tri.get_side_size(), 100.0, EPSILON);
801}
802
804{
805 Regular_Polygon sq(Point(0, 0), 100.0, 4);
806
807 EXPECT_EQ(sq.size(), 4u);
808 EXPECT_NEAR(sq.get_side_size(), 100.0, EPSILON);
809}
810
812{
813 Regular_Polygon hex(Point(100, 100), 50.0, 6);
814
815 EXPECT_EQ(hex.size(), 6u);
816 EXPECT_TRUE(points_equal(hex.get_center(), Point(100, 100)));
817}
818
820{
821 EXPECT_THROW(Regular_Polygon(Point(0, 0), 100.0, 2), std::domain_error);
822 EXPECT_THROW(Regular_Polygon(Point(0, 0), 100.0, 1), std::domain_error);
823 EXPECT_THROW(Regular_Polygon(Point(0, 0), 100.0, 0), std::domain_error);
824}
825
827{
828 // For a regular hexagon with side s, the circumradius r = s
829 Regular_Polygon hex(Point(0, 0), 100.0, 6);
830 EXPECT_NEAR(hex.radius(), 100.0, EPSILON);
831}
832
833//============================================================================
834// Regular Polygon Vertex Access Tests
835//============================================================================
836
837class RegularPolygonVertexTest : public ::testing::Test
838{
839protected:
840 void SetUp() override
841 {
842 // Hexagon centered at origin with side 100
843 hex = std::make_unique<Regular_Polygon>(Point(0, 0), 100.0, 6);
844 }
845
846 std::unique_ptr<Regular_Polygon> hex;
847};
848
850{
851 for (size_t i = 0; i < hex->size(); ++i)
852 EXPECT_NO_THROW(hex->get_vertex(i));
853}
854
856{
857 EXPECT_THROW(hex->get_vertex(6), std::out_of_range);
858 EXPECT_THROW(hex->get_vertex(100), std::out_of_range);
859}
860
862{
863 Point first = hex->get_first_vertex();
864 Point vertex0 = hex->get_vertex(0);
865
867}
868
870{
871 Point last = hex->get_last_vertex();
872 Point vertex5 = hex->get_vertex(5);
873
875}
876
878{
879 double r = hex->radius();
880
881 for (size_t i = 0; i < hex->size(); ++i)
882 {
883 Point v = hex->get_vertex(i);
884 Point center = hex->get_center();
885 double dist = std::sqrt(
886 std::pow(v.get_x().get_d() - center.get_x().get_d(), 2) +
887 std::pow(v.get_y().get_d() - center.get_y().get_d(), 2)
888 );
889 EXPECT_NEAR(dist, r, EPSILON);
890 }
891}
892
893//============================================================================
894// Regular Polygon Segment Access Tests
895//============================================================================
896
897class RegularPolygonSegmentTest : public ::testing::Test
898{
899protected:
900 void SetUp() override
901 {
902 // Square centered at origin
903 sq = std::make_unique<Regular_Polygon>(Point(0, 0), 100.0, 4);
904 }
905
906 std::unique_ptr<Regular_Polygon> sq;
907};
908
910{
911 Segment first = sq->get_first_segment();
912 Point vertex0 = sq->get_vertex(0);
913 Point vertex1 = sq->get_vertex(1);
914
917}
918
920{
921 Segment last = sq->get_last_segment();
922 Point vertex0 = sq->get_vertex(0);
923 Point vertex3 = sq->get_vertex(3);
924
927}
928
930{
931 double expected = sq->get_side_size();
932
933 for (size_t i = 0; i < sq->size(); ++i)
934 {
935 Point v1 = sq->get_vertex(i);
936 Point v2 = sq->get_vertex((i + 1) % sq->size());
937
938 Segment s(v1, v2);
939 EXPECT_NEAR(s.size().get_d(), expected, 0.01); // Larger tolerance for floating point
940 }
941}
942
943//============================================================================
944// Regular Polygon Vertex Iterator Tests
945//============================================================================
946
947class RegularPolygonVertexIteratorTest : public ::testing::Test
948{
949protected:
950 void SetUp() override
951 {
952 pentagon = std::make_unique<Regular_Polygon>(Point(0, 0), 50.0, 5);
953 }
954
955 std::unique_ptr<Regular_Polygon> pentagon;
956};
957
959{
960 size_t count = 0;
961 for (Regular_Polygon::Vertex_Iterator it(*pentagon); it.has_curr(); it.next())
962 ++count;
963
964 EXPECT_EQ(count, 5u);
965}
966
975
977{
979 for (size_t i = 0; i < 5; ++i)
980 it.next_ne();
981
983 EXPECT_THROW(it.next(), std::overflow_error);
984}
985
987{
989 for (size_t i = 0; i < 5; ++i)
990 it.next_ne();
991
992 EXPECT_THROW(it.get_current_vertex(), std::overflow_error);
993}
994
995//============================================================================
996// Regular Polygon Segment Iterator Tests
997//============================================================================
998
999class RegularPolygonSegmentIteratorTest : public ::testing::Test
1000{
1001protected:
1002 void SetUp() override
1003 {
1004 triangle = std::make_unique<Regular_Polygon>(Point(0, 0), 100.0, 3);
1005 }
1006
1007 std::unique_ptr<Regular_Polygon> triangle;
1008};
1009
1011{
1012 size_t count = 0;
1013 for (Regular_Polygon::Segment_Iterator it(*triangle); it.has_curr(); it.next())
1014 ++count;
1015
1016 EXPECT_EQ(count, 3u);
1017}
1018
1020{
1023
1024 Point v0 = triangle->get_vertex(0);
1025 Point v1 = triangle->get_vertex(1);
1026
1029}
1030
1032{
1034 for (size_t i = 0; i < 3; ++i)
1035 it.next_ne();
1036
1037 EXPECT_FALSE(it.has_curr());
1038 EXPECT_THROW(it.next(), std::overflow_error);
1039}
1040
1042{
1044 for (size_t i = 0; i < 3; ++i)
1045 it.next_ne();
1046
1047 EXPECT_THROW(it.get_current_segment(), std::overflow_error);
1048}
1049
1050//============================================================================
1051// Regular Polygon Extreme Points Tests
1052//============================================================================
1053
1054class RegularPolygonExtremePointsTest : public ::testing::Test
1055{
1056protected:
1057 void SetUp() override
1058 {
1059 // Hexagon centered at (100, 100) with radius ~100
1060 hex = std::make_unique<Regular_Polygon>(Point(100, 100), 100.0, 6);
1061 }
1062
1063 std::unique_ptr<Regular_Polygon> hex;
1064};
1065
1067{
1068 Point lowest = hex->lowest_point();
1069 Point center = hex->get_center();
1070 double r = hex->radius();
1071
1072 EXPECT_TRUE(points_equal(lowest, center + Point(0, -r)));
1073}
1074
1076{
1077 Point highest = hex->highest_point();
1078 Point center = hex->get_center();
1079 double r = hex->radius();
1080
1081 EXPECT_TRUE(points_equal(highest, center + Point(0, r)));
1082}
1083
1085{
1086 Point leftmost = hex->leftmost_point();
1087 Point center = hex->get_center();
1088 double r = hex->radius();
1089
1090 EXPECT_TRUE(points_equal(leftmost, center + Point(-r, 0)));
1091}
1092
1094{
1095 Point rightmost = hex->rightmost_point();
1096 Point center = hex->get_center();
1097 double r = hex->radius();
1098
1099 EXPECT_TRUE(points_equal(rightmost, center + Point(r, 0)));
1100}
1101
1102//============================================================================
1103// Regular Polygon Rotation Tests
1104//============================================================================
1105
1106class RegularPolygonRotationTest : public ::testing::Test {};
1107
1109{
1110 Regular_Polygon sq(Point(0, 0), 100.0, 4, 0);
1111
1112 // First vertex should be at the "south" position (negative y)
1113 Point v0 = sq.get_vertex(0);
1114 EXPECT_LT(v0.get_y().get_d(), 0); // Below center
1115 EXPECT_NEAR(v0.get_x().get_d(), 0, 0.1); // On vertical axis
1116}
1117
1119{
1120 Regular_Polygon sq1(Point(0, 0), 100.0, 4, 0);
1121 Regular_Polygon sq2(Point(0, 0), 100.0, 4, PI / 4); // 45 degree rotation
1122
1123 // First vertex of rotated polygon should be different from non-rotated
1124 Point v0_orig = sq1.get_vertex(0);
1125 Point v0_rot = sq2.get_vertex(0);
1126
1127 // The x-coordinate should change after rotation
1128 EXPECT_FALSE(approx_equal(v0_orig.get_x(), v0_rot.get_x(), 0.1));
1129}
1130
1132{
1133 // Rotated hexagon should still have all vertices equidistant from center
1134 Regular_Polygon hex(Point(0, 0), 100.0, 6, PI / 6); // 30 degree rotation
1135 double r = hex.radius();
1136
1137 for (size_t i = 0; i < hex.size(); ++i)
1138 {
1139 Point v = hex.get_vertex(i);
1140 double dist = std::sqrt(
1141 std::pow(v.get_x().get_d(), 2) + std::pow(v.get_y().get_d(), 2)
1142 );
1143 EXPECT_NEAR(dist, r, 0.001);
1144 }
1145}
1146
1147//============================================================================
1148// Polygon from Regular Polygon Tests
1149//============================================================================
1150
1151class PolygonFromRegularTest : public ::testing::Test {};
1152
1154{
1155 Regular_Polygon hex(Point(100, 100), 50.0, 6);
1156 Polygon poly(hex);
1157
1158 EXPECT_EQ(poly.size(), 6u);
1159 EXPECT_TRUE(poly.is_closed());
1160}
1161
1163{
1164 Regular_Polygon sq(Point(0, 0), 100.0, 4);
1165 Polygon poly;
1166
1167 poly = sq;
1168
1169 EXPECT_EQ(poly.size(), 4u);
1170 EXPECT_TRUE(poly.is_closed());
1171}
1172
1174{
1175 Regular_Polygon tri(Point(0, 0), 100.0, 3);
1176 Polygon poly(tri);
1177
1178 // Both should have same number of vertices
1179 EXPECT_EQ(poly.size(), tri.size());
1180
1181 // Verify each vertex
1182 size_t i = 0;
1183 for (Polygon::Vertex_Iterator it(poly); it.has_curr(); it.next_ne(), ++i)
1184 {
1185 Point polyV = it.get_current_vertex();
1186 Point regV = tri.get_vertex(i);
1188 }
1189}
1190
1191//============================================================================
1192// Type Traits and Noexcept Tests
1193//============================================================================
1194
1196{
1197 EXPECT_TRUE(std::is_nothrow_move_constructible<Polygon>::value);
1198}
1199
1201{
1202 EXPECT_TRUE(std::is_nothrow_move_assignable<Polygon>::value);
1203}
1204
1205//============================================================================
1206// Edge Cases and Stress Tests
1207//============================================================================
1208
1210{
1211 Polygon poly;
1212 const size_t N = 1000;
1213
1214 // Create a circle-like polygon with N vertices
1215 for (size_t i = 0; i < N; ++i)
1216 {
1217 double angle = 2.0 * PI * i / N;
1218 double x = 1000.0 * cos(angle);
1219 double y = 1000.0 * sin(angle);
1220 poly.add_vertex(Point(x, y));
1221 }
1222 poly.close();
1223
1224 EXPECT_EQ(poly.size(), N);
1225 EXPECT_TRUE(poly.is_closed());
1226
1227 // Containment test should work
1228 EXPECT_TRUE(poly.contains_to(Point(0, 0)));
1229 EXPECT_FALSE(poly.contains_to(Point(2000, 2000)));
1230}
1231
1233{
1234 Regular_Polygon poly(Point(0, 0), 100.0, 100);
1235
1236 EXPECT_EQ(poly.size(), 100u);
1237
1238 // All vertices should be at the same distance from center
1239 double r = poly.radius();
1240 for (size_t i = 0; i < poly.size(); ++i)
1241 {
1242 Point v = poly.get_vertex(i);
1243 double dist = std::sqrt(
1244 std::pow(v.get_x().get_d(), 2) + std::pow(v.get_y().get_d(), 2)
1245 );
1246 EXPECT_NEAR(dist, r, 0.001);
1247 }
1248}
1249
1251{
1252 Polygon poly;
1253 poly.add_vertex(Point(0.0001, 0.0001));
1254 poly.add_vertex(Point(0.0002, 0.0001));
1255 poly.add_vertex(Point(0.00015, 0.0002));
1256 poly.close();
1257
1258 EXPECT_EQ(poly.size(), 3u);
1259 EXPECT_TRUE(poly.is_closed());
1260}
1261
1263{
1264 Polygon poly;
1265 poly.add_vertex(Point(-1000, -1000));
1266 poly.add_vertex(Point(-500, -1000));
1267 poly.add_vertex(Point(-500, -500));
1268 poly.add_vertex(Point(-1000, -500));
1269 poly.close();
1270
1271 EXPECT_TRUE(poly.contains_to(Point(-750, -750)));
1272 EXPECT_FALSE(poly.contains_to(Point(0, 0)));
1273}
1274
1275//============================================================================
1276// Main
1277//============================================================================
1278
1279int main(int argc, char **argv)
1280{
1281 ::testing::InitGoogleTest(&argc, argv);
1282 return RUN_ALL_TESTS();
1283}
int main()
Graph create_triangle()
Creates a triangle (K_3) - the simplest non-bipartite graph.
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
Rectangular point in the plane.
Definition point.H:156
const Geom_Number & get_y() const
Returns y value.
Definition point.H:226
const Point & highest_point() const
Definition point.H:321
const Point & leftmost_point() const
Definition point.H:325
const Point & rightmost_point() const
Definition point.H:327
const Point & lowest_point() const
Definition point.H:323
const Geom_Number & get_x() const
Returns x value.
Definition point.H:221
void SetUp() override
Iterator over the edges (segments) of a polygon.
Definition polygon.H:451
Segment get_current_segment() const
Get the current segment (edge).
Definition polygon.H:479
bool has_curr() const
Check if there is a current segment.
Definition polygon.H:468
A general (irregular) 2D polygon defined by a sequence of vertices.
Definition polygon.H:233
Segment get_first_segment()
Get the first edge (segment) of the polygon.
Definition polygon.H:556
void close()
Close the polygon.
Definition polygon.H:710
const Vertex & get_last_vertex() const
Get the last vertex of the polygon.
Definition polygon.H:521
const Point & rightmost_point() const
Get the vertex with the maximum x-coordinate.
Definition polygon.H:399
const bool & is_closed() const
Check if the polygon is closed.
Definition polygon.H:403
const size_t & size() const
Get the number of vertices.
Definition polygon.H:407
const Point & leftmost_point() const
Get the vertex with the minimum x-coordinate.
Definition polygon.H:395
const Vertex & get_first_vertex() const
Get the first vertex of the polygon.
Definition polygon.H:510
void add_vertex(const Point &point)
Add a vertex to the polygon.
Definition polygon.H:610
const Point & highest_point() const
Get the vertex with the maximum y-coordinate.
Definition polygon.H:391
bool contains_to(const Point &p)
Check if a point is inside the polygon.
Definition polygon.H:751
const Point & lowest_point() const
Get the vertex with the minimum y-coordinate.
Definition polygon.H:387
std::unique_ptr< Regular_Polygon > hex
std::unique_ptr< Regular_Polygon > triangle
std::unique_ptr< Regular_Polygon > sq
std::unique_ptr< Regular_Polygon > pentagon
std::unique_ptr< Regular_Polygon > hex
Iterator over the edges (segments) of a regular polygon.
Definition polygon.H:1010
void next_ne() noexcept
Advance to next segment (no exception on overflow).
Definition polygon.H:1040
const Segment get_current_segment() const
Get the current segment (edge).
Definition polygon.H:1030
void next()
Advance to next segment.
Definition polygon.H:1044
bool has_curr() const
Check if there is a current segment.
Definition polygon.H:1025
Iterator over the vertices of a regular polygon.
Definition polygon.H:944
bool has_curr() const
Check if there is a current vertex.
Definition polygon.H:960
void next_ne() noexcept
Advance to next vertex (no exception on overflow).
Definition polygon.H:976
Vertex & get_current_vertex()
Get the current vertex.
Definition polygon.H:965
void next()
Advance to next vertex.
Definition polygon.H:980
A regular polygon defined by center, side length, and vertex count.
Definition polygon.H:829
const Point & get_center() const
Get the center point.
Definition polygon.H:872
const size_t & size() const
Get the number of vertices.
Definition polygon.H:876
const double & get_side_size() const
Get the side length.
Definition polygon.H:868
const Point get_vertex(const size_t &i) const
Get the i-th vertex of the polygon.
Definition polygon.H:895
const double & radius() const
Get the circumradius.
Definition polygon.H:880
Fundamental segment defined by two points.
Definition point.H:417
const Point & get_tgt_point() const
Definition point.H:470
Geom_Number size() const
Return the Euclidean length of the segment (distance between endpoints).
Definition point.H:578
const Point & get_src_point() const
Definition point.H:468
void SetUp() override
A vertex in a polygon's doubly-linked vertex list.
Definition polygon.H:113
static Vertex * dlink_to_vertex(Dlink *link)
Convert a Dlink pointer to a Vertex pointer.
Definition polygon.H:148
#define TEST(name)
#define N
Definition fib.C:294
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_cos_function > > cos(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4069
__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
Itor2 copy(Itor1 sourceBeg, const Itor1 &sourceEnd, Itor2 destBeg)
Copy elements from one range to another.
Definition ahAlgo.H:584
void next()
Advance all underlying iterators (bounds-checked).
Definition ah-zip.H:175
DynList< T > maps(const C &c, Op op)
Classic map operation.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
mpq_class Geom_Number
Numeric type used by the geometry module.
Definition point.H:68
constexpr double PI
Definition point.H:85
2D polygon representation and geometric operations.
bool points_equal(const Point &a, const Point &b, double tol=EPSILON)
constexpr double EPSILON
TEST_F(VertexTest, DefaultConstruction)
bool approx_equal(const Geom_Number &a, const Geom_Number &b, double tol=EPSILON)
Iterator over the vertices of a polygon.
Definition polygon.H:419
Vertex & get_current_vertex()
Get the current vertex.
Definition polygon.H:431