Pangolin
Header-only C++20 plane computational geometry library
Loading...
Searching...
No Matches
samepointset.hpp
Go to the documentation of this file.
1#pragma once
2
4
42
43#include <algorithm>
44#include <compare>
45#include <concepts>
46#include <cstddef>
47#include <optional>
48#include <ranges>
49#include <type_traits>
50#include <utility>
51#include <variant>
52#include <vector>
53
54namespace pgl::detail {
55
63template <AnyShapeConcept First, AnyShapeConcept Second>
64constexpr bool samePointSetAny(const First& first, const Second& second);
65
66// ---------------------------------------------------------------------------
67// Carriers of collapsed shapes
68
70template <class TShape>
71struct shape_point {
72 using type = typename TShape::PointType;
73};
74
75template <class Number, class Label>
76struct shape_point<Point<Number, Label>> {
77 using type = Point<Number, Label>;
78};
79
80template <class TShape>
81using shape_point_t = typename shape_point<std::remove_cvref_t<TShape>>::type;
82
92template <class TShape>
93constexpr auto collapsedPoint(const TShape& shape) {
94 using Shape = std::remove_cvref_t<TShape>;
95 if constexpr (PolygonWithHolesConcept<Shape>) {
96 return shape.outer().getIfPoint();
97 } else if constexpr (PolygonSetConcept<Shape>) {
98 using Result = std::optional<typename Shape::PointType>;
99 if (shape.componentCount() != 1) {
100 return Result{};
101 }
102 return Result(shape.component(0).outer().getIfPoint());
103 } else if constexpr (requires { shape.getIfPoint(); }) {
104 return shape.getIfPoint();
105 } else {
106 return std::optional<shape_point_t<Shape>>{};
107 }
108}
109
114template <class TShape>
115constexpr auto collapsedSegment(const TShape& shape) {
116 using Shape = std::remove_cvref_t<TShape>;
117 if constexpr (PolygonWithHolesConcept<Shape>) {
118 return shape.outer().getIfSegment();
119 } else if constexpr (PolygonSetConcept<Shape>) {
120 using Result = std::optional<Segment<typename Shape::PointType>>;
121 if (shape.componentCount() != 1) {
122 return Result{};
123 }
124 return Result(shape.component(0).outer().getIfSegment());
125 } else if constexpr (requires { shape.getIfSegment(); }) {
126 return shape.getIfSegment();
127 } else {
128 return std::optional<Segment<shape_point_t<Shape>>>{};
129 }
130}
131
139template <class TShape>
140constexpr bool collapsedBelowArea(const TShape& shape) {
141 if constexpr (requires { shape.isPoint(); shape.isSegment(); }) {
142 return shape.isPoint() || shape.isSegment();
143 } else if constexpr (requires { shape.isPoint(); }) {
144 return shape.isPoint();
145 } else {
146 return false;
147 }
148}
149
159template <class TShape, class Predicate>
160constexpr bool reduceCollapsed(const TShape& shape, Predicate predicate) {
161 if (const auto vertex = collapsedPoint(shape)) {
162 return predicate(*vertex);
163 }
164 if (const auto carrier = collapsedSegment(shape)) {
165 return predicate(*carrier);
166 }
167 return false;
168}
169
174template <class First, class Second>
175constexpr bool collapsedMatches(const First& first, const Second& second) {
176 return reduceCollapsed(first, [&second](const auto& carrier) {
177 return samePointSetAny(carrier, second);
178 });
179}
180
189template <HalfplaneIntersectionConcept Region, class Predicate>
190constexpr bool reduceRegionCarrier(const Region& region, Predicate predicate) {
191 if (const auto vertex = region.getIfPoint()) {
192 return predicate(*vertex);
193 }
194 if (const auto carrier = region.getIfSegment()) {
195 return predicate(*carrier);
196 }
197 if (const auto carrier = region.getIfRay()) {
198 return predicate(*carrier);
199 }
200 if (const auto carrier = region.getIfLine()) {
201 return predicate(*carrier);
202 }
203 return false;
204}
205
206// ---------------------------------------------------------------------------
207// The straight primitives
208
210template <class First, class Second>
211constexpr bool sameSegmentPointSet(const First& first, const Second& second) {
212 return first.min() == second.min() && first.max() == second.max();
213}
214
221template <class First, class Second>
222constexpr bool sameLinePointSet(const First& first, const Second& second) {
223 return collinear(first.min(), first.max(), second.min()) &&
224 collinear(first.min(), first.max(), second.max());
225}
226
228template <RayConcept First, RayConcept Second>
229constexpr bool sameRayPointSet(const First& first, const Second& second) {
230 return first.source() == second.source() &&
231 collinear(first.source(), first.target(), second.target()) &&
232 dotSign(first.source(), first.target(), second.source(), second.target()) > 0;
233}
234
243template <class First, class Second>
244constexpr bool sameHalfplanePointSet(const First& first, const Second& second) {
245 return collinear(first.source(), first.target(), second.source()) &&
246 collinear(first.source(), first.target(), second.target()) &&
247 dotSign(first.source(), first.target(), second.source(), second.target()) > 0;
248}
249
252 * `tail -> head`, with the region on its left.
253 *
254 * The half-plane form of @ref sameHalfplanePointSet, for a caller that holds
255 * the boundary as two points rather than as a `Halfplane`.
256 */
257template <class HalfplaneType, class TailPoint, class HeadPoint>
258constexpr bool halfplaneBoundedByEdge(const HalfplaneType& halfplane,
259 const TailPoint& tail,
260 const HeadPoint& head) {
261 return collinear(halfplane.source(), halfplane.target(), tail) &&
262 collinear(halfplane.source(), halfplane.target(), head) &&
263 dotSign(halfplane.source(), halfplane.target(), tail, head) > 0;
264}
265
266// ---------------------------------------------------------------------------
267// Bounded shapes
268
270template <class First, class Second>
271constexpr bool sameBoundingBox(const First& first, const Second& second) {
272 const auto& firstBox = first.bbox();
273 const auto& secondBox = second.bbox();
274 return firstBox.min() == secondBox.min() && firstBox.max() == secondBox.max();
275}
276
277// ---------------------------------------------------------------------------
278// Polygonal rings
279
292template <class First, class Second>
293constexpr bool sameRepresentation(const First& first, const Second& second) {
294 if constexpr (requires { { first == second } -> std::convertible_to<bool>; }) {
295 return first == second;
296 } else {
297 return false;
298 }
299}
300
311template <class Ring>
312constexpr bool subdividingVertex(const Ring& ring, std::size_t index) {
313 const auto position = static_cast<std::ptrdiff_t>(index);
314 const auto previous = ring.get(position - 1);
315 const auto current = ring[index];
316 const auto next = ring.get(position + 1);
317 if (!collinear(previous, current, next)) {
318 return false;
319 }
320 return (previous < current && current < next) || (next < current && current < previous);
321}
322
331template <class Ring>
332constexpr std::size_t nextRingCorner(const Ring& ring, std::size_t index) {
333 const std::size_t count = ring.size();
334 do {
335 index = index + 1 == count ? 0 : index + 1;
336 } while (index != 0 && subdividingVertex(ring, index));
337 return index;
338}
339
352template <class First, class Second>
353constexpr bool sameRingPointSet(const First& first, const Second& second) {
354 if (first.size() < 3 || second.size() < 3) {
355 return false; // no area to enclose
356 }
357 if (sameRepresentation(first, second)) {
358 return true;
359 }
360 if (!(first[0] == second[0])) {
361 return false;
362 }
363 if (first.size() == second.size()) {
364 std::size_t index = 1;
365 while (index < first.size() && first[index] == second[index]) {
366 ++index;
367 }
368 if (index == first.size()) {
369 return true;
370 }
371 }
372 std::size_t here = 0;
373 std::size_t there = 0;
374 for (;;) {
375 here = nextRingCorner(first, here);
376 there = nextRingCorner(second, there);
377 if (here == 0 || there == 0) {
378 return here == there; // one ring ran out of corners before the other
379 }
380 if (!(first[here] == second[there])) {
381 return false;
382 }
383 }
384}
385
390template <class First, class Second>
391constexpr bool sameRingShapes(const First& first, const Second& second) {
392 if (sameRepresentation(first, second)) {
393 return true;
394 }
395 if (!sameBoundingBox(first, second)) {
396 // Four coordinates read straight out of the cached boxes, with no
397 // vertex rebuilt and nothing to overflow.
398 return false;
399 }
400 if (!(first[0] == second[0])) {
401 // The first vertex is the lexicographically smallest one whether the
402 // ring encloses area or has collapsed onto a segment or a point, and
403 // the smallest point of a set is a property of the set. That settles
404 // the rings a shared box let through, before anything asks how either
405 // one is shaped.
406 return false;
407 }
408 if (collapsedBelowArea(first)) {
409 return collapsedMatches(first, second);
410 }
411 if (collapsedBelowArea(second)) {
412 return collapsedMatches(second, first);
413 }
414 return sameRingPointSet(first, second);
415}
416
429template <class FirstRange, class SecondRange, class Compare>
430constexpr bool sameRingCollection(const FirstRange& first, const SecondRange& second, Compare same) {
431 const std::size_t count = first.size();
432 bool aligned = true;
433 for (std::size_t i = 0; i < count; ++i) {
434 if (!same(first[i], second[i])) {
435 aligned = false;
436 break;
437 }
438 }
439 if (aligned) {
440 return true;
441 }
442 for (const auto& ring : first) {
443 bool found = false;
444 for (const auto& candidate : second) {
445 if (same(ring, candidate)) {
446 found = true;
447 break;
448 }
449 }
450 if (!found) {
451 return false;
452 }
453 }
454 return true;
455}
456
466template <PolygonWithHolesConcept First, PolygonWithHolesConcept Second>
467constexpr bool sameRegionRings(const First& first, const Second& second) {
468 if (sameRepresentation(first, second)) {
469 return true;
470 }
471 if (!sameRingPointSet(first.outer(), second.outer())) {
472 return false;
473 }
474 if (first.holeCount() != second.holeCount()) {
475 return false;
476 }
477 return sameRingCollection(first.holes(), second.holes(),
478 [](const auto& one, const auto& other) {
479 return sameRingPointSet(one, other);
480 });
481}
482
483// ---------------------------------------------------------------------------
484// Boundaries
485
495template <class SegmentType, class EdgeRange>
496constexpr bool segmentCoveredByEdges(const SegmentType& segment, const EdgeRange& edges) {
497 using EdgeType = std::ranges::range_value_t<EdgeRange>;
498 using CommonPoint =
499 Point<std::common_type_t<typename SegmentType::PointType::NumberType,
500 typename EdgeType::PointType::NumberType>>;
501
502 const CommonPoint low(segment.min());
503 const CommonPoint high(segment.max());
504 if (low == high) {
505 for (const auto& edge : edges) {
506 if (edge.contains(low)) {
507 return true;
508 }
509 }
510 return false;
511 }
512
513 std::vector<std::pair<CommonPoint, CommonPoint>> overlaps;
514 for (const auto& edge : edges) {
515 if (!collinear(low, high, edge.min()) || !collinear(low, high, edge.max())) {
516 continue; // the edge leaves the segment's supporting line
517 }
518 const CommonPoint lo = (edge.min() < low) ? low : CommonPoint(edge.min());
519 const CommonPoint hi = (high < edge.max()) ? high : CommonPoint(edge.max());
520 if (hi < lo) {
521 continue; // collinear but disjoint from the segment
522 }
523 overlaps.emplace_back(lo, hi);
524 }
525 std::sort(overlaps.begin(), overlaps.end());
526
527 CommonPoint covered = low;
528 for (const auto& [lo, hi] : overlaps) {
529 if (covered < lo) {
530 return false; // the part between covered and lo is off the edges
531 }
532 if (covered < hi) {
533 covered = hi;
534 }
535 }
536 return !(covered < high);
537}
538
552template <class First, class Second>
553constexpr bool sameBoundaryPointSet(const First& first, const Second& second) {
554 const auto firstEdges = first.edges();
555 const auto secondEdges = second.edges();
556 for (const auto& edge : firstEdges) {
557 if (!segmentCoveredByEdges(edge, secondEdges)) {
558 return false;
559 }
560 }
561 for (const auto& edge : secondEdges) {
562 if (!segmentCoveredByEdges(edge, firstEdges)) {
563 return false;
564 }
565 }
566 return true;
567}
568
569// ---------------------------------------------------------------------------
570// Half-plane intersections
571
583template <HalfplaneIntersectionConcept Region, class Ring>
584constexpr bool sameConvexRegionAndRing(const Region& region, const Ring& ring) {
585 if (region.isDegenerate()) {
586 return reduceRegionCarrier(region, [&ring](const auto& carrier) {
587 return samePointSetAny(carrier, ring);
588 });
589 }
590 if (collapsedBelowArea(ring) || !region.isBounded()) {
591 // The region has interior and is unbounded or the ring has neither.
592 return false;
593 }
594 const std::size_t constraints = region.size();
595 if (constraints < 3) {
596 return false; // fewer constraints than that bound nothing
597 }
598
599 // Where the two cyclic sequences start relative to each other is the only
600 // unknown, and the ring's first corner edge locates it.
601 const std::size_t behind = nextRingCorner(ring, 0);
602 std::size_t start = constraints;
603 for (std::size_t i = 0; i < constraints; ++i) {
604 if (halfplaneBoundedByEdge(region[i], ring[0], ring[behind])) {
605 start = i;
606 break;
607 }
608 }
609 if (start == constraints) {
610 return false;
611 }
612
613 // Walking the corners against the constraints also counts them: the ring
614 // has to close after exactly as many corners as there are constraints.
615 std::size_t here = 0;
616 for (std::size_t i = 0; i < constraints; ++i) {
617 const std::size_t next = nextRingCorner(ring, here);
618 if (!halfplaneBoundedByEdge(region[(start + i) % constraints], ring[here], ring[next])) {
619 return false;
620 }
621 here = next;
622 }
623 return here == 0;
624}
625
626// ---------------------------------------------------------------------------
627// Chains
628
633template <class Chain>
634constexpr std::size_t nextChainCorner(const Chain& chain, std::size_t index) {
635 const std::size_t last = chain.size() - 1;
636 do {
637 ++index;
638 } while (index < last && collinear(chain[index - 1], chain[index], chain[index + 1]));
639 return index;
640}
641
651template <MonotoneChainConcept First, MonotoneChainConcept Second>
652constexpr bool sameChainPointSet(const First& first, const Second& second) {
653 if (sameRepresentation(first, second)) {
654 return true;
655 }
656 const std::size_t firstCount = first.size();
657 const std::size_t secondCount = second.size();
658 if (!(first[0] == second[0])) {
659 return false;
660 }
661 if (firstCount == secondCount) {
662 std::size_t index = 1;
663 while (index < firstCount && first[index] == second[index]) {
664 ++index;
665 }
666 if (index == firstCount) {
667 return true;
668 }
669 }
670 std::size_t i = 0;
671 std::size_t j = 0;
672 for (;;) {
673 if (i + 1 == firstCount || j + 1 == secondCount) {
674 return i + 1 == firstCount && j + 1 == secondCount;
675 }
676 i = nextChainCorner(first, i);
677 j = nextChainCorner(second, j);
678 if (!(first[i] == second[j])) {
679 return false;
680 }
681 }
682}
683
695template <class First, class Second>
696constexpr bool samePolylinePointSet(const First& first, const Second& second) {
697 if (!sameBoundingBox(first, second)) {
698 // Both shapes cache their box, and having no canonical first vertex to
699 // compare, this is the O(1) rejection they do have.
700 return false;
701 }
702 if (sameRepresentation(first, second)) {
703 return true;
704 }
705 if (const auto carrier = collapsedSegment(first)) {
706 return samePointSetAny(*carrier, second);
707 }
708 if (const auto carrier = collapsedPoint(first)) {
709 return samePointSetAny(*carrier, second);
710 }
711 if (first.size() == second.size()) {
712 const std::size_t count = first.size();
713 bool forward = true;
714 bool backward = true;
715 for (std::size_t i = 0; i < count; ++i) {
716 forward = forward && first[i] == second[i];
717 backward = backward && first[i] == second[count - 1 - i];
718 }
719 if (forward || backward) {
720 return true;
721 }
722 }
723 return first.contains(second) && second.contains(first);
724}
725
726// ---------------------------------------------------------------------------
727
733
735template <PointConcept First, PointConcept Second>
736constexpr bool samePointSet(const First& first, const Second& second) {
737 return first == second;
738}
739
741template <PointConcept First, SegmentConcept Second>
742constexpr bool samePointSet(const First& first, const Second& second) {
743 return second.min() == second.max() && first == second.min();
744}
745
747template <PointConcept First, OrientedSegmentConcept Second>
748constexpr bool samePointSet(const First& first, const Second& second) {
749 return second.min() == second.max() && first == second.min();
750}
751
753template <PointConcept First, LineConcept Second>
754constexpr bool samePointSet(const First&, const Second&) {
755 return false;
756}
757
759template <PointConcept First, OrientedLineConcept Second>
760constexpr bool samePointSet(const First&, const Second&) {
761 return false;
762}
763
765template <PointConcept First, RayConcept Second>
766constexpr bool samePointSet(const First&, const Second&) {
767 return false;
768}
769
771template <PointConcept First, HalfplaneConcept Second>
772constexpr bool samePointSet(const First&, const Second&) {
773 return false;
774}
775
777template <PointConcept First, RectangleConcept Second>
778constexpr bool samePointSet(const First& first, const Second& second) {
779 return collapsedMatches(second, first);
780}
781
783template <PointConcept First, TriangleConcept Second>
784constexpr bool samePointSet(const First& first, const Second& second) {
785 return collapsedMatches(second, first);
786}
787
789template <PointConcept First, DiskConcept Second>
790constexpr bool samePointSet(const First& first, const Second& second) {
791 return collapsedMatches(second, first);
792}
793
795template <PointConcept First, ConvexConcept Second>
796constexpr bool samePointSet(const First& first, const Second& second) {
797 return collapsedMatches(second, first);
798}
799
801template <PointConcept First, MonotoneChainConcept Second>
802constexpr bool samePointSet(const First& first, const Second& second) {
803 return collapsedMatches(second, first);
804}
805
807template <PointConcept First, PolylineConcept Second>
808constexpr bool samePointSet(const First& first, const Second& second) {
809 return collapsedMatches(second, first);
810}
811
813template <PointConcept First, PolygonConcept Second>
814constexpr bool samePointSet(const First& first, const Second& second) {
815 return collapsedMatches(second, first);
816}
817
819template <PointConcept First, HalfplaneIntersectionConcept Second>
820constexpr bool samePointSet(const First& first, const Second& second) {
821 return collapsedMatches(second, first);
822}
823
825template <PointConcept First, PolygonWithHolesConcept Second>
826constexpr bool samePointSet(const First& first, const Second& second) {
827 return collapsedMatches(second, first);
828}
829
831template <PointConcept First, PolygonSetConcept Second>
832constexpr bool samePointSet(const First& first, const Second& second) {
833 return collapsedMatches(second, first);
834}
835
842
844template <SegmentConcept First, SegmentConcept Second>
845constexpr bool samePointSet(const First& first, const Second& second) {
846 return sameSegmentPointSet(first, second);
847}
848
850template <SegmentConcept First, OrientedSegmentConcept Second>
851constexpr bool samePointSet(const First& first, const Second& second) {
852 return sameSegmentPointSet(first, second);
853}
854
856template <SegmentConcept First, LineConcept Second>
857constexpr bool samePointSet(const First&, const Second&) {
858 return false;
859}
860
862template <SegmentConcept First, OrientedLineConcept Second>
863constexpr bool samePointSet(const First&, const Second&) {
864 return false;
865}
866
868template <SegmentConcept First, RayConcept Second>
869constexpr bool samePointSet(const First&, const Second&) {
870 return false;
871}
872
874template <SegmentConcept First, HalfplaneConcept Second>
875constexpr bool samePointSet(const First&, const Second&) {
876 return false;
877}
878
880template <SegmentConcept First, RectangleConcept Second>
881constexpr bool samePointSet(const First& first, const Second& second) {
882 return collapsedMatches(second, first);
883}
884
886template <SegmentConcept First, TriangleConcept Second>
887constexpr bool samePointSet(const First& first, const Second& second) {
888 return collapsedMatches(second, first);
889}
890
892template <SegmentConcept First, DiskConcept Second>
893constexpr bool samePointSet(const First& first, const Second& second) {
894 return collapsedMatches(second, first);
895}
896
898template <SegmentConcept First, ConvexConcept Second>
899constexpr bool samePointSet(const First& first, const Second& second) {
900 return collapsedMatches(second, first);
901}
902
904template <SegmentConcept First, MonotoneChainConcept Second>
905constexpr bool samePointSet(const First& first, const Second& second) {
906 return collapsedMatches(second, first);
907}
908
913template <SegmentConcept First, PolylineConcept Second>
914constexpr bool samePointSet(const First& first, const Second& second) {
915 return collapsedMatches(second, first);
916}
917
919template <SegmentConcept First, PolygonConcept Second>
920constexpr bool samePointSet(const First& first, const Second& second) {
921 return collapsedMatches(second, first);
922}
923
925template <SegmentConcept First, HalfplaneIntersectionConcept Second>
926constexpr bool samePointSet(const First& first, const Second& second) {
927 return collapsedMatches(second, first);
928}
929
931template <SegmentConcept First, PolygonWithHolesConcept Second>
932constexpr bool samePointSet(const First& first, const Second& second) {
933 return collapsedMatches(second, first);
934}
935
937template <SegmentConcept First, PolygonSetConcept Second>
938constexpr bool samePointSet(const First& first, const Second& second) {
939 return collapsedMatches(second, first);
940}
941
946
948template <OrientedSegmentConcept First, OrientedSegmentConcept Second>
949constexpr bool samePointSet(const First& first, const Second& second) {
950 return sameSegmentPointSet(first, second);
951}
952
954template <OrientedSegmentConcept First, LineConcept Second>
955constexpr bool samePointSet(const First&, const Second&) {
956 return false;
957}
958
960template <OrientedSegmentConcept First, OrientedLineConcept Second>
961constexpr bool samePointSet(const First&, const Second&) {
962 return false;
963}
964
966template <OrientedSegmentConcept First, RayConcept Second>
967constexpr bool samePointSet(const First&, const Second&) {
968 return false;
969}
970
972template <OrientedSegmentConcept First, HalfplaneConcept Second>
973constexpr bool samePointSet(const First&, const Second&) {
974 return false;
975}
976
978template <OrientedSegmentConcept First, RectangleConcept Second>
979constexpr bool samePointSet(const First& first, const Second& second) {
980 return collapsedMatches(second, first);
981}
982
984template <OrientedSegmentConcept First, TriangleConcept Second>
985constexpr bool samePointSet(const First& first, const Second& second) {
986 return collapsedMatches(second, first);
987}
988
990template <OrientedSegmentConcept First, DiskConcept Second>
991constexpr bool samePointSet(const First& first, const Second& second) {
992 return collapsedMatches(second, first);
993}
994
996template <OrientedSegmentConcept First, ConvexConcept Second>
997constexpr bool samePointSet(const First& first, const Second& second) {
998 return collapsedMatches(second, first);
999}
1000
1002template <OrientedSegmentConcept First, MonotoneChainConcept Second>
1003constexpr bool samePointSet(const First& first, const Second& second) {
1004 return collapsedMatches(second, first);
1005}
1006
1008template <OrientedSegmentConcept First, PolylineConcept Second>
1009constexpr bool samePointSet(const First& first, const Second& second) {
1010 return collapsedMatches(second, first);
1011}
1012
1014template <OrientedSegmentConcept First, PolygonConcept Second>
1015constexpr bool samePointSet(const First& first, const Second& second) {
1016 return collapsedMatches(second, first);
1017}
1018
1020template <OrientedSegmentConcept First, HalfplaneIntersectionConcept Second>
1021constexpr bool samePointSet(const First& first, const Second& second) {
1022 return collapsedMatches(second, first);
1023}
1024
1026template <OrientedSegmentConcept First, PolygonWithHolesConcept Second>
1027constexpr bool samePointSet(const First& first, const Second& second) {
1028 return collapsedMatches(second, first);
1029}
1030
1032template <OrientedSegmentConcept First, PolygonSetConcept Second>
1033constexpr bool samePointSet(const First& first, const Second& second) {
1034 return collapsedMatches(second, first);
1035}
1036
1042
1044template <LineConcept First, LineConcept Second>
1045constexpr bool samePointSet(const First& first, const Second& second) {
1046 return sameLinePointSet(first, second);
1047}
1048
1050template <LineConcept First, OrientedLineConcept Second>
1051constexpr bool samePointSet(const First& first, const Second& second) {
1052 return sameLinePointSet(first, second);
1053}
1054
1056template <LineConcept First, RayConcept Second>
1057constexpr bool samePointSet(const First&, const Second&) {
1058 return false;
1059}
1060
1062template <LineConcept First, HalfplaneConcept Second>
1063constexpr bool samePointSet(const First&, const Second&) {
1064 return false;
1065}
1066
1068template <LineConcept First, RectangleConcept Second>
1069constexpr bool samePointSet(const First&, const Second&) {
1070 return false;
1071}
1072
1074template <LineConcept First, TriangleConcept Second>
1075constexpr bool samePointSet(const First&, const Second&) {
1076 return false;
1077}
1078
1080template <LineConcept First, DiskConcept Second>
1081constexpr bool samePointSet(const First&, const Second&) {
1082 return false;
1083}
1084
1086template <LineConcept First, ConvexConcept Second>
1087constexpr bool samePointSet(const First&, const Second&) {
1088 return false;
1089}
1090
1092template <LineConcept First, MonotoneChainConcept Second>
1093constexpr bool samePointSet(const First&, const Second&) {
1094 return false;
1095}
1096
1098template <LineConcept First, PolylineConcept Second>
1099constexpr bool samePointSet(const First&, const Second&) {
1100 return false;
1101}
1102
1104template <LineConcept First, PolygonConcept Second>
1105constexpr bool samePointSet(const First&, const Second&) {
1106 return false;
1107}
1108
1110template <LineConcept First, HalfplaneIntersectionConcept Second>
1111constexpr bool samePointSet(const First& first, const Second& second) {
1112 const auto carrier = second.getIfLine();
1113 return carrier && sameLinePointSet(first, *carrier);
1114}
1115
1117template <LineConcept First, PolygonWithHolesConcept Second>
1118constexpr bool samePointSet(const First&, const Second&) {
1119 return false;
1120}
1121
1123template <LineConcept First, PolygonSetConcept Second>
1124constexpr bool samePointSet(const First&, const Second&) {
1125 return false;
1126}
1127
1132
1134template <OrientedLineConcept First, OrientedLineConcept Second>
1135constexpr bool samePointSet(const First& first, const Second& second) {
1136 return sameLinePointSet(first, second);
1137}
1138
1140template <OrientedLineConcept First, RayConcept Second>
1141constexpr bool samePointSet(const First&, const Second&) {
1142 return false;
1143}
1144
1146template <OrientedLineConcept First, HalfplaneConcept Second>
1147constexpr bool samePointSet(const First&, const Second&) {
1148 return false;
1149}
1150
1152template <OrientedLineConcept First, RectangleConcept Second>
1153constexpr bool samePointSet(const First&, const Second&) {
1154 return false;
1155}
1156
1158template <OrientedLineConcept First, TriangleConcept Second>
1159constexpr bool samePointSet(const First&, const Second&) {
1160 return false;
1161}
1162
1164template <OrientedLineConcept First, DiskConcept Second>
1165constexpr bool samePointSet(const First&, const Second&) {
1166 return false;
1167}
1168
1170template <OrientedLineConcept First, ConvexConcept Second>
1171constexpr bool samePointSet(const First&, const Second&) {
1172 return false;
1173}
1174
1176template <OrientedLineConcept First, MonotoneChainConcept Second>
1177constexpr bool samePointSet(const First&, const Second&) {
1178 return false;
1179}
1180
1182template <OrientedLineConcept First, PolylineConcept Second>
1183constexpr bool samePointSet(const First&, const Second&) {
1184 return false;
1185}
1186
1188template <OrientedLineConcept First, PolygonConcept Second>
1189constexpr bool samePointSet(const First&, const Second&) {
1190 return false;
1191}
1192
1194template <OrientedLineConcept First, HalfplaneIntersectionConcept Second>
1195constexpr bool samePointSet(const First& first, const Second& second) {
1196 const auto carrier = second.getIfLine();
1197 return carrier && sameLinePointSet(first, *carrier);
1198}
1199
1201template <OrientedLineConcept First, PolygonWithHolesConcept Second>
1202constexpr bool samePointSet(const First&, const Second&) {
1203 return false;
1204}
1205
1207template <OrientedLineConcept First, PolygonSetConcept Second>
1208constexpr bool samePointSet(const First&, const Second&) {
1209 return false;
1210}
1211
1216
1218template <RayConcept First, RayConcept Second>
1219constexpr bool samePointSet(const First& first, const Second& second) {
1220 return sameRayPointSet(first, second);
1221}
1222
1224template <RayConcept First, HalfplaneConcept Second>
1225constexpr bool samePointSet(const First&, const Second&) {
1226 return false;
1227}
1228
1230template <RayConcept First, RectangleConcept Second>
1231constexpr bool samePointSet(const First&, const Second&) {
1232 return false;
1233}
1234
1236template <RayConcept First, TriangleConcept Second>
1237constexpr bool samePointSet(const First&, const Second&) {
1238 return false;
1239}
1240
1242template <RayConcept First, DiskConcept Second>
1243constexpr bool samePointSet(const First&, const Second&) {
1244 return false;
1245}
1246
1248template <RayConcept First, ConvexConcept Second>
1249constexpr bool samePointSet(const First&, const Second&) {
1250 return false;
1251}
1252
1254template <RayConcept First, MonotoneChainConcept Second>
1255constexpr bool samePointSet(const First&, const Second&) {
1256 return false;
1257}
1258
1260template <RayConcept First, PolylineConcept Second>
1261constexpr bool samePointSet(const First&, const Second&) {
1262 return false;
1263}
1264
1266template <RayConcept First, PolygonConcept Second>
1267constexpr bool samePointSet(const First&, const Second&) {
1268 return false;
1269}
1270
1272template <RayConcept First, HalfplaneIntersectionConcept Second>
1273constexpr bool samePointSet(const First& first, const Second& second) {
1274 const auto carrier = second.getIfRay();
1275 return carrier && sameRayPointSet(first, *carrier);
1276}
1277
1279template <RayConcept First, PolygonWithHolesConcept Second>
1280constexpr bool samePointSet(const First&, const Second&) {
1281 return false;
1282}
1283
1285template <RayConcept First, PolygonSetConcept Second>
1286constexpr bool samePointSet(const First&, const Second&) {
1287 return false;
1288}
1289
1295
1297template <HalfplaneConcept First, HalfplaneConcept Second>
1298constexpr bool samePointSet(const First& first, const Second& second) {
1299 return sameHalfplanePointSet(first, second);
1300}
1301
1303template <HalfplaneConcept First, RectangleConcept Second>
1304constexpr bool samePointSet(const First&, const Second&) {
1305 return false;
1306}
1307
1309template <HalfplaneConcept First, TriangleConcept Second>
1310constexpr bool samePointSet(const First&, const Second&) {
1311 return false;
1312}
1313
1315template <HalfplaneConcept First, DiskConcept Second>
1316constexpr bool samePointSet(const First&, const Second&) {
1317 return false;
1318}
1319
1321template <HalfplaneConcept First, ConvexConcept Second>
1322constexpr bool samePointSet(const First&, const Second&) {
1323 return false;
1324}
1325
1327template <HalfplaneConcept First, MonotoneChainConcept Second>
1328constexpr bool samePointSet(const First&, const Second&) {
1329 return false;
1330}
1331
1333template <HalfplaneConcept First, PolylineConcept Second>
1334constexpr bool samePointSet(const First&, const Second&) {
1335 return false;
1336}
1337
1339template <HalfplaneConcept First, PolygonConcept Second>
1340constexpr bool samePointSet(const First&, const Second&) {
1341 return false;
1342}
1343
1349template <HalfplaneConcept First, HalfplaneIntersectionConcept Second>
1350constexpr bool samePointSet(const First& first, const Second& second) {
1351 const auto carrier = second.getIfHalfplane();
1352 return carrier && sameHalfplanePointSet(first, *carrier);
1353}
1354
1356template <HalfplaneConcept First, PolygonWithHolesConcept Second>
1357constexpr bool samePointSet(const First&, const Second&) {
1358 return false;
1359}
1360
1362template <HalfplaneConcept First, PolygonSetConcept Second>
1363constexpr bool samePointSet(const First&, const Second&) {
1364 return false;
1365}
1366
1372
1374template <RectangleConcept First, RectangleConcept Second>
1375constexpr bool samePointSet(const First& first, const Second& second) {
1376 return first.min() == second.min() && first.max() == second.max();
1377}
1378
1383template <RectangleConcept First, TriangleConcept Second>
1384constexpr bool samePointSet(const First& first, const Second& second) {
1385 return collapsedMatches(first, second);
1386}
1387
1389template <RectangleConcept First, DiskConcept Second>
1390constexpr bool samePointSet(const First& first, const Second& second) {
1391 return collapsedMatches(second, first);
1392}
1393
1395template <RectangleConcept First, ConvexConcept Second>
1396constexpr bool samePointSet(const First& first, const Second& second) {
1397 return sameRingShapes(first, second);
1398}
1399
1401template <RectangleConcept First, MonotoneChainConcept Second>
1402constexpr bool samePointSet(const First& first, const Second& second) {
1403 return collapsedMatches(first, second);
1404}
1405
1407template <RectangleConcept First, PolylineConcept Second>
1408constexpr bool samePointSet(const First& first, const Second& second) {
1409 return collapsedMatches(first, second);
1410}
1411
1413template <RectangleConcept First, PolygonConcept Second>
1414constexpr bool samePointSet(const First& first, const Second& second) {
1415 return sameRingShapes(first, second);
1416}
1417
1419template <RectangleConcept First, HalfplaneIntersectionConcept Second>
1420constexpr bool samePointSet(const First& first, const Second& second) {
1421 return sameConvexRegionAndRing(second, first);
1422}
1423
1428template <RectangleConcept First, PolygonWithHolesConcept Second>
1429constexpr bool samePointSet(const First& first, const Second& second) {
1430 if (second.hasHoles()) {
1431 return false;
1432 }
1433 return sameRingShapes(first, second.outer());
1434}
1435
1440template <RectangleConcept First, PolygonSetConcept Second>
1441constexpr bool samePointSet(const First& first, const Second& second) {
1442 if (second.componentCount() != 1) {
1443 return false;
1444 }
1445 return samePointSetAny(first, second.component(0));
1446}
1447
1452
1457template <TriangleConcept First, TriangleConcept Second>
1458constexpr bool samePointSet(const First& first, const Second& second) {
1459 if (first.isDegenerate() || second.isDegenerate()) {
1460 return sameRingShapes(first, second);
1461 }
1462 return first[0] == second[0] && first[1] == second[1] && first[2] == second[2];
1463}
1464
1466template <TriangleConcept First, DiskConcept Second>
1467constexpr bool samePointSet(const First& first, const Second& second) {
1468 return collapsedMatches(second, first);
1469}
1470
1472template <TriangleConcept First, ConvexConcept Second>
1473constexpr bool samePointSet(const First& first, const Second& second) {
1474 return sameRingShapes(first, second);
1475}
1476
1478template <TriangleConcept First, MonotoneChainConcept Second>
1479constexpr bool samePointSet(const First& first, const Second& second) {
1480 return collapsedMatches(first, second);
1481}
1482
1484template <TriangleConcept First, PolylineConcept Second>
1485constexpr bool samePointSet(const First& first, const Second& second) {
1486 return collapsedMatches(first, second);
1487}
1488
1490template <TriangleConcept First, PolygonConcept Second>
1491constexpr bool samePointSet(const First& first, const Second& second) {
1492 return sameRingShapes(first, second);
1493}
1494
1496template <TriangleConcept First, HalfplaneIntersectionConcept Second>
1497constexpr bool samePointSet(const First& first, const Second& second) {
1498 return sameConvexRegionAndRing(second, first);
1499}
1500
1502template <TriangleConcept First, PolygonWithHolesConcept Second>
1503constexpr bool samePointSet(const First& first, const Second& second) {
1504 if (second.hasHoles()) {
1505 return false;
1506 }
1507 return sameRingShapes(first, second.outer());
1508}
1509
1511template <TriangleConcept First, PolygonSetConcept Second>
1512constexpr bool samePointSet(const First& first, const Second& second) {
1513 if (second.componentCount() != 1) {
1514 return false;
1515 }
1516 return samePointSetAny(first, second.component(0));
1517}
1518
1524
1529template <DiskConcept First, DiskConcept Second>
1530constexpr bool samePointSet(const First& first, const Second& second) {
1531 if (first.isPoint() || second.isPoint()) {
1532 return first.isPoint() && second.isPoint() && first.a() == second.a();
1533 }
1534 return inCircleSign(first.a(), first.b(), first.c(), second.a()) == 0 &&
1535 inCircleSign(first.a(), first.b(), first.c(), second.b()) == 0 &&
1536 inCircleSign(first.a(), first.b(), first.c(), second.c()) == 0;
1537}
1538
1540template <DiskConcept First, ConvexConcept Second>
1541constexpr bool samePointSet(const First& first, const Second& second) {
1542 return collapsedMatches(first, second);
1543}
1544
1546template <DiskConcept First, MonotoneChainConcept Second>
1547constexpr bool samePointSet(const First& first, const Second& second) {
1548 return collapsedMatches(first, second);
1549}
1550
1552template <DiskConcept First, PolylineConcept Second>
1553constexpr bool samePointSet(const First& first, const Second& second) {
1554 return collapsedMatches(first, second);
1555}
1556
1558template <DiskConcept First, PolygonConcept Second>
1559constexpr bool samePointSet(const First& first, const Second& second) {
1560 return collapsedMatches(first, second);
1561}
1562
1564template <DiskConcept First, HalfplaneIntersectionConcept Second>
1565constexpr bool samePointSet(const First& first, const Second& second) {
1566 return collapsedMatches(first, second);
1567}
1568
1570template <DiskConcept First, PolygonWithHolesConcept Second>
1571constexpr bool samePointSet(const First& first, const Second& second) {
1572 return collapsedMatches(first, second);
1573}
1574
1576template <DiskConcept First, PolygonSetConcept Second>
1577constexpr bool samePointSet(const First& first, const Second& second) {
1578 return collapsedMatches(first, second);
1579}
1580
1586
1588template <ConvexConcept First, ConvexConcept Second>
1589constexpr bool samePointSet(const First& first, const Second& second) {
1590 return sameRingShapes(first, second);
1591}
1592
1594template <ConvexConcept First, MonotoneChainConcept Second>
1595constexpr bool samePointSet(const First& first, const Second& second) {
1596 return collapsedMatches(first, second);
1597}
1598
1600template <ConvexConcept First, PolylineConcept Second>
1601constexpr bool samePointSet(const First& first, const Second& second) {
1602 return collapsedMatches(first, second);
1603}
1604
1606template <ConvexConcept First, PolygonConcept Second>
1607constexpr bool samePointSet(const First& first, const Second& second) {
1608 return sameRingShapes(first, second);
1609}
1610
1612template <ConvexConcept First, HalfplaneIntersectionConcept Second>
1613constexpr bool samePointSet(const First& first, const Second& second) {
1614 return sameConvexRegionAndRing(second, first);
1615}
1616
1618template <ConvexConcept First, PolygonWithHolesConcept Second>
1619constexpr bool samePointSet(const First& first, const Second& second) {
1620 if (second.hasHoles()) {
1621 return false;
1622 }
1623 return sameRingShapes(first, second.outer());
1624}
1625
1627template <ConvexConcept First, PolygonSetConcept Second>
1628constexpr bool samePointSet(const First& first, const Second& second) {
1629 if (second.componentCount() != 1) {
1630 return false;
1631 }
1632 return samePointSetAny(first, second.component(0));
1633}
1634
1640
1642template <MonotoneChainConcept First, MonotoneChainConcept Second>
1643constexpr bool samePointSet(const First& first, const Second& second) {
1644 return sameChainPointSet(first, second);
1645}
1646
1648template <MonotoneChainConcept First, PolylineConcept Second>
1649constexpr bool samePointSet(const First& first, const Second& second) {
1650 return samePolylinePointSet(second, first);
1651}
1652
1654template <MonotoneChainConcept First, PolygonConcept Second>
1655constexpr bool samePointSet(const First& first, const Second& second) {
1656 return collapsedMatches(second, first);
1657}
1658
1660template <MonotoneChainConcept First, HalfplaneIntersectionConcept Second>
1661constexpr bool samePointSet(const First& first, const Second& second) {
1662 return collapsedMatches(second, first);
1663}
1664
1666template <MonotoneChainConcept First, PolygonWithHolesConcept Second>
1667constexpr bool samePointSet(const First& first, const Second& second) {
1668 return collapsedMatches(second, first);
1669}
1670
1672template <MonotoneChainConcept First, PolygonSetConcept Second>
1673constexpr bool samePointSet(const First& first, const Second& second) {
1674 return collapsedMatches(second, first);
1675}
1676
1682
1684template <PolylineConcept First, PolylineConcept Second>
1685constexpr bool samePointSet(const First& first, const Second& second) {
1686 return samePolylinePointSet(first, second);
1687}
1688
1690template <PolylineConcept First, PolygonConcept Second>
1691constexpr bool samePointSet(const First& first, const Second& second) {
1692 return collapsedMatches(second, first);
1693}
1694
1696template <PolylineConcept First, HalfplaneIntersectionConcept Second>
1697constexpr bool samePointSet(const First& first, const Second& second) {
1698 return collapsedMatches(second, first);
1699}
1700
1702template <PolylineConcept First, PolygonWithHolesConcept Second>
1703constexpr bool samePointSet(const First& first, const Second& second) {
1704 return collapsedMatches(second, first);
1705}
1706
1708template <PolylineConcept First, PolygonSetConcept Second>
1709constexpr bool samePointSet(const First& first, const Second& second) {
1710 return collapsedMatches(second, first);
1711}
1712
1717
1719template <PolygonConcept First, PolygonConcept Second>
1720constexpr bool samePointSet(const First& first, const Second& second) {
1721 return sameRingShapes(first, second);
1722}
1723
1728template <PolygonConcept First, HalfplaneIntersectionConcept Second>
1729constexpr bool samePointSet(const First& first, const Second& second) {
1730 return sameConvexRegionAndRing(second, first);
1731}
1732
1734template <PolygonConcept First, PolygonWithHolesConcept Second>
1735constexpr bool samePointSet(const First& first, const Second& second) {
1736 if (second.hasHoles()) {
1737 return false;
1738 }
1739 return sameRingShapes(first, second.outer());
1740}
1741
1743template <PolygonConcept First, PolygonSetConcept Second>
1744constexpr bool samePointSet(const First& first, const Second& second) {
1745 if (second.componentCount() != 1) {
1746 return false;
1747 }
1748 return samePointSetAny(first, second.component(0));
1749}
1750
1756
1763template <HalfplaneIntersectionConcept First, HalfplaneIntersectionConcept Second>
1764constexpr bool samePointSet(const First& first, const Second& second) {
1765 if (first.isDegenerate() || second.isDegenerate()) {
1766 return reduceRegionCarrier(first, [&second](const auto& carrier) {
1767 return samePointSetAny(carrier, second);
1768 });
1769 }
1770 if (first.size() != second.size()) {
1771 return false;
1772 }
1773 for (std::size_t i = 0; i < first.size(); ++i) {
1774 if (!sameHalfplanePointSet(first[i], second[i])) {
1775 return false;
1776 }
1777 }
1778 return true;
1779}
1780
1786template <HalfplaneIntersectionConcept First, PolygonWithHolesConcept Second>
1787constexpr bool samePointSet(const First& first, const Second& second) {
1788 if (second.hasHoles()) {
1789 return false;
1790 }
1791 return sameConvexRegionAndRing(first, second.outer());
1792}
1793
1795template <HalfplaneIntersectionConcept First, PolygonSetConcept Second>
1796constexpr bool samePointSet(const First& first, const Second& second) {
1797 if (second.componentCount() != 1) {
1798 return false;
1799 }
1800 return samePointSetAny(first, second.component(0));
1801}
1802
1808
1810template <PolygonWithHolesConcept First, PolygonWithHolesConcept Second>
1811constexpr bool samePointSet(const First& first, const Second& second) {
1812 if (sameRepresentation(first, second)) {
1813 return true;
1814 }
1815 if (!sameBoundingBox(first, second) || !(first.outer()[0] == second.outer()[0])) {
1816 // A region's box and smallest vertex are its outer ring's, and reject
1817 // it for the same reasons a ring is rejected.
1818 return false;
1819 }
1820 if (collapsedBelowArea(first)) {
1821 return collapsedMatches(first, second);
1822 }
1823 if (collapsedBelowArea(second)) {
1824 return collapsedMatches(second, first);
1825 }
1826 return sameRegionRings(first, second);
1827}
1828
1839template <PolygonWithHolesConcept First, PolygonSetConcept Second>
1840constexpr bool samePointSet(const First& first, const Second& second) {
1841 if (second.componentCount() == 1) {
1842 return samePointSetAny(first, second.component(0));
1843 }
1844 if (collapsedBelowArea(first)) {
1845 return false; // several components with area against no area at all
1846 }
1847 return sameBoundingBox(first, second) && sameBoundaryPointSet(first, second);
1848}
1849
1856
1866template <PolygonSetConcept First, PolygonSetConcept Second>
1867constexpr bool samePointSet(const First& first, const Second& second) {
1868 if (sameRepresentation(first, second)) {
1869 return true;
1870 }
1871 if (first.componentCount() == second.componentCount() &&
1872 sameRingCollection(first.components(), second.components(),
1873 [](const auto& one, const auto& other) {
1874 return sameRegionRings(one, other);
1875 })) {
1876 return true;
1877 }
1878 if (collapsedBelowArea(first) || collapsedBelowArea(second)) {
1879 return collapsedMatches(first, second) || collapsedMatches(second, first);
1880 }
1881 return sameBoundingBox(first, second) && sameBoundaryPointSet(first, second);
1882}
1883
1884// ---------------------------------------------------------------------------
1885
1902template <AnyShapeConcept First, AnyShapeConcept Second>
1903constexpr bool samePointSetAny(const First& first, const Second& second) {
1904 if constexpr (ShapeConcept<First>) {
1905 return std::visit(
1906 [&second](const auto& value) { return samePointSetAny(value, second); },
1907 first.variant());
1908 } else if constexpr (ShapeConcept<Second>) {
1909 return std::visit(
1910 [&first](const auto& value) { return samePointSetAny(first, value); },
1911 second.variant());
1912 } else if constexpr (EmptyShapeConcept<First> || EmptyShapeConcept<Second>) {
1913 return coversNoPoint(first) && coversNoPoint(second);
1914 } else {
1915 const bool firstEmpty = coversNoPoint(first);
1916 const bool secondEmpty = coversNoPoint(second);
1917 if (firstEmpty || secondEmpty) {
1918 return firstEmpty && secondEmpty;
1919 }
1920 if constexpr (shapeRank<std::remove_cvref_t<First>> >
1921 shapeRank<std::remove_cvref_t<Second>>) {
1922 return samePointSet(second, first);
1923 } else {
1924 return samePointSet(first, second);
1925 }
1926 }
1927}
1928
1929} // namespace pgl::detail
1930
1931namespace pgl {
1932
1933template <class Number, class Label>
1934template <AnyShapeConcept OtherShape>
1935constexpr bool Point<Number, Label>::samePointSet(const OtherShape& other) const {
1936 return detail::samePointSetAny(*this, other);
1937}
1938
1939template <class PointType>
1940template <AnyShapeConcept OtherShape>
1941constexpr bool EmptyShape<PointType>::samePointSet(const OtherShape& other) const {
1942 return detail::samePointSetAny(*this, other);
1943}
1944
1945template <class PointType, class LabelType>
1946template <AnyShapeConcept OtherShape>
1947constexpr bool Segment<PointType, LabelType>::samePointSet(const OtherShape& other) const {
1948 return detail::samePointSetAny(*this, other);
1949}
1950
1951template <class PointType, class LabelType>
1952template <AnyShapeConcept OtherShape>
1953constexpr bool OrientedSegment<PointType, LabelType>::samePointSet(const OtherShape& other) const {
1954 return detail::samePointSetAny(*this, other);
1955}
1956
1957template <class PointType, class LabelType>
1958template <AnyShapeConcept OtherShape>
1959constexpr bool Line<PointType, LabelType>::samePointSet(const OtherShape& other) const {
1960 return detail::samePointSetAny(*this, other);
1961}
1962
1963template <class PointType, class LabelType>
1964template <AnyShapeConcept OtherShape>
1965constexpr bool OrientedLine<PointType, LabelType>::samePointSet(const OtherShape& other) const {
1966 return detail::samePointSetAny(*this, other);
1967}
1968
1969template <class PointType, class LabelType>
1970template <AnyShapeConcept OtherShape>
1971constexpr bool Ray<PointType, LabelType>::samePointSet(const OtherShape& other) const {
1972 return detail::samePointSetAny(*this, other);
1973}
1974
1975template <class PointType, class LabelType>
1976template <AnyShapeConcept OtherShape>
1977constexpr bool Halfplane<PointType, LabelType>::samePointSet(const OtherShape& other) const {
1978 return detail::samePointSetAny(*this, other);
1979}
1980
1981template <class PointType, class LabelType>
1982template <AnyShapeConcept OtherShape>
1983constexpr bool Rectangle<PointType, LabelType>::samePointSet(const OtherShape& other) const {
1984 return detail::samePointSetAny(*this, other);
1985}
1986
1987template <class PointType, class LabelType>
1988template <AnyShapeConcept OtherShape>
1989constexpr bool Triangle<PointType, LabelType>::samePointSet(const OtherShape& other) const {
1990 return detail::samePointSetAny(*this, other);
1991}
1992
1993template <class PointType, class LabelType>
1994template <AnyShapeConcept OtherShape>
1995constexpr bool Disk<PointType, LabelType>::samePointSet(const OtherShape& other) const {
1996 return detail::samePointSetAny(*this, other);
1997}
1998
1999template <class PointType, class LabelType>
2000template <AnyShapeConcept OtherShape>
2001constexpr bool Convex<PointType, LabelType>::samePointSet(const OtherShape& other) const {
2002 return detail::samePointSetAny(*this, other);
2003}
2004
2005template <class PointType, class LabelType, class Storage>
2006template <AnyShapeConcept OtherShape>
2007constexpr bool MonotoneChain<PointType, LabelType, Storage>::samePointSet(const OtherShape& other) const {
2008 return detail::samePointSetAny(*this, other);
2009}
2010
2011template <class PointType, class LabelType>
2012template <AnyShapeConcept OtherShape>
2013constexpr bool Polyline<PointType, LabelType>::samePointSet(const OtherShape& other) const {
2014 return detail::samePointSetAny(*this, other);
2015}
2016
2017template <class PointType, class LabelType>
2018template <AnyShapeConcept OtherShape>
2019constexpr bool Polygon<PointType, LabelType>::samePointSet(const OtherShape& other) const {
2020 return detail::samePointSetAny(*this, other);
2021}
2022
2023template <class PointType, class LabelType>
2024template <AnyShapeConcept OtherShape>
2025constexpr bool HalfplaneIntersection<PointType, LabelType>::samePointSet(const OtherShape& other) const {
2026 return detail::samePointSetAny(*this, other);
2027}
2028
2029template <class PointType, class LabelType>
2030template <AnyShapeConcept OtherShape>
2031constexpr bool PolygonWithHoles<PointType, LabelType>::samePointSet(const OtherShape& other) const {
2032 return detail::samePointSetAny(*this, other);
2033}
2034
2035template <class PointType, class LabelType>
2036template <AnyShapeConcept OtherShape>
2037constexpr bool PolygonSet<PointType, LabelType>::samePointSet(const OtherShape& other) const {
2038 return detail::samePointSetAny(*this, other);
2039}
2040
2041template <class PointType>
2042template <AnyShapeConcept OtherShape>
2043constexpr bool Shape<PointType>::samePointSet(const OtherShape& other) const {
2044 return detail::samePointSetAny(*this, other);
2045}
2046
2047} // namespace pgl
Definition arrangement.hpp:67
constexpr std::partial_ordering inCircleSign(const Point< ANumber, ALabel > &a, const Point< BNumber, BLabel > &b, const Point< CNumber, CLabel > &c, const Point< DNumber, DLabel > &d)
Classifies a point with respect to the circumcircle of three others.
Definition orientation.hpp:894
@ edge
Definition bitmatrix.hpp:37
@ vertex
Definition bitmatrix.hpp:37
Point() -> Point< int >
constexpr std::partial_ordering dotSign(const Point< ANumber, ALabel > &a, const Point< BNumber, BLabel > &b)
Tells if the angle between two vectors is acute, right, or obtuse.
Definition orientation.hpp:688
constexpr bool collinear(const Point< ANumber, ALabel > &a, const Point< BNumber, BLabel > &b, const Point< CNumber, CLabel > &c)
Tests whether three points are collinear.
Definition orientation.hpp:651
Shape(const std::variant< T, Ts... > &) -> Shape< detail::shape_point_type_t< T > >
Method definitions for the shapes.
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:2001
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:1995
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines the empty point set.
Definition samepointset.hpp:1941
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:2025
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:1977
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:1959
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:2007
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:1965
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:1953
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:1935
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:2037
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:2031
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:2019
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:2013
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:1971
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:1983
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:1947
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:2043
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:1989