23template <
class Number,
class Label>
24template<Po
intConcept OtherPo
int>
26 using Compare = std::common_type_t<Number, typename OtherPoint::NumberType>;
27 return detail::asNumber<Compare>(
x()) == detail::asNumber<Compare>(other.x()) &&
28 detail::asNumber<Compare>(
y()) == detail::asNumber<Compare>(other.y());
31template <
class Number,
class Label>
32template<SegmentConcept OtherSegment>
34 return other.isDegenerate() &&
contains(other.min());
37template <
class Number,
class Label>
38template<OrientedSegmentConcept OtherOrientedSegment>
40 return other.isDegenerate() &&
contains(other.source());
43template <
class Number,
class Label>
44template<LineConcept OtherLine>
46 return other.isDegenerate() &&
contains(other.min());
49template <
class Number,
class Label>
50template<OrientedLineConcept OtherOrientedLine>
52 return other.isDegenerate() &&
contains(other.source());
55template <
class Number,
class Label>
56template<RayConcept OtherRay>
58 return other.isDegenerate() &&
contains(other.source());
61template <
class Number,
class Label>
62template<HalfplaneConcept OtherHalfplane>
64 return other.isDegenerate() &&
contains(other.source());
67template <
class Number,
class Label>
68template<RectangleConcept OtherRectangle>
78template <
class Number,
class Label>
79template<TriangleConcept OtherTriangle>
81 const auto vertices = other.vertices();
85template <
class Number,
class Label>
86template<ConvexConcept OtherConvex>
88 return other.size()== 0 || (other.size() == 1 && other[0]==*
this);
91template <
class Number,
class Label>
92template<DiskConcept OtherDisk>
98 return other.a() == other.b() &&
contains(other.a());
101template <
class Number,
class Label>
104 [
this](
const auto& value) {
105 return this->contains(value);
117template <
class Po
intType,
class LabelType>
118template<Po
intConcept OtherPo
int>
120 if (point <
min() ||
max() < point) {
126template <
class Po
intType,
class LabelType>
127template<SegmentConcept OtherSegment>
132template <
class Po
intType,
class LabelType>
133template<OrientedSegmentConcept OtherOrientedSegment>
138template <
class Po
intType,
class LabelType>
139template<LineConcept OtherLine>
141 return other.isDegenerate() &&
contains(other.min());
144template <
class Po
intType,
class LabelType>
145template<OrientedLineConcept OtherOrientedLine>
147 return other.isDegenerate() &&
contains(other.source());
150template <
class Po
intType,
class LabelType>
151template<RayConcept OtherRay>
153 return other.isDegenerate() &&
contains(other.source());
156template <
class Po
intType,
class LabelType>
157template<HalfplaneConcept OtherHalfplane>
159 return other.isDegenerate() &&
contains(other.source());
162template <
class Po
intType,
class LabelType>
163template<RectangleConcept OtherRectangle>
170 if (!other.isDegenerate()) {
173 if (other.min() == other.max()) {
179template <
class Po
intType,
class LabelType>
180template<TriangleConcept OtherTriangle>
185template <
class Po
intType,
class LabelType>
186template<ConvexConcept OtherConvex>
188 if (other.size() > 2) {
191 for (std::size_t i = 0; i < other.size(); ++i) {
199template <
class Po
intType,
class LabelType>
200template<DiskConcept OtherDisk>
202 return other.a() == other.b() && other.b() == other.c() &&
contains(other.a());
205template <
class Po
intType,
class LabelType>
206template<Po
intConcept OtherPo
int>
209 [
this](
const auto& value) {
221template <
class Po
intType,
class LabelType>
222template<Po
intConcept OtherPo
int>
230 const bool has_negative =
231 o1 == std::partial_ordering::less ||
232 o2 == std::partial_ordering::less ||
233 o3 == std::partial_ordering::less;
234 const bool has_positive =
235 o1 == std::partial_ordering::greater ||
236 o2 == std::partial_ordering::greater ||
237 o3 == std::partial_ordering::greater;
238 return !(has_negative && has_positive);
241template <
class Po
intType,
class LabelType>
242template<SegmentConcept OtherSegment>
247template <
class Po
intType,
class LabelType>
248template<OrientedSegmentConcept OtherOrientedSegment>
253template <
class Po
intType,
class LabelType>
254template<LineConcept OtherLine>
256 return other.isDegenerate() &&
contains(other.min());
259template <
class Po
intType,
class LabelType>
260template<OrientedLineConcept OtherOrientedLine>
262 return other.isDegenerate() &&
contains(other.source());
265template <
class Po
intType,
class LabelType>
266template<RayConcept OtherRay>
268 return other.isDegenerate() &&
contains(other.source());
271template <
class Po
intType,
class LabelType>
272template<HalfplaneConcept OtherHalfplane>
274 return other.isDegenerate() &&
contains(other.source());
277template <
class Po
intType,
class LabelType>
278template<RectangleConcept OtherRectangle>
285 const auto vertices = other.vertices();
294template <
class Po
intType,
class LabelType>
295template<TriangleConcept OtherTriangle>
300template <
class Po
intType,
class LabelType>
301template<ConvexConcept OtherConvex>
303 if (other.size() == 0) {
309 for (std::size_t i = 0; i < other.size(); ++i) {
317template <
class Po
intType,
class LabelType>
318template<DiskConcept OtherDisk>
320 if (
const auto center = other.getIfPoint()) {
329template <
class Po
intType,
class LabelType>
332 [
this](
const auto& value) {
344template <
class Po
intType,
class LabelType>
345template<Po
intConcept OtherPo
int>
350template <
class Po
intType,
class LabelType>
351template<SegmentConcept OtherSegment>
356template <
class Po
intType,
class LabelType>
357template<OrientedSegmentConcept OtherOrientedSegment>
362template <
class Po
intType,
class LabelType>
363template<LineConcept OtherLine>
368template <
class Po
intType,
class LabelType>
369template<OrientedLineConcept OtherOrientedLine>
374template <
class Po
intType,
class LabelType>
375template<RayConcept OtherRay>
380template <
class Po
intType,
class LabelType>
381template<HalfplaneConcept OtherHalfplane>
386template <
class Po
intType,
class LabelType>
387template<RectangleConcept OtherRectangle>
397template <
class Po
intType,
class LabelType>
398template<TriangleConcept OtherTriangle>
403template <
class Po
intType,
class LabelType>
404template<ConvexConcept OtherConvex>
409template <
class Po
intType,
class LabelType>
410template<DiskConcept OtherDisk>
415template <
class Po
intType,
class LabelType>
426template <
class Po
intType,
class LabelType>
427template<Po
intConcept OtherPo
int>
430 return point ==
min();
435template <
class Po
intType,
class LabelType>
436template<LineConcept OtherLine>
441template <
class Po
intType,
class LabelType>
442template<SegmentConcept OtherSegment>
447template <
class Po
intType,
class LabelType>
448template<OrientedSegmentConcept OtherOrientedSegment>
453template <
class Po
intType,
class LabelType>
454template<OrientedLineConcept OtherOrientedLine>
459template <
class Po
intType,
class LabelType>
460template<RayConcept OtherRay>
465template <
class Po
intType,
class LabelType>
466template<HalfplaneConcept OtherHalfplane>
468 return other.isDegenerate() &&
contains(other.source());
471template <
class Po
intType,
class LabelType>
472template<RectangleConcept OtherRectangle>
479 if (!other.isDegenerate()) {
485template <
class Po
intType,
class LabelType>
486template<TriangleConcept OtherTriangle>
491template <
class Po
intType,
class LabelType>
492template<ConvexConcept OtherConvex>
494 if (other.size() > 2) {
497 for (std::size_t i = 0; i < other.size(); ++i) {
505template <
class Po
intType,
class LabelType>
506template<DiskConcept OtherDisk>
511 return other.a() == other.b() &&
contains(other.a());
514template <
class Po
intType,
class LabelType>
517 [
this](
const auto& value) {
529template <
class Po
intType,
class LabelType>
530template<Po
intConcept OtherPo
int>
532 return this->
asLine().contains(point);
535template <
class Po
intType,
class LabelType>
536template<LineConcept OtherLine>
538 return this->
asLine().contains(other);
541template <
class Po
intType,
class LabelType>
542template<OrientedLineConcept OtherOrientedLine>
544 return this->
asLine().contains(other.asLine());
547template <
class Po
intType,
class LabelType>
548template<SegmentConcept OtherSegment>
550 return this->
asLine().contains(other);
553template <
class Po
intType,
class LabelType>
554template<OrientedSegmentConcept OtherOrientedSegment>
556 return this->
asLine().contains(other);
559template <
class Po
intType,
class LabelType>
560template<RayConcept OtherRay>
562 return this->
asLine().contains(other);
565template <
class Po
intType,
class LabelType>
566template<HalfplaneConcept OtherHalfplane>
568 return this->
asLine().contains(other);
571template <
class Po
intType,
class LabelType>
572template<RectangleConcept OtherRectangle>
579 return this->
asLine().contains(other);
582template <
class Po
intType,
class LabelType>
583template<TriangleConcept OtherTriangle>
585 return this->
asLine().contains(other);
588template <
class Po
intType,
class LabelType>
589template<ConvexConcept OtherConvex>
591 if (other.size() > 2) {
594 for (std::size_t i = 0; i < other.size(); ++i) {
602template <
class Po
intType,
class LabelType>
603template<DiskConcept OtherDisk>
605 return this->
asLine().contains(other);
608template <
class Po
intType,
class LabelType>
611 [
this](
const auto& value) {
623template <
class Po
intType,
class LabelType>
624template<Po
intConcept OtherPo
int>
632template <
class Po
intType,
class LabelType>
633template<LineConcept OtherLine>
635 return other.isDegenerate() &&
contains(other.min());
638template <
class Po
intType,
class LabelType>
639template<OrientedLineConcept OtherOrientedLine>
641 return other.isDegenerate() &&
contains(other.source());
644template <
class Po
intType,
class LabelType>
645template<SegmentConcept OtherSegment>
650template <
class Po
intType,
class LabelType>
651template<OrientedSegmentConcept OtherOrientedSegment>
656template <
class Po
intType,
class LabelType>
657template<RayConcept OtherRay>
662template <
class Po
intType,
class LabelType>
663template<HalfplaneConcept OtherHalfplane>
665 return other.isDegenerate() &&
contains(other.source());
668template <
class Po
intType,
class LabelType>
669template<RectangleConcept OtherRectangle>
676 if (!other.isDegenerate()) {
682template <
class Po
intType,
class LabelType>
683template<TriangleConcept OtherTriangle>
688template <
class Po
intType,
class LabelType>
689template<ConvexConcept OtherConvex>
691 if (other.size() > 2) {
694 for (std::size_t i = 0; i < other.size(); ++i) {
702template <
class Po
intType,
class LabelType>
703template<DiskConcept OtherDisk>
708 return other.a() == other.b() &&
contains(other.a());
711template <
class Po
intType,
class LabelType>
714 [
this](
const auto& value) {
726template <
class Po
intType,
class LabelType>
727template<Po
intConcept OtherPo
int>
732 return !(point.x() <
min().
x()) &&
733 !(
max().x() < point.x()) &&
734 !(point.y() <
min().
y()) &&
735 !(
max().y() < point.y());
738template <
class Po
intType,
class LabelType>
739template<LineConcept OtherLine>
743 return detail::coversNoPoint(other);
745 return other.isDegenerate() &&
contains(other.min());
748template <
class Po
intType,
class LabelType>
749template<OrientedLineConcept OtherOrientedLine>
753 return detail::coversNoPoint(other);
755 return other.isDegenerate() &&
contains(other.source());
758template <
class Po
intType,
class LabelType>
759template<SegmentConcept OtherSegment>
763 return detail::coversNoPoint(other);
768template <
class Po
intType,
class LabelType>
769template<OrientedSegmentConcept OtherOrientedSegment>
773 return detail::coversNoPoint(other);
778template <
class Po
intType,
class LabelType>
779template<RayConcept OtherRay>
783 return detail::coversNoPoint(other);
785 return other.isDegenerate() &&
contains(other.source());
788template <
class Po
intType,
class LabelType>
789template<HalfplaneConcept OtherHalfplane>
793 return detail::coversNoPoint(other);
795 return other.isDegenerate() &&
contains(other.source());
798template <
class Po
intType,
class LabelType>
799template<RectangleConcept OtherRectangle>
810template <
class Po
intType,
class LabelType>
811template<TriangleConcept OtherTriangle>
815 return detail::coversNoPoint(other);
820template <
class Po
intType,
class LabelType>
821template<ConvexConcept OtherConvex>
825 return detail::coversNoPoint(other);
827 return other.size()==0 ||
contains(other.bbox());
830template <
class Po
intType,
class LabelType>
831template<DiskConcept OtherDisk>
835 return detail::coversNoPoint(other);
837 if (
const auto center = other.getIfPoint()) {
848 if (
edge.interiorsIntersect(other)) {
852 return other.pointInsideInteriorContainedIn(*
this);
855template <
class Po
intType,
class LabelType>
858 [
this](
const auto& value) {
870template <
class Po
intType,
class LabelType>
871template<Po
intConcept OtherPo
int>
877 return side == std::partial_ordering::greater || side == std::partial_ordering::equivalent;
880template <
class Po
intType,
class LabelType>
881template<LineConcept OtherLine>
884 return other.isDegenerate() &&
contains(other.min());
889template <
class Po
intType,
class LabelType>
890template<OrientedLineConcept OtherOrientedLine>
895template <
class Po
intType,
class LabelType>
896template<SegmentConcept OtherSegment>
899 return other.isDegenerate() &&
contains(other.min());
904template <
class Po
intType,
class LabelType>
905template<OrientedSegmentConcept OtherOrientedSegment>
908 return other.isDegenerate() &&
contains(other.source());
913template <
class Po
intType,
class LabelType>
914template<RayConcept OtherRay>
917 return other.isDegenerate() &&
contains(other.source());
929template <
class Po
intType,
class LabelType>
930template<RectangleConcept OtherRectangle>
937 const auto vertices = other.vertices();
938 for (
const auto&
vertex : vertices) {
946template <
class Po
intType,
class LabelType>
947template<HalfplaneConcept OtherHalfplane>
959 if (!
asLine().parallel(other.asLine()) ||
961 std::partial_ordering::greater) {
967template <
class Po
intType,
class LabelType>
968template<TriangleConcept OtherTriangle>
973template <
class Po
intType,
class LabelType>
974template<ConvexConcept OtherConvex>
976 if (other.size() == 0) {
979 if (other.size() == 1) {
982 if (other.size() == 2) {
989template <
class Po
intType,
class LabelType>
990template<DiskConcept OtherDisk>
992 if (
const auto center = other.getIfPoint()) {
998 return !
asLine().interiorsIntersect(other) && other.pointInsideInteriorContainedIn(*
this);
1001template <
class Po
intType,
class LabelType>
1004 [
this](
const auto& value) {
1013template <
class Po
intType,
class LabelType>
1014template<Po
intConcept OtherPo
int>
1021 return a() == point;
1024 return inCircleSign(
a(),
b(),
c(), point) != std::partial_ordering::less;
1027template <
class Po
intType,
class LabelType>
1028template<SegmentConcept OtherSegment>
1033template <
class Po
intType,
class LabelType>
1034template<OrientedSegmentConcept OtherOrientedSegment>
1039template <
class Po
intType,
class LabelType>
1040template<LineConcept OtherLine>
1042 return other.isDegenerate() &&
contains(other.min());
1045template <
class Po
intType,
class LabelType>
1046template<OrientedLineConcept OtherOrientedLine>
1048 return other.isDegenerate() &&
contains(other.source());
1051template <
class Po
intType,
class LabelType>
1052template<RayConcept OtherRay>
1054 return other.isDegenerate() &&
contains(other.source());
1057template <
class Po
intType,
class LabelType>
1058template<HalfplaneConcept OtherHalfplane>
1060 return other.isDegenerate() &&
contains(other.source());
1063template <
class Po
intType,
class LabelType>
1064template<TriangleConcept OtherTriangle>
1069template <
class Po
intType,
class LabelType>
1070template<RectangleConcept OtherRectangle>
1072 if (other.empty()) {
1077 const auto vertices = other.vertices();
1081template <
class Po
intType,
class LabelType>
1082template<ConvexConcept OtherConvex>
1084 for (
const auto& point : other) {
1092template <
class Po
intType,
class LabelType>
1093template<DiskConcept OtherDisk>
1096 if (other.a() == other.b()) {
1103 using R = std::conditional_t<
1104 std::is_floating_point_v<NumberType> ||
1105 std::is_floating_point_v<typename OtherDisk::NumberType>,
1111 if (r1_sq < r2_sq) {
1116 const R A = d2 - r1_sq - r2_sq;
1117 return A <= R{} && A * A >= R{4} * r1_sq * r2_sq;
1120template <
class Po
intType,
class LabelType>
1123 [
this](
const auto& value) {
1133template <
class Po
intType,
class LabelType>
1134template<Po
intConcept OtherPo
int>
1143 return carrier->contains(point);
1154 const auto& lower = (*edges)[0];
1155 const auto& upper = (*edges)[1];
1162template <
class Po
intType,
class LabelType>
1163template<SegmentConcept OtherSegment>
1168template <
class Po
intType,
class LabelType>
1169template<OrientedSegmentConcept OtherOrientedSegment>
1174template <
class Po
intType,
class LabelType>
1175template<LineConcept OtherLine>
1180template <
class Po
intType,
class LabelType>
1181template<OrientedLineConcept OtherOrientedLine>
1186template <
class Po
intType,
class LabelType>
1187template<RayConcept OtherRay>
1192template <
class Po
intType,
class LabelType>
1193template<HalfplaneConcept OtherHalfplane>
1198template <
class Po
intType,
class LabelType>
1199template<RectangleConcept OtherRectangle>
1201 if (other.empty()) {
1209 for (
size_t i = 0; i < 4; ++i) {
1217template <
class Po
intType,
class LabelType>
1218template<TriangleConcept OtherTriangle>
1223 for (
size_t i = 0; i < 3; ++i) {
1231template <
class Po
intType,
class LabelType>
1232template<ConvexConcept OtherConvex>
1236 if (other.empty()) {
1247 return other.size() == 1 && (*this)[0] == other[0];
1249 if (
size() == 2 && other.size() == 1) {
1252 if (
size() == 2 && other.size() == 2) {
1256 if (other.size() <= 2*
size()) {
1257 for (
size_t i = 0; i < other.size(); ++i) {
1264 if (!
edge.leftHalfplane().contains(other)) {
1272template <
class Po
intType,
class LabelType>
1273template<DiskConcept OtherDisk>
1275 if (
const auto center = other.getIfPoint()) {
1283 if (!
edge.leftHalfplane().contains(other)) {
1294template <
class Po
intType,
class LabelType>
1295template<Po
intConcept OtherPo
int>
1297 const std::size_t n =
size();
1306 const auto p = point - translation_;
1309 return points_[0] == p;
1317 for (std::size_t i = 0; i < n; ++i) {
1326 for (std::size_t i = 0; i < n; ++i) {
1328 const PointType& b = points_[(i + 1) % n];
1329 if (!(a.y() > p.y())) {
1330 if (b.y() > p.y()) {
1336 if (!(b.y() > p.y())) {
1343 return winding != 0;
1346template <
class Po
intType,
class LabelType>
1347template<SegmentConcept OtherSegment>
1355 if (other.isDegenerate()) {
1359 const std::size_t n =
size();
1364 const auto a = other.min() - translation_;
1365 const auto b = other.max() - translation_;
1371 auto entersClosedAtVertex = [&](std::size_t i,
const auto& q) ->
bool {
1372 const PointType& u = points_[(i + n - 1) % n];
1379 return incoming >= 0 && outgoing >= 0;
1382 return incoming >= 0 || outgoing >= 0;
1384 return incoming >= 0;
1387 for (std::size_t i = 0; i < n; ++i) {
1389 const PointType& d = points_[(i + 1) % n];
1398 const bool straddleEdge = (cSide < 0 && dSide > 0) || (cSide > 0 && dSide < 0);
1399 const bool straddleSeg = (aSide < 0 && bSide > 0) || (aSide > 0 && bSide < 0);
1400 if (straddleEdge && straddleSeg) {
1406 if (
collinear(a, b, c) && a < c && c < b) {
1407 if (!entersClosedAtVertex(i, a) || !entersClosedAtVertex(i, b)) {
1427 if (a == c && !entersClosedAtVertex(i, b)) {
1430 if (b == c && !entersClosedAtVertex(i, a)) {
1438template <
class Po
intType,
class LabelType>
1439template<OrientedSegmentConcept OtherOrientedSegment>
1444template <
class Po
intType,
class LabelType>
1445template<LineConcept OtherLine>
1447 return other.isDegenerate() &&
contains(other.min());
1450template <
class Po
intType,
class LabelType>
1451template<OrientedLineConcept OtherOrientedLine>
1453 return other.isDegenerate() &&
contains(other.source());
1456template <
class Po
intType,
class LabelType>
1457template<RayConcept OtherRay>
1459 return other.isDegenerate() &&
contains(other.source());
1462template <
class Po
intType,
class LabelType>
1463template<HalfplaneConcept OtherHalfplane>
1465 return other.isDegenerate() &&
contains(other.source());
1470template <
class Po
intType,
class LabelType>
1471template<RectangleConcept OtherRectangle>
1473 if (other.empty()) {
1478 for (std::size_t i = 0; i < other.size(); ++i) {
1486template <
class Po
intType,
class LabelType>
1487template<TriangleConcept OtherTriangle>
1489 for (std::size_t i = 0; i < other.size(); ++i) {
1501template <
class Po
intType,
class LabelType>
1502template<ConvexConcept OtherConvex>
1504 using OtherPoint =
typename OtherConvex::PointType;
1505 if (other.size() == 0) {
1511 if (other.size() == 1) {
1522 bool boundaries_intersect =
false;
1523 BoundaryChains<Polygon> mine(*
this);
1524 while (!mine.exhausted()) {
1525 const auto& chain = mine.produceNext();
1527 if (chain.intersects(*their)) {
1528 boundaries_intersect =
true;
1529 if (chain.edgesCross(*their)) {
1536 if (!boundaries_intersect) {
1541 for (std::size_t i = 0; i < other.size(); ++i) {
1564template <
class Po
intType,
class LabelType>
1565template<PolygonConcept OtherPolygon>
1573 if (other.size() == 0) {
1585template <
class Po
intType,
class LabelType>
1586template<PolygonConcept OtherPolygon>
1588 if (other.size() == 0) {
1594 if (other.size() == 1) {
1599 if (
const auto vertex = other.getIfPoint()) {
1612 bool boundaries_intersect =
false;
1614 BoundaryChains<Polygon> mine(*
this);
1615 BoundaryChains<OtherPolygon> theirs(other);
1616 while (!mine.exhausted() || !theirs.exhausted()) {
1617 if (!mine.exhausted()) {
1618 const auto& chain = mine.produceNext();
1619 for (
const auto& their : theirs.produced()) {
1620 if (chain.intersects(their)) {
1621 boundaries_intersect =
true;
1622 if (chain.edgesCross(their)) {
1628 if (!theirs.exhausted()) {
1629 const auto& chain = theirs.produceNext();
1630 for (
const auto& my : mine.produced()) {
1631 if (chain.intersects(my)) {
1632 boundaries_intersect =
true;
1633 if (chain.edgesCross(my)) {
1641 if (!boundaries_intersect) {
1646 for (std::size_t i = 0; i < other.size(); ++i) {
1655template <
class Po
intType,
class LabelType>
1656template<DiskConcept OtherDisk>
1658 if (other.isDegenerate()) {
1662 if (!other.pointInsideInteriorContainedIn(*
this)) {
1667 if (other.interiorsIntersect(
edge)) {
1674template <
class Po
intType,
class LabelType>
1677 [
this](
const auto& value) {
1683template <
class Po
intType,
class LabelType>
1684template <Po
intConcept OtherPo
int>
1687 [
this](
const auto& value) {
1693template <
class Number,
class Label>
1694template<PolygonConcept OtherPolygon>
1696 for (
const auto&
vertex : other) {
1704template <
class Po
intType,
class LabelType>
1705template<PolygonConcept OtherPolygon>
1707 for (
const auto&
vertex : other) {
1715template <
class Po
intType,
class LabelType>
1716template<PolygonConcept OtherPolygon>
1721template <
class Po
intType,
class LabelType>
1722template<PolygonConcept OtherPolygon>
1724 for (
const auto&
vertex : other) {
1732template <
class Po
intType,
class LabelType>
1733template<PolygonConcept OtherPolygon>
1735 for (
const auto&
vertex : other) {
1743template <
class Po
intType,
class LabelType>
1744template<PolygonConcept OtherPolygon>
1746 for (
const auto&
vertex : other) {
1754template <
class Po
intType,
class LabelType>
1755template<PolygonConcept OtherPolygon>
1757 for (
const auto&
vertex : other) {
1765template <
class Po
intType,
class LabelType>
1766template<PolygonConcept OtherPolygon>
1770 return detail::coversNoPoint(other);
1772 for (
const auto&
vertex : other) {
1780template <
class Po
intType,
class LabelType>
1781template<PolygonConcept OtherPolygon>
1783 for (
const auto&
vertex : other) {
1791template <
class Po
intType,
class LabelType>
1792template<PolygonConcept OtherPolygon>
1794 for (
const auto&
vertex : other) {
1802template <
class Po
intType,
class LabelType>
1803template<PolygonConcept OtherPolygon>
1805 for (
const auto&
vertex : other) {
1820template <
class Po
intType,
class LabelType,
class Storage>
1821template<Po
intConcept OtherPo
int>
1829template <
class Po
intType,
class LabelType,
class Storage>
1830template<SegmentConcept OtherSegment>
1840 const auto first = std::upper_bound(
1841 points_.begin(), points_.end(), other.min(),
1842 [
this](
const auto& value,
const PointType& p) { return value < p + translation_; });
1843 for (
auto it = first; it != points_.end(); ++it) {
1845 if (!(
vertex < other.max())) {
1855template <
class Po
intType,
class LabelType,
class Storage>
1856template<OrientedSegmentConcept OtherOrientedSegment>
1861template <
class Po
intType,
class LabelType,
class Storage>
1862template<LineConcept OtherLine>
1864 return other.isDegenerate() &&
contains(other.min());
1867template <
class Po
intType,
class LabelType,
class Storage>
1868template<OrientedLineConcept OtherOrientedLine>
1870 return other.isDegenerate() &&
contains(other.source());
1873template <
class Po
intType,
class LabelType,
class Storage>
1874template<RayConcept OtherRay>
1876 return other.isDegenerate() &&
contains(other.source());
1879template <
class Po
intType,
class LabelType,
class Storage>
1880template<HalfplaneConcept OtherHalfplane>
1882 return other.isDegenerate() &&
contains(other.source());
1885template <
class Po
intType,
class LabelType,
class Storage>
1886template<RectangleConcept OtherRectangle>
1888 if (other.empty()) {
1893 if (!other.isDegenerate()) {
1896 if (other.min() == other.max()) {
1902template <
class Po
intType,
class LabelType,
class Storage>
1903template<TriangleConcept OtherTriangle>
1905 if (!other.isDegenerate()) {
1908 if (other.a() == other.c()) {
1914template <
class Po
intType,
class LabelType,
class Storage>
1915template<ConvexConcept OtherConvex>
1917 if (other.size() == 0) {
1920 if (other.size() == 1) {
1923 if (other.size() == 2) {
1929template <
class Po
intType,
class LabelType,
class Storage>
1930template<PolygonConcept OtherPolygon>
1936 if (!other.isDegenerate()) {
1939 if (other.size() == 0) {
1942 if (other.size() == 1) {
1945 for (
const auto&
edge : other.edgesView()) {
1953template <
class Po
intType,
class LabelType,
class Storage>
1954template<DiskConcept OtherDisk>
1956 return other.a() == other.b() && other.b() == other.c() &&
contains(other.a());
1959template <
class Po
intType,
class LabelType,
class Storage>
1960template<MonotoneChainConcept OtherChain>
1962 if (other.empty()) {
1965 if (other.size() == 1) {
1970 for (std::size_t i = 0; i + 1 < other.size(); ++i) {
1978template <
class Po
intType,
class LabelType,
class Storage>
1979template<Po
intConcept OtherPo
int>
1982 [
this](
const auto& value) {
1991template <
class Number,
class Label>
1992template<MonotoneChainConcept OtherChain>
1994 for (
const auto&
vertex : other) {
2002template <
class Po
intType,
class LabelType>
2003template<MonotoneChainConcept OtherChain>
2005 for (
const auto&
vertex : other) {
2013template <
class Po
intType,
class LabelType>
2014template<MonotoneChainConcept OtherChain>
2019template <
class Po
intType,
class LabelType>
2020template<MonotoneChainConcept OtherChain>
2022 for (
const auto&
vertex : other) {
2030template <
class Po
intType,
class LabelType>
2031template<MonotoneChainConcept OtherChain>
2033 return asLine().contains(other);
2036template <
class Po
intType,
class LabelType>
2037template<MonotoneChainConcept OtherChain>
2039 for (
const auto&
vertex : other) {
2047template <
class Po
intType,
class LabelType>
2048template<MonotoneChainConcept OtherChain>
2050 for (
const auto&
vertex : other) {
2058template <
class Po
intType,
class LabelType>
2059template<MonotoneChainConcept OtherChain>
2063 return detail::coversNoPoint(other);
2065 for (
const auto&
vertex : other) {
2073template <
class Po
intType,
class LabelType>
2074template<MonotoneChainConcept OtherChain>
2076 for (
const auto&
vertex : other) {
2084template <
class Po
intType,
class LabelType>
2085template<MonotoneChainConcept OtherChain>
2087 for (
const auto&
vertex : other) {
2095template <
class Po
intType,
class LabelType>
2096template<MonotoneChainConcept OtherChain>
2098 for (
const auto&
vertex : other) {
2107template <
class Po
intType,
class LabelType>
2108template<MonotoneChainConcept OtherChain>
2110 if (other.empty()) {
2113 if (other.size() == 1) {
2116 for (std::size_t i = 0; i + 1 < other.size(); ++i) {
2132template <
class Po
intType,
class LabelType>
2133template<Po
intConcept OtherPo
int>
2139 return (*
this)[0] == point;
2142 if (
edge.contains(point)) {
2149template <
class Po
intType,
class LabelType>
2150template<SegmentConcept OtherSegment>
2152 if (other.min() == other.max()) {
2167 std::vector<std::pair<CommonPoint, CommonPoint>> overlaps;
2173 const CommonPoint lo =
2174 (
edge.min() < other.min()) ? CommonPoint(other.min()) : CommonPoint(
edge.min());
2175 const CommonPoint hi =
2176 (other.max() <
edge.max()) ? CommonPoint(other.max()) : CommonPoint(
edge.max());
2180 overlaps.emplace_back(lo, hi);
2182 std::sort(overlaps.begin(), overlaps.end());
2183 CommonPoint covered(other.min());
2184 for (
const auto& [lo, hi] : overlaps) {
2192 return !(covered < CommonPoint(other.max()));
2195template <
class Po
intType,
class LabelType>
2196template<OrientedSegmentConcept OtherOrientedSegment>
2201template <
class Po
intType,
class LabelType>
2202template<LineConcept OtherLine>
2204 return other.isDegenerate() &&
contains(other.min());
2207template <
class Po
intType,
class LabelType>
2208template<OrientedLineConcept OtherOrientedLine>
2210 return other.isDegenerate() &&
contains(other.source());
2213template <
class Po
intType,
class LabelType>
2214template<RayConcept OtherRay>
2216 return other.isDegenerate() &&
contains(other.source());
2219template <
class Po
intType,
class LabelType>
2220template<HalfplaneConcept OtherHalfplane>
2222 return other.isDegenerate() &&
contains(other.source());
2225template <
class Po
intType,
class LabelType>
2226template<RectangleConcept OtherRectangle>
2228 if (other.empty()) {
2233 if (!other.isDegenerate()) {
2236 if (other.min() == other.max()) {
2242template <
class Po
intType,
class LabelType>
2243template<TriangleConcept OtherTriangle>
2245 if (!other.isDegenerate()) {
2248 if (other.a() == other.c()) {
2254template <
class Po
intType,
class LabelType>
2255template<ConvexConcept OtherConvex>
2257 if (other.size() == 0) {
2260 if (other.size() == 1) {
2263 if (other.size() == 2) {
2269template <
class Po
intType,
class LabelType>
2270template<PolygonConcept OtherPolygon>
2276 if (!other.isDegenerate()) {
2279 if (other.size() == 0) {
2282 if (other.size() == 1) {
2285 for (
const auto&
edge : other.edgesView()) {
2293template <
class Po
intType,
class LabelType>
2294template<DiskConcept OtherDisk>
2296 return other.a() == other.b() && other.b() == other.c() &&
contains(other.a());
2299template <
class Po
intType,
class LabelType>
2300template<MonotoneChainConcept OtherChain>
2302 if (other.empty()) {
2305 if (other.size() == 1) {
2309 for (std::size_t i = 0; i + 1 < other.size(); ++i) {
2317template <
class Po
intType,
class LabelType>
2318template<PolylineConcept OtherPolyline>
2320 if (other.empty()) {
2323 if (other.size() == 1) {
2327 for (std::size_t i = 0; i + 1 < other.size(); ++i) {
2335template <
class Po
intType,
class LabelType>
2336template<Po
intConcept OtherPo
int>
2339 [
this](
const auto& value) {
2349template <
class Number,
class Label>
2350template<PolylineConcept OtherPolyline>
2352 for (
const auto&
vertex : other) {
2360template <
class Po
intType,
class LabelType>
2361template<PolylineConcept OtherPolyline>
2363 for (
const auto&
vertex : other) {
2371template <
class Po
intType,
class LabelType>
2372template<PolylineConcept OtherPolyline>
2381template <
class Po
intType,
class LabelType>
2382template<PolylineConcept OtherPolyline>
2384 for (
const auto&
vertex : other) {
2392template <
class Po
intType,
class LabelType>
2393template<PolylineConcept OtherPolyline>
2395 return asLine().contains(other);
2398template <
class Po
intType,
class LabelType>
2399template<PolylineConcept OtherPolyline>
2401 for (
const auto&
vertex : other) {
2409template <
class Po
intType,
class LabelType>
2410template<PolylineConcept OtherPolyline>
2412 for (
const auto&
vertex : other) {
2420template <
class Po
intType,
class LabelType>
2421template<PolylineConcept OtherPolyline>
2425 return detail::coversNoPoint(other);
2427 for (
const auto&
vertex : other) {
2435template <
class Po
intType,
class LabelType>
2436template<PolylineConcept OtherPolyline>
2438 for (
const auto&
vertex : other) {
2446template <
class Po
intType,
class LabelType>
2447template<PolylineConcept OtherPolyline>
2449 for (
const auto&
vertex : other) {
2457template <
class Po
intType,
class LabelType>
2458template<PolylineConcept OtherPolyline>
2460 for (
const auto&
vertex : other) {
2470template <
class Po
intType,
class LabelType,
class Storage>
2471template<PolylineConcept OtherPolyline>
2473 if (other.empty()) {
2476 if (other.size() == 1) {
2479 for (std::size_t i = 0; i + 1 < other.size(); ++i) {
2488template <
class Po
intType,
class LabelType>
2489template<PolylineConcept OtherPolyline>
2491 if (other.empty()) {
2494 if (other.size() == 1) {
2497 for (std::size_t i = 0; i + 1 < other.size(); ++i) {
2509template <
class Po
intType,
class LabelType>
2510template <Po
intConcept OtherPo
int>
2512 return pointStatus(point) >= 0;
2515template <
class Po
intType,
class LabelType>
2516template <SegmentConcept OtherSegment>
2522template <
class Po
intType,
class LabelType>
2523template <OrientedSegmentConcept OtherOrientedSegment>
2528template <
class Po
intType,
class LabelType>
2529template <LineConcept OtherLine>
2537 for (
const auto& halfplane : halfplanes_) {
2538 if (!halfplane.contains(other)) {
2545template <
class Po
intType,
class LabelType>
2546template <OrientedLineConcept OtherOrientedLine>
2551template <
class Po
intType,
class LabelType>
2552template <RayConcept OtherRay>
2564 return recessionContains(forward);
2567template <
class Po
intType,
class LabelType>
2568template <HalfplaneConcept OtherHalfplane>
2576 return halfplanes_.empty() || halfplanes_[0].contains(other);
2579template <
class Po
intType,
class LabelType>
2580template <RectangleConcept OtherRectangle>
2582 if (other.empty()) {
2588 const auto vertices = other.vertices();
2597template <
class Po
intType,
class LabelType>
2598template <TriangleConcept OtherTriangle>
2603template <
class Po
intType,
class LabelType>
2604template <DiskConcept OtherDisk>
2610 if (
const auto center = other.getIfPoint()) {
2615 for (
const auto& halfplane : halfplanes_) {
2616 if (!halfplane.contains(other)) {
2623template <
class Po
intType,
class LabelType>
2624template <ConvexConcept OtherConvex>
2627 for (std::size_t i = 0; i < other.size(); ++i) {
2635template <
class Po
intType,
class LabelType>
2636template <MonotoneChainConcept OtherChain>
2639 for (std::size_t i = 0; i < other.size(); ++i) {
2647template <
class Po
intType,
class LabelType>
2648template <PolylineConcept OtherPolyline>
2651 for (std::size_t i = 0; i < other.size(); ++i) {
2659template <
class Po
intType,
class LabelType>
2660template <PolygonConcept OtherPolygon>
2664 for (std::size_t i = 0; i < other.size(); ++i) {
2672template <
class Po
intType,
class LabelType>
2673template <HalfplaneIntersectionConcept OtherRegion>
2677 if (other.empty()) {
2683 for (
const auto& halfplane : halfplanes_) {
2684 if (!halfplane.contains(other)) {
2691template <
class Po
intType,
class LabelType>
2692template <Po
intConcept OtherPo
int>
2695 [
this](
const auto& value) {
2711template <
class Number,
class Label>
2712template <HalfplaneIntersectionConcept OtherRegion>
2716 const Point right(
x() + Number(1),
y());
2717 const Point up(
x(),
y() + Number(1));
2718 return detail::regionInsideHalfplane(other,
Halfplane<Point>(*
this, right)) &&
2724template <
class Po
intType,
class LabelType>
2725template <HalfplaneIntersectionConcept OtherRegion>
2734 return min().contains(other);
2738 const auto a =
min();
2739 const auto b =
max();
2740 const auto dx = b.x() - a.x();
2741 const auto dy = b.y() - a.y();
2742 const PointType aClamp(a.x() + dy, a.y() - dx);
2743 const PointType bClamp(b.x() - dy, b.y() + dx);
2750template <
class Po
intType,
class LabelType>
2751template <HalfplaneIntersectionConcept OtherRegion>
2756template <
class Po
intType,
class LabelType>
2757template <HalfplaneIntersectionConcept OtherRegion>
2763template <
class Po
intType,
class LabelType>
2764template <HalfplaneIntersectionConcept OtherRegion>
2766 return asLine().contains(other);
2769template <
class Po
intType,
class LabelType>
2770template <HalfplaneIntersectionConcept OtherRegion>
2776 const auto dx = b.x() - a.x();
2777 const auto dy = b.y() - a.y();
2778 const PointType clamp(a.x() + dy, a.y() - dx);
2784template <
class Po
intType,
class LabelType>
2785template <HalfplaneIntersectionConcept OtherRegion>
2787 return detail::regionInsideHalfplane(other, *
this);
2790template <
class Po
intType,
class LabelType>
2791template <HalfplaneIntersectionConcept OtherRegion>
2795 return detail::coversNoPoint(other);
2813template <
class Po
intType,
class LabelType>
2814template <HalfplaneIntersectionConcept OtherRegion>
2816 if (other.empty()) {
2820 return vertex->contains(other);
2823 return carrier->contains(other);
2832template <
class Po
intType,
class LabelType>
2833template <HalfplaneIntersectionConcept OtherRegion>
2835 if (other.empty()) {
2838 if (!other.isBounded()) {
2842 using E = detail::region_exact_number_t<typename OtherRegion::NumberType>;
2843 const auto vertices = other.template vertices<E>();
2844 for (
const auto&
vertex : vertices) {
2852template <
class Po
intType,
class LabelType>
2853template <HalfplaneIntersectionConcept OtherRegion>
2856 return other.empty();
2864 for (std::size_t i = 0; i <
size(); ++i) {
2865 if (!detail::regionInsideHalfplane(other,
Halfplane<PointType>((*
this)[i],
get(
static_cast<std::ptrdiff_t
>(i) + 1)))) {
2872template <
class Po
intType,
class LabelType,
class Storage>
2873template <HalfplaneIntersectionConcept OtherRegion>
2875 if (other.empty()) {
2878 if (!other.isDegenerate()) {
2882 [
this](
const auto& carrier) {
2883 using Carrier = std::remove_cvref_t<
decltype(carrier)>;
2884 if constexpr (detail::is_point_v<Carrier> || detail::is_segment_v<Carrier>) {
2890 detail::degenerateRegionCarrier(other));
2893template <
class Po
intType,
class LabelType>
2894template <HalfplaneIntersectionConcept OtherRegion>
2896 if (other.empty()) {
2899 if (!other.isDegenerate()) {
2903 [
this](
const auto& carrier) {
2904 using Carrier = std::remove_cvref_t<
decltype(carrier)>;
2905 if constexpr (detail::is_point_v<Carrier> || detail::is_segment_v<Carrier>) {
2911 detail::degenerateRegionCarrier(other));
2914template <
class Po
intType,
class LabelType>
2915template <HalfplaneIntersectionConcept OtherRegion>
2917 if (other.empty()) {
2920 if (!other.isBounded()) {
2923 using E = detail::region_exact_number_t<typename OtherRegion::NumberType>;
2924 if (other.isDegenerate()) {
2926 [
this](
const auto& carrier) {
2927 using Carrier = std::remove_cvref_t<
decltype(carrier)>;
2928 if constexpr (detail::is_point_v<Carrier> || detail::is_segment_v<Carrier>) {
2934 detail::degenerateRegionCarrier(other));
2936 return contains(other.template asConvex<E>());
2943template <
class Po
intType,
class LabelType>
2944template <Po
intConcept OtherPo
int>
2946 if (!outer_.contains(point)) {
2951 for (
const auto&
hole : holes_) {
2952 if (
hole.interiorContains(point)) {
2959template <
class Po
intType,
class LabelType>
2960template <SegmentConcept OtherSegment>
2964 if (other.isDegenerate()) {
2967 if (!outer_.contains(other)) {
2974 for (
const auto&
hole : holes_) {
2975 if (
hole.interiorsIntersect(other)) {
2982template <
class Po
intType,
class LabelType>
2983template <OrientedSegmentConcept OtherOrientedSegment>
2985 return contains(other.asSegment());
2990template <
class Po
intType,
class LabelType>
2991template <LineConcept OtherLine>
2993 return other.isDegenerate() &&
contains(other.min());
2996template <
class Po
intType,
class LabelType>
2997template <OrientedLineConcept OtherOrientedLine>
2999 return other.isDegenerate() &&
contains(other.source());
3002template <
class Po
intType,
class LabelType>
3003template <RayConcept OtherRay>
3005 return other.isDegenerate() &&
contains(other.source());
3008template <
class Po
intType,
class LabelType>
3009template <HalfplaneConcept OtherHalfplane>
3011 return other.isDegenerate() &&
contains(other.source());
3032template <
class Po
intType,
class LabelType>
3033template <
class OtherArea>
3034constexpr bool PolygonWithHoles<PointType, LabelType>::areaContains(
const OtherArea& other)
const {
3041 if (holes_.empty()) {
3042 return outer_.contains(other);
3059 for (
const auto&
edge : other.edges()) {
3060 if (!contains(
edge)) {
3064 if (other.isDegenerate()) {
3067 for (
const auto& hole : holes_) {
3068 if (hole.pointInsideInteriorContainedIn(other)) {
3075template <
class Po
intType,
class LabelType>
3076template <RectangleConcept OtherRectangle>
3078 if (other.empty()) {
3083 return areaContains(other);
3086template <
class Po
intType,
class LabelType>
3087template <TriangleConcept OtherTriangle>
3089 return areaContains(other);
3092template <
class Po
intType,
class LabelType>
3093template <ConvexConcept OtherConvex>
3095 return areaContains(other);
3098template <
class Po
intType,
class LabelType>
3099template <PolygonConcept OtherPolygon>
3101 return areaContains(other);
3104template <
class Po
intType,
class LabelType>
3105template <PolygonWithHolesConcept OtherRegion>
3107 return areaContains(other);
3116template <
class Po
intType,
class LabelType>
3117template <
class OtherChain,
class EdgeRelation>
3118constexpr bool PolygonWithHoles<PointType, LabelType>::chainRelation(
const OtherChain& other,
3120 EdgeRelation&& relation)
const {
3122 if (other.empty()) {
3126 if (other.size() == 1) {
3127 return relation(ChainSegment(other[0], other[0]));
3129 for (std::size_t i = 0; i + 1 < other.size(); ++i) {
3130 const bool holds = relation(ChainSegment(other[i], other[i + 1]));
3138template <
class Po
intType,
class LabelType>
3139template <MonotoneChainConcept OtherChain>
3141 return chainRelation(other,
true, [
this](
const auto&
edge) {
return this->
contains(
edge); });
3144template <
class Po
intType,
class LabelType>
3145template <PolylineConcept OtherPolyline>
3147 return chainRelation(other,
true, [
this](
const auto&
edge) {
return this->
contains(
edge); });
3159template <
class Po
intType,
class LabelType>
3160template <DiskConcept OtherDisk>
3162 if (other.isDegenerate()) {
3165 if (!outer_.contains(other)) {
3168 for (
const auto&
hole : holes_) {
3169 if (
hole.interiorsIntersect(other)) {
3176template <
class Po
intType,
class LabelType>
3177template <
class OtherIntersection>
3178constexpr auto PolygonWithHoles<PointType, LabelType>::asConvexOperand(
const OtherIntersection& other) {
3179 using E = detail::region_exact_number_t<typename OtherIntersection::NumberType>;
3180 return other.template asConvex<E>();
3183template <
class Po
intType,
class LabelType>
3184template <
class OtherIntersection,
class Relation>
3185constexpr bool PolygonWithHoles<PointType, LabelType>::degenerateIntersectionRelation(
3186 const OtherIntersection& other, Relation&& relation)
const {
3187 return std::visit([&relation](
const auto& carrier) {
return relation(carrier); },
3188 detail::degenerateRegionCarrier(other));
3195template <
class Po
intType,
class LabelType>
3196template <HalfplaneIntersectionConcept OtherIntersection>
3198 if (other.empty()) {
3201 if (other.isDegenerate()) {
3202 return degenerateIntersectionRelation(
3203 other, [
this](
const auto& carrier) {
return this->
contains(carrier); });
3205 if (!other.isBounded()) {
3208 return areaContains(asConvexOperand(other));
3245template <
class Number,
class Label>
3246template <PolygonWithHolesConcept OtherRegion>
3248 return contains(other.outer());
3251template <
class Po
intType,
class LabelType>
3252template <PolygonWithHolesConcept OtherRegion>
3254 return contains(other.outer());
3257template <
class Po
intType,
class LabelType>
3258template <PolygonWithHolesConcept OtherRegion>
3260 return asSegment().contains(other);
3263template <
class Po
intType,
class LabelType>
3264template <PolygonWithHolesConcept OtherRegion>
3266 return contains(other.outer());
3269template <
class Po
intType,
class LabelType>
3270template <PolygonWithHolesConcept OtherRegion>
3272 return asLine().contains(other);
3275template <
class Po
intType,
class LabelType>
3276template <PolygonWithHolesConcept OtherRegion>
3278 return contains(other.outer());
3281template <
class Po
intType,
class LabelType>
3282template <PolygonWithHolesConcept OtherRegion>
3284 return contains(other.outer());
3287template <
class Po
intType,
class LabelType>
3288template <PolygonWithHolesConcept OtherRegion>
3292 return detail::coversNoPoint(other);
3294 return contains(other.outer());
3297template <
class Po
intType,
class LabelType>
3298template <PolygonWithHolesConcept OtherRegion>
3300 return contains(other.outer());
3303template <
class Po
intType,
class LabelType>
3304template <PolygonWithHolesConcept OtherRegion>
3306 return contains(other.outer());
3309template <
class Po
intType,
class LabelType>
3310template <PolygonWithHolesConcept OtherRegion>
3312 return contains(other.outer());
3315template <
class Po
intType,
class LabelType,
class Storage>
3316template <PolygonWithHolesConcept OtherRegion>
3318 return contains(other.outer());
3322template <
class Po
intType,
class LabelType>
3323template <PolygonWithHolesConcept OtherRegion>
3325 if (!other.isDegenerate()) {
3328 return detail::everyHoledRegionEdge(
3329 other, [
this](
const auto&
edge) {
return this->contains(
edge); });
3332template <
class Po
intType,
class LabelType>
3333template <PolygonWithHolesConcept OtherRegion>
3335 return contains(other.outer());
3338template <
class Po
intType,
class LabelType>
3339template <PolygonWithHolesConcept OtherHoledRegion>
3348template <
class Po
intType,
class LabelType>
3349template <Po
intConcept OtherPo
int>
3352 [
this](
const auto& value) {
3367template <
class Po
intType,
class LabelType>
3369 if (pinched_ >= 0) {
3370 return pinched_ != 0;
3373 for (std::size_t i = 0; i < components_.size() && pinched_ == 0; ++i) {
3374 for (std::size_t j = i + 1; j < components_.size(); ++j) {
3378 if (components_[i].
intersects(components_[j])) {
3384 return pinched_ != 0;
3387template <
class Po
intType,
class LabelType>
3388template <
class OtherSegment>
3389bool PolygonSet<PointType, LabelType>::segmentIn(
const OtherSegment& segment,
3390 bool boundaryOnly)
const {
3391 using ExactNumber = detail::Exact1DNumber<NumberType, typename OtherSegment::NumberType>;
3400 if (anyComponent([&](
const ComponentType& component) {
3401 return boundaryOnly ? component.boundaryContains(segment) : component.contains(segment);
3406 const ExactSegment probe(ExactPoint(segment.min()), ExactPoint(segment.max()));
3407 const auto holds = [
this, boundaryOnly](
const ExactPoint& point) {
3408 return anyComponent([&](
const ComponentType& component) {
3409 return boundaryOnly ? component.boundaryContains(point) : component.contains(point);
3412 if (probe.min() == probe.max()) {
3413 return holds(probe.min());
3416 std::vector<ExactPoint> cuts{probe.min(), probe.max()};
3417 for (
const auto& component : components_) {
3418 for (
const auto&
edge : component.edges()) {
3419 const auto piece = probe.template intersection<ExactNumber>(
3420 ExactSegment(ExactPoint(
edge.min()), ExactPoint(
edge.max())));
3424 if (
const auto* touch = std::get_if<0>(&*piece)) {
3425 cuts.push_back(*touch);
3427 const auto& overlap = std::get<1>(*piece);
3428 cuts.push_back(overlap.min());
3429 cuts.push_back(overlap.max());
3435 std::sort(cuts.begin(), cuts.end());
3436 cuts.erase(std::unique(cuts.begin(), cuts.end()), cuts.end());
3438 for (
const ExactPoint& cut : cuts) {
3443 const ExactNumber two(2);
3444 for (std::size_t i = 0; i + 1 < cuts.size(); ++i) {
3445 const ExactPoint middle((cuts[i].
x() + cuts[i + 1].
x()) / two,
3446 (cuts[i].
y() + cuts[i + 1].
y()) / two);
3447 if (!holds(middle)) {
3454template <
class Po
intType,
class LabelType>
3455template <
class OtherChain>
3456bool PolygonSet<PointType, LabelType>::chainIn(
const OtherChain& chain,
bool boundaryOnly)
const {
3457 if (chain.size() == 0) {
3460 if (chain.size() == 1) {
3461 return anyComponent([&](
const ComponentType& component) {
3462 return boundaryOnly ? component.boundaryContains(chain[0]) : component.contains(chain[0]);
3465 for (
const auto&
edge : chain.edgesView()) {
3466 if (!segmentIn(
edge, boundaryOnly)) {
3473template <
class Po
intType,
class LabelType>
3474template <
class OtherRegion>
3475bool PolygonSet<PointType, LabelType>::regionIn(
const OtherRegion& region)
const {
3476 using ExactNumber = detail::Exact1DNumber<NumberType, typename OtherRegion::NumberType>;
3478 const ExactNumber two(2);
3485 for (
const auto&
vertex : region.vertices()) {
3486 if (!anyComponent([&](
const ComponentType& component) {
3487 return component.contains(
vertex);
3495 const auto boundary = region.edges();
3496 for (
const auto&
edge : boundary) {
3497 if (!segmentIn(
edge,
false)) {
3506 for (
const auto& component : components_) {
3507 for (
const auto&
edge : component.edges()) {
3508 if (region.interiorsIntersect(
edge)) {
3520 std::vector<ExactNumber> abscissas;
3521 abscissas.reserve(2 * boundary.size());
3522 for (
const auto&
edge : boundary) {
3523 abscissas.emplace_back(
edge.min().x());
3524 abscissas.emplace_back(
edge.max().x());
3526 std::sort(abscissas.begin(), abscissas.end());
3527 abscissas.erase(std::unique(abscissas.begin(), abscissas.end()), abscissas.end());
3529 std::vector<ExactNumber> ordinates;
3530 for (std::size_t strip = 0; strip + 1 < abscissas.size(); ++strip) {
3531 const ExactNumber
x = (abscissas[strip] + abscissas[strip + 1]) / two;
3533 for (
const auto&
edge : boundary) {
3536 const ExactNumber left(
edge.min().x());
3537 const ExactNumber right(
edge.max().x());
3538 if (!(left <
x) || !(
x < right)) {
3541 const ExactNumber low(
edge.min().y());
3542 const ExactNumber high(
edge.max().y());
3543 ordinates.push_back(low + (high - low) * (
x - left) / (right - left));
3545 std::sort(ordinates.begin(), ordinates.end());
3546 ordinates.erase(std::unique(ordinates.begin(), ordinates.end()), ordinates.end());
3547 for (std::size_t i = 0; i + 1 < ordinates.size(); ++i) {
3548 const ExactPoint witness(
x, (ordinates[i] + ordinates[i + 1]) / two);
3549 if (!region.contains(witness)) {
3552 if (!anyComponent([&](
const ComponentType& component) {
3553 return component.contains(witness);
3562template <
class Po
intType,
class LabelType>
3563template <detail::SetOperandConcept OtherShape>
3578 return other.isDegenerate() &&
contains(other.min());
3580 return other.isDegenerate() &&
contains(other.source());
3582 return other.isDegenerate() &&
contains(other.source());
3586 return other.isDegenerate() &&
contains(other.source());
3596 return segmentIn(other,
false);
3604 return chainIn(other,
false);
3616 if (!
isPinched() || other.vertexCount() == 0) {
3628 return regionIn(other);
3640 return detail::reduceDegenerate(other,
3641 [
this](
const auto& carrier) {
return this->
contains(carrier); });
3645template <
class Po
intType,
class LabelType>
3646template <PolygonSetConcept OtherSet>
3658template <
class Po
intType,
class LabelType>
3659template <Po
intConcept OtherPo
int>
3661 return std::visit([
this](
const auto& value) {
return this->
contains(value); }, other.
variant());
Implementations of the 'boundaryContains' predicate.
Exact rational number class template.
Definition rational.hpp:106
Definition forward.hpp:312
Definition forward.hpp:309
Definition forward.hpp:320
Definition forward.hpp:310
Definition forward.hpp:308
Definition forward.hpp:306
Definition forward.hpp:317
Definition forward.hpp:321
Definition forward.hpp:311
Definition forward.hpp:307
constexpr bool preferSweep(const RedShape &red, const BlueShape &blue)
Whether red against blue is a job for redBlueSweep rather than for a pairwise test of their monotone ...
Definition redbluesweep.hpp:673
Definition arrangement.hpp:67
bool sweepContains(const OuterPolygon &outer, const InnerPolygon &inner)
Sweep-based counterpart of Polygon::contains(Polygon).
Definition redbluesweep.hpp:716
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
@ y
Definition intervaltree.hpp:24
@ x
Definition intervaltree.hpp:24
@ edge
Definition bitmatrix.hpp:37
@ vertex
Definition bitmatrix.hpp:37
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 std::partial_ordering orientationSign(const Point< ANumber, ALabel > &a, const Point< BNumber, BLabel > &b, const Point< CNumber, CLabel > &c)
Classifies the orientation of three points.
Definition orientation.hpp:544
constexpr std::partial_ordering crossSign(const Point< UNumber, ULabel > &u, const Point< VNumber, VLabel > &v)
Classifies the turn from one vector to another.
Definition orientation.hpp:583
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
Exact low-level orientation and incircle predicates.
Small dispatch traits and geometry helpers reused by the implementations.
constexpr const Rectangle< PointType > & bbox() const
Computes the bounding box of the convex polygon.
Definition bounding.hpp:374
constexpr bool empty() const
Returns whether the convex polygon is the empty set of points.
Definition convex.hpp:390
constexpr std::optional< PointType > getIfPoint() const
Returns the point the convex polygon collapses to, if it does.
Definition predicates.hpp:994
constexpr PointType get(std::ptrdiff_t index) const
Cyclic access: same as operator[] but index is taken modulo size(); negative indices wrap from the en...
Definition convex.hpp:289
constexpr bool isDegenerate() const
Checks if the convex polygon is degenerate (has zero area).
Definition predicates.hpp:982
constexpr std::vector< Segment< PointType > > edges() const
Returns the edges of the convex polygon.
Definition convex.hpp:529
constexpr std::optional< BoundaryType< false > > getIfSegment() const
Returns the segment the convex polygon collapses to, if it does.
Definition predicates.hpp:1008
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1135
constexpr auto orientedEdgesView() const
Lazy view counterpart of orientedEdges(); see edgesView().
Definition convex.hpp:583
constexpr std::optional< std::array< Segment< PointType >, 2 > > edgesAtX(OtherNumberType x) const
Returns two edges of the convex polygon that intersect with the vertical line at x.
Definition atxy.hpp:289
size_t size() const
Returns the number of vertices in the convex polygon.
Definition convex.hpp:840
constexpr ResultNumber squaredRadius() const
Returns the squared radius in an explicitly chosen result type.
Definition disk.hpp:402
constexpr Point< ResultNumber, PointLabelType > center() const
Returns the center (circumcenter of the three boundary points) in an explicitly chosen coordinate typ...
Definition disk.hpp:284
constexpr bool isDegenerate() const
Returns whether the three boundary points are collinear.
Definition disk.hpp:348
constexpr const PointType & c() const
Returns the third boundary point in canonical order.
Definition disk.hpp:244
constexpr bool contains(const OtherPoint &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1015
detail::floating_result_t< ResultNumber > squaredDistance(const OtherPoint &point) const
Returns the squared Euclidean distance from this disk to a point.
Definition distance.hpp:1194
constexpr const PointType & a() const
Returns the first boundary point (lexicographically smallest).
Definition disk.hpp:228
constexpr const PointType & b() const
Returns the second boundary point in canonical order.
Definition disk.hpp:235
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2511
constexpr bool empty() const
Returns whether the region is the empty set.
Definition halfplaneintersection.hpp:649
constexpr std::vector< Point< ResultNumber, typename PointType::LabelType > > vertices() const
Returns every vertex of the region, in pair-index order (for a bounded region: counterclockwise).
Definition halfplaneintersection.hpp:890
constexpr std::size_t size() const
Returns the number of stored (non-redundant) half-planes.
Definition halfplaneintersection.hpp:596
constexpr Point< ResultNumber, typename PointType::LabelType > vertex(std::size_t i) const
Returns the vertex between half-planes i and i+1 (cyclically).
Definition halfplaneintersection.hpp:875
Closed half-plane defined by an oriented boundary line.
Definition halfplane.hpp:51
constexpr const PointType & target() const
Returns the target boundary point.
Definition halfplane.hpp:193
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:872
constexpr Line< PointType > asLine() const
Returns the boundary line without orientation.
Definition halfplane.hpp:318
constexpr const PointType & source() const
Returns the source boundary point.
Definition halfplane.hpp:181
constexpr bool isDegenerate() const
Returns whether the defining points coincide.
Definition predicates.hpp:952
Unoriented infinite line.
Definition line.hpp:52
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:428
constexpr const PointType & max() const
Returns the largest stored defining point.
Definition line.hpp:189
constexpr const PointType & min() const
Returns the smallest stored defining point.
Definition line.hpp:180
constexpr bool interiorsIntersect(const OtherPoint &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:328
constexpr bool isDegenerate() const
Returns whether the defining points coincide.
Definition predicates.hpp:451
Weakly x-monotone polyline stored by lexicographically sorted vertices.
Definition monotonechain.hpp:146
constexpr std::optional< std::size_t > isBelow(const OtherPoint &point) const
Tests whether the chain passes weakly below a point.
Definition atxy.hpp:462
PointType_ PointType
Definition monotonechain.hpp:147
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1822
constexpr std::optional< std::size_t > isAbove(const OtherPoint &point) const
Tests whether the chain passes weakly above a point.
Definition atxy.hpp:489
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:531
constexpr Line< PointType > asLine() const
Returns the line without orientation.
Definition orientedline.hpp:321
constexpr Segment< PointType > asSegment() const
Returns the segment without orientation.
Definition orientedsegment.hpp:322
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:346
Two-dimensional point with optional label payload.
Definition point.hpp:129
constexpr Point()=default
Creates the origin point (0, 0).
constexpr std::array< Point, 1 > vertices() const
Returns the unique vertex of the point-shaped object.
Definition bounding.hpp:34
constexpr bool contains(const OtherPoint &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:25
bool intersects(const OtherShape &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:2234
constexpr const ComponentType & component(std::size_t index) const
Accesses a component by index.
Definition polygonset.hpp:271
bool contains(const OtherShape &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:3564
bool isPinched() const
Tests whether two components touch each other anywhere.
Definition contains.hpp:3368
constexpr std::size_t componentCount() const
Returns the number of components.
Definition polygonset.hpp:263
PolygonWithHoles< PointType > ComponentType
Definition polygonset.hpp:169
constexpr const Rectangle< PointType > & bbox() const
Computes the bounding box of the set.
Definition bounding.hpp:469
constexpr const PolygonType & hole(std::size_t index) const
Accesses a hole by index.
Definition polygonwithholes.hpp:196
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2945
constexpr const Rectangle< PointType > & bbox() const
Computes the bounding box of the polygon.
Definition bounding.hpp:449
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1296
constexpr auto edgesView() const
Returns a lazy view over the edges, materializing each Segment on the fly instead of allocating a vec...
Definition polygon.hpp:782
constexpr bool isPoint() const
Checks whether the polygon covers exactly one point.
Definition polygon.hpp:330
constexpr bool containsChainBased(const OtherPolygon &other) const
Same contract as contains(const OtherPolygon&) const, by the chain-pair strategy alone.
Definition contains.hpp:1587
constexpr std::size_t size() const
Returns the number of vertices in the polygon.
Definition polygon.hpp:259
PointType_ PointType
Definition polygon.hpp:60
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2134
constexpr bool empty() const
Checks whether the polyline has no vertex.
Definition polyline.hpp:395
constexpr std::size_t size() const
Returns the number of vertices in the polyline.
Definition polyline.hpp:388
constexpr auto edgesView() const
Returns a lazy view over the edges, materializing each Segment on the fly instead of allocating a vec...
Definition polyline.hpp:627
constexpr bool containsCollinear(const OtherPoint &point) const
Returns whether the ray contains the given point that is collinear with the ray.
Definition predicates.hpp:754
PointType_ PointType
Definition ray.hpp:52
constexpr bool isDegenerate() const
Returns whether the defining points coincide.
Definition predicates.hpp:727
constexpr const PointType & target() const
Returns the second stored point defining the direction.
Definition ray.hpp:193
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:625
constexpr const PointType & source() const
Returns the source point of the ray.
Definition ray.hpp:181
constexpr bool isDegenerate() const
Returns whether the rectangle has empty interior.
Definition predicates.hpp:869
constexpr const PointType & min() const
Returns the minimum corner (min x, min y).
Definition rectangle.hpp:347
constexpr bool empty() const
Returns whether the rectangle is the empty set of points.
Definition rectangle.hpp:290
constexpr std::array< Segment< PointType >, 4 > edges() const
Returns the four edges as unordered segments.
Definition bounding.hpp:199
constexpr Point< ResultNumber > center() const
Returns the center of the rectangle.
Definition measures.hpp:325
PointType_ PointType
Definition rectangle.hpp:76
constexpr const PointType & max() const
Returns the maximum corner (max x, max y).
Definition rectangle.hpp:359
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:728
Unoriented closed segment between two endpoints plus optional segment label.
Definition segment.hpp:58
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:119
constexpr const PointType & max() const
Returns the largest stored endpoint.
Definition segment.hpp:199
TPoint PointType
Definition segment.hpp:59
constexpr const PointType & min() const
Returns the smallest stored endpoint.
Definition segment.hpp:190
constexpr Segment()=default
Creates the degenerate segment (0,0)--(0,0).
Runtime variant wrapper over the supported primitive shapes.
Definition shape.hpp:160
constexpr const Variant & variant() const
Returns the underlying variant.
Definition shape.hpp:264
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:223
constexpr const PointType & b() const
Returns the second vertex.
Definition triangle.hpp:217
constexpr std::array< PointType, 3 > vertices() const
Returns the vertices in canonical order.
Definition bounding.hpp:235
constexpr const PointType & a() const
Returns the first vertex.
Definition triangle.hpp:208
constexpr bool boundaryContains(const OtherPoint &point) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:123
constexpr Rectangle< PointType > bbox() const
Returns the axis-aligned bounding box of the vertices.
Definition bounding.hpp:224
constexpr std::optional< BoundaryType< false > > getIfSegment() const
Returns the segment the triangle collapses to, if it does.
Definition predicates.hpp:255
constexpr Convex< PointType > asConvex() const
Returns the triangle as a convex polygon.
Definition triangle.hpp:490
constexpr bool isDegenerate() const
Tests whether the three vertices are collinear.
Definition predicates.hpp:223
constexpr std::optional< PointType > getIfPoint() const
Returns the point the triangle collapses to, if it does.
Definition predicates.hpp:241
constexpr const PointType & c() const
Returns the third vertex.
Definition triangle.hpp:226