23template <
class Number,
class Label>
24template<Po
intConcept OtherPo
int>
30template <
class Number,
class Label>
33 [
this](
const auto& value) {
34 return this->intersects(value);
46template <
class Po
intType,
class LabelType>
47template<Po
intConcept OtherPo
int>
52template <
class Po
intType,
class LabelType>
53template<SegmentConcept OtherSegment>
55 using Coordinate = detail::sign_coordinate_t<NumberType, typename OtherSegment::NumberType>;
64 const auto a = detail::filtered<Coordinate>(
min());
65 const auto b = detail::filtered<Coordinate>(
max());
66 const auto c = detail::filtered<Coordinate>(other.min());
67 const auto d = detail::filtered<Coordinate>(other.max());
68 const auto s1 = detail::orientationSignOf(a, b, c);
69 const auto s2 = detail::orientationSignOf(a, b, d);
70 const auto s3 = detail::orientationSignOf(c, d, a);
71 const auto s4 = detail::orientationSignOf(c, d, b);
75 if (detail::allDecided(s1, s2, s3, s4)) {
76 return s1.value() != s2.value() && s3.value() != s4.value();
80 const int cross = boundingBoxesCross(other);
88 else if (!boundingBoxesOverlap(other)) {
94 const auto d1 = s1.value();
98 const auto d2 = s2.value();
102 const auto d3 = s3.value();
103 if (d3 == 0 && other.containsCollinear(
min())) {
106 const auto d4 = s4.value();
107 if (d4 == 0 && other.containsCollinear(
max())) {
110 if (d1 == 0 || d2 == 0 || d3 == 0 || d4 == 0) {
113 return d1 != d2 && d3 != d4;
117template <
class Po
intType,
class LabelType>
120 [
this](
const auto& value) {
132template <
class Po
intType,
class LabelType>
133template<Po
intConcept OtherPo
int>
138template <
class Po
intType,
class LabelType>
139template<LineConcept OtherLine>
141 if (other.isDegenerate()) {
146 bool positive =
false, negative =
false;
147 for (
auto p : *
this) {
152 negative = (negative || o < 0);
153 positive = (positive || o > 0);
154 if (positive && negative) {
161template <
class Po
intType,
class LabelType>
162template<OrientedLineConcept OtherOrientedLine>
167template <
class Po
intType,
class LabelType>
168template<SegmentConcept OtherSegment>
176 if (
edge.intersects(other)) {
183template <
class Po
intType,
class LabelType>
184template<OrientedSegmentConcept OtherOrientedSegment>
189template <
class Po
intType,
class LabelType>
190template<RayConcept OtherRay>
197 if (
edge.intersects(other)) {
204template <
class Po
intType,
class LabelType>
205template<HalfplaneConcept OtherHalfplane>
207 if (other.contains(
a()) || other.contains(
b()) || other.contains(
c())) {
211 if (other.intersects(
edge)) {
218template <
class Po
intType,
class LabelType>
219template<RectangleConcept OtherRectangle>
228 if (!other.intersects(
bbox())) {
236 return detail::segmentIntersectsRectangle(other,
a(),
b()) ||
237 detail::segmentIntersectsRectangle(other,
b(),
c()) ||
238 detail::segmentIntersectsRectangle(other,
c(),
a()) ||
242template <
class Po
intType,
class LabelType>
243template<TriangleConcept OtherTriangle>
246 other.contains(
a()) || other.contains(
b()) || other.contains(
c())) {
249 const auto this_edges =
edges();
250 const auto other_edges = other.edges();
251 for (
const auto& left : this_edges) {
252 for (
const auto& right : other_edges) {
253 if (left.intersects(right)) {
261template <
class Po
intType,
class LabelType>
264 [
this](
const auto& value) {
276template <
class Po
intType,
class LabelType>
277template<Po
intConcept OtherPo
int>
282template <
class Po
intType,
class LabelType>
283template<SegmentConcept OtherSegment>
288template <
class Po
intType,
class LabelType>
289template<OrientedSegmentConcept OtherOrientedSegment>
295template <
class Po
intType,
class LabelType>
298 [
this](
const auto& value) {
310template <
class Po
intType,
class LabelType>
311template<Po
intConcept OtherPo
int>
316template <
class Po
intType,
class LabelType>
317template<LineConcept OtherLine>
320 return other.contains(
min());
322 if (other.isDegenerate()) {
328template <
class Po
intType,
class LabelType>
329template<SegmentConcept OtherSegment>
331 if (other.isDegenerate()) {
336 return first == std::partial_ordering::equivalent ||
337 second == std::partial_ordering::equivalent ||
341template <
class Po
intType,
class LabelType>
342template<OrientedSegmentConcept OtherOrientedSegment>
347template <
class Po
intType,
class LabelType>
350 [
this](
const auto& value) {
362template <
class Po
intType,
class LabelType>
363template<Po
intConcept OtherPo
int>
365 return this->
asLine().intersects(other);
368template <
class Po
intType,
class LabelType>
369template<LineConcept OtherLine>
371 return this->
asLine().intersects(other);
374template <
class Po
intType,
class LabelType>
375template<OrientedLineConcept OtherOrientedLine>
377 return this->
asLine().intersects(other.asLine());
380template <
class Po
intType,
class LabelType>
381template<SegmentConcept OtherSegment>
383 return this->
asLine().intersects(other);
386template <
class Po
intType,
class LabelType>
387template<OrientedSegmentConcept OtherOrientedSegment>
389 return this->
asLine().intersects(other);
392template <
class Po
intType,
class LabelType>
395 [
this](
const auto& value) {
407template <
class Po
intType,
class LabelType>
408template<Po
intConcept OtherPo
int>
413template <
class Po
intType,
class LabelType>
414template<LineConcept OtherLine>
416 if (other.isDegenerate()) {
420 if (source_side == 0) {
426 const auto direction_side =
428 return direction_side != 0 && direction_side != source_side;
431template <
class Po
intType,
class LabelType>
432template<OrientedLineConcept OtherOrientedLine>
437template <
class Po
intType,
class LabelType>
438template<SegmentConcept OtherSegment>
440 if (other.isDegenerate()) {
454 this->
asLine().intersects(other);
457template <
class Po
intType,
class LabelType>
458template<OrientedSegmentConcept OtherOrientedSegment>
463template <
class Po
intType,
class LabelType>
464template<RayConcept OtherRay>
467 return other.contains(
source());
469 if (other.isDegenerate()) {
482 this->
asLine().intersects(other);
485template <
class Po
intType,
class LabelType>
488 [
this](
const auto& value) {
500template <
class Po
intType,
class LabelType>
501template<Po
intConcept OtherPo
int>
508template <
class Po
intType,
class LabelType>
509template<RectangleConcept OtherRectangle>
516 return intervalsOverlap(
min().
x(),
max().
x(), other.min().x(), other.max().x()) &&
517 intervalsOverlap(
min().
y(),
max().
y(), other.min().y(), other.max().y()) &&
518 !
empty() && !other.empty();
521template <
class Po
intType,
class LabelType>
522template<LineConcept OtherLine>
528 if (other.isDegenerate()) {
531 return detail::lineIntersectsRectangle(*
this, other.min(), other.max());
534template <
class Po
intType,
class LabelType>
535template<OrientedLineConcept OtherOrientedLine>
541 if (other.isDegenerate()) {
544 return detail::lineIntersectsRectangle(*
this, other.source(), other.target());
547template <
class Po
intType,
class LabelType>
548template<SegmentConcept OtherSegment>
554 return detail::segmentIntersectsRectangle(*
this, other.min(), other.max());
557template <
class Po
intType,
class LabelType>
558template<OrientedSegmentConcept OtherOrientedSegment>
564 return detail::segmentIntersectsRectangle(*
this, other.source(), other.target());
567template <
class Po
intType,
class LabelType>
568template<RayConcept OtherRay>
577 const auto rectangle_edges =
edges();
578 for (
const auto&
edge : rectangle_edges) {
579 if (other.intersects(
edge)) {
586template <
class Po
intType,
class LabelType>
587template<HalfplaneConcept OtherHalfplane>
593 if (other.isDegenerate()) {
596 const auto rectangle_vertices =
vertices();
597 for (
const auto&
vertex : rectangle_vertices) {
598 if (other.contains(
vertex)) {
605template <
class Po
intType,
class LabelType>
608 [
this](
const auto& value) {
620template <
class Po
intType,
class LabelType>
621template<Po
intConcept OtherPo
int>
626template <
class Po
intType,
class LabelType>
627template<LineConcept OtherLine>
630 return other.contains(
source());
632 if (other.isDegenerate()) {
642template <
class Po
intType,
class LabelType>
643template<OrientedLineConcept OtherOrientedLine>
646 return other.contains(
source());
648 if (other.isDegenerate()) {
655template <
class Po
intType,
class LabelType>
656template<SegmentConcept OtherSegment>
659 return other.contains(
source());
664template <
class Po
intType,
class LabelType>
665template<OrientedSegmentConcept OtherOrientedSegment>
668 return other.contains(
source());
673template <
class Po
intType,
class LabelType>
674template<RayConcept OtherRay>
677 return other.contains(
source());
679 if (other.isDegenerate()) {
686template <
class Po
intType,
class LabelType>
687template<HalfplaneConcept OtherHalfplane>
701template <
class Po
intType,
class LabelType>
704 [
this](
const auto& value) {
714template <
class Po
intType,
class LabelType>
715template<SegmentConcept OtherSegment>
723 auto translatedOther = other - translation_;
724 auto it1 = detail::cyclicMaxOrPositive(points_.begin(), points_.end(), [&translatedOther](
const PointType& a) {
725 return orientationDeterminant(translatedOther[0], translatedOther[1], a);
727 auto it2 = detail::cyclicMaxOrPositive(points_.begin(), points_.end(), [&translatedOther](
const PointType& a) {
728 return orientationDeterminant(translatedOther[1], translatedOther[0], a);
734template <
class Po
intType,
class LabelType>
735template<OrientedSegmentConcept OtherOrientedSegment>
740template <
class Po
intType,
class LabelType>
741template<LineConcept OtherLine>
743 auto translatedOther = other - translation_;
744 auto it1 = detail::cyclicMaxOrPositive(points_.begin(), points_.end(), [&translatedOther](
const PointType& a) {
745 return orientationDeterminant(translatedOther[0], translatedOther[1], a);
747 auto it2 = detail::cyclicMaxOrPositive(points_.begin(), points_.end(), [&translatedOther](
const PointType& a) {
748 return orientationDeterminant(translatedOther[1], translatedOther[0], a);
754template <
class Po
intType,
class LabelType>
755template<OrientedLineConcept OtherOrientedLine>
760template <
class Po
intType,
class LabelType>
761template<RayConcept OtherRay>
767 auto translatedOther = other - translation_;
768 auto it1 = detail::cyclicMaxOrPositive(points_.begin(), points_.end(), [&translatedOther](
const PointType& a) {
769 return orientationDeterminant(translatedOther[0], translatedOther[1], a);
771 auto it2 = detail::cyclicMaxOrPositive(points_.begin(), points_.end(), [&translatedOther](
const PointType& a) {
772 return orientationDeterminant(translatedOther[1], translatedOther[0], a);
778template <
class Po
intType,
class LabelType>
779template<RectangleConcept OtherRectangle>
792 if (other.contains(points_[0])) {
796 for (
auto &
edge : other.edges()) {
805template <
class Po
intType,
class LabelType>
806template<TriangleConcept OtherTriangle>
814 if (other.contains(points_[0])) {
818 for (
auto &
edge : other.edges()) {
827template <
class Po
intType,
class LabelType>
828template<Po
intConcept OtherPo
int>
836template <
class Po
intType,
class LabelType>
837template<HalfplaneConcept OtherHalfplane>
839 if (points_.empty()) {
842 if (other.isDegenerate()) {
849 const auto it = detail::cyclicMaxOrPositive(points_.begin(), points_.end(),
851 return orientationDeterminant(other.source(), other.target(), a + translation_);
853 return other.contains(*it + translation_);
856template <
class Po
intType,
class LabelType>
857template<ConvexConcept OtherConvex>
859 if (
size() > other.size()) {
860 return other.intersects(*
this);
862 if (
size() == 0 || other.size() == 0) {
868 if (
bbox().
separates(other.bbox()) || other.bbox().separates(this->bbox())) {
872 if (
contains(other[0]) || other.contains((*
this)[0])) {
877 if (other.intersects(
edge)) {
885template <
class Po
intType,
class LabelType>
886template<DiskConcept OtherDisk>
892 if (
edge.intersects(other)) {
902template <
class Po
intType,
class LabelType>
903template<SegmentConcept OtherSegment>
910 return other.contains(*point);
930 using W = detail::promoted_number_t<
937 if (squared_length == W{}) {
940 const W m = squared_length * det;
942 const W projection = (j0 - j1) * det;
943 const W half_span = m * det;
944 const W discriminant_base = j0 + j1 + m;
946 const bool foot_on_segment = projection >= -half_span && projection <= half_span;
947 const bool reaches_disk = discriminant_base * discriminant_base >= W{4} * j0 * j1;
949 return foot_on_segment && reaches_disk;
952template <
class Po
intType,
class LabelType>
953template<DiskConcept OtherDisk>
955 using R = std::conditional_t<
956 std::is_floating_point_v<NumberType> ||
957 std::is_floating_point_v<typename OtherDisk::NumberType>,
965 const R A = d2 - r1_sq - r2_sq;
966 return A <= R{} || A * A <= R{4} * r1_sq * r2_sq;
969template <
class Po
intType,
class LabelType>
970template <Po
intConcept OtherPo
int>
973 [
this](
const auto& value) {
983template <
class Po
intType,
class LabelType>
984template<Po
intConcept OtherPo
int>
989template <
class Po
intType,
class LabelType>
990template<SegmentConcept OtherSegment>
998 if (
edge.intersects(other)) {
1005template <
class Po
intType,
class LabelType>
1006template<OrientedSegmentConcept OtherOrientedSegment>
1011template <
class Po
intType,
class LabelType>
1012template<LineConcept OtherLine>
1014 if (other.isDegenerate()) {
1020 bool positive =
false, negative =
false;
1026 negative = negative || o < 0;
1027 positive = positive || o > 0;
1028 if (positive && negative) {
1035template <
class Po
intType,
class LabelType>
1036template<OrientedLineConcept OtherOrientedLine>
1041template <
class Po
intType,
class LabelType>
1042template<RayConcept OtherRay>
1048 if (
edge.intersects(other)) {
1055template <
class Po
intType,
class LabelType>
1056template<HalfplaneConcept OtherHalfplane>
1058 if (other.isDegenerate()) {
1064 if (other.contains(
vertex)) {
1073template <
class Po
intType,
class LabelType>
1074template<RectangleConcept OtherRectangle>
1076 if (other.empty()) {
1089 if (other.contains((*
this)[0]) ||
contains(other[0])) {
1093 if (other.intersects(
edge)) {
1100template <
class Po
intType,
class LabelType>
1101template<TriangleConcept OtherTriangle>
1112 if (other.contains((*
this)[0]) ||
contains(other[0])) {
1116 if (other.intersects(
edge)) {
1123template <
class Po
intType,
class LabelType>
1124template<ConvexConcept OtherConvex>
1126 if (
size() == 0 || other.size() == 0) {
1132 if (
bbox().
separates(other.bbox()) || other.bbox().separates(this->bbox())) {
1135 if (other.contains((*
this)[0]) ||
contains(other[0])) {
1139 if (other.intersects(
edge)) {
1146template <
class Po
intType,
class LabelType>
1147template<PolygonConcept OtherPolygon>
1149 if (
size() == 0 || other.size() == 0) {
1167 return contains(other.get(0)) || other.contains(
get(0));
1170template <
class Po
intType,
class LabelType>
1171template<Po
intConcept OtherPo
int>
1174 [
this](
const auto& value) {
1180template <
class Po
intType,
class LabelType>
1181template<Po
intConcept OtherPo
int>
1186template <
class Po
intType,
class LabelType>
1187template<OrientedSegmentConcept OtherOrientedSegment>
1192template <
class Po
intType,
class LabelType>
1193template<LineConcept OtherLine>
1198 return other.contains(*point);
1211 using W = detail::promoted_number_t<
1218 if (squared_length == W{}) {
1221 const W discriminant_base = j0 + j1 + squared_length * det;
1223 return discriminant_base * discriminant_base >= W{4} * j0 * j1;
1226template <
class Po
intType,
class LabelType>
1227template<OrientedLineConcept OtherOrientedLine>
1232template <
class Po
intType,
class LabelType>
1233template<RayConcept OtherRay>
1238 return other.contains(*
center);
1254 using W = detail::promoted_number_t<
1261 const W m = squared_length * det;
1263 const W projection = (j0 - j1) * det;
1264 const W half_span = m * det;
1265 const W discriminant_base = j0 + j1 + m;
1267 const bool reaches_disk = discriminant_base * discriminant_base >= W{4} * j0 * j1;
1268 const bool contact_ahead = projection < half_span;
1270 return reaches_disk && contact_ahead;
1273template <
class Po
intType,
class LabelType>
1274template<HalfplaneConcept OtherHalfplane>
1276 return other.contains((*
this)[0]) ||
intersects(other.asLine());
1279template <
class Po
intType,
class LabelType>
1280template<RectangleConcept OtherRectangle>
1282 if (other.empty()) {
1291 for (
const auto&
edge : other.edges()) {
1296 return other.contains((*
this)[0]);
1299template <
class Po
intType,
class LabelType>
1300template<TriangleConcept OtherTriangle>
1307 for (
const auto&
edge : other.edges()) {
1312 return other.contains((*
this)[0]);
1315template <
class Po
intType,
class LabelType>
1316template<Po
intConcept OtherPo
int>
1319 [
this](
const auto& value) {
1326template <
class Po
intType,
class LabelType>
1327template<DiskConcept OtherDisk>
1337 if (
edge.intersects(other)) {
1351template <
class Po
intType,
class LabelType,
class Storage>
1352template<Po
intConcept OtherPo
int>
1357template <
class Po
intType,
class LabelType,
class Storage>
1358template<SegmentConcept OtherSegment>
1360 if (points_.empty()) {
1363 if (points_.size() == 1) {
1364 return other.contains((*
this)[0]);
1366 const auto window = edgeWindow(other.min().x(), other.max().x());
1370 for (std::size_t i = window->first; i <= window->second; ++i) {
1371 if (this->
template boundaryAt<false>(i).
intersects(other)) {
1378template <
class Po
intType,
class LabelType,
class Storage>
1379template<OrientedSegmentConcept OtherOrientedSegment>
1384template <
class Po
intType,
class LabelType,
class Storage>
1385template<LineConcept OtherLine>
1391 return other.contains((*
this)[0]);
1393 for (std::size_t i = 0; i + 1 <
size(); ++i) {
1394 if (this->
template boundaryAt<false>(i).
intersects(other)) {
1401template <
class Po
intType,
class LabelType,
class Storage>
1402template<OrientedLineConcept OtherOrientedLine>
1408 return other.contains((*
this)[0]);
1410 for (std::size_t i = 0; i + 1 <
size(); ++i) {
1411 if (this->
template boundaryAt<false>(i).
intersects(other)) {
1418template <
class Po
intType,
class LabelType,
class Storage>
1419template<RayConcept OtherRay>
1425 return other.contains((*
this)[0]);
1427 for (std::size_t i = 0; i + 1 <
size(); ++i) {
1428 if (this->
template boundaryAt<false>(i).
intersects(other)) {
1435template <
class Po
intType,
class LabelType,
class Storage>
1436template<HalfplaneConcept OtherHalfplane>
1442 return other.contains((*
this)[0]);
1444 for (std::size_t i = 0; i + 1 <
size(); ++i) {
1445 if (this->
template boundaryAt<false>(i).
intersects(other)) {
1452template <
class Po
intType,
class LabelType,
class Storage>
1453template<RectangleConcept OtherRectangle>
1455 if (other.empty()) {
1463 return other.contains((*
this)[0]);
1467 const auto window = edgeWindow(other.min().x(), other.max().x());
1471 for (std::size_t i = window->first; i <= window->second; ++i) {
1472 if (this->
template boundaryAt<false>(i).
intersects(other)) {
1479template <
class Po
intType,
class LabelType,
class Storage>
1480template<TriangleConcept OtherTriangle>
1486 return other.contains((*
this)[0]);
1488 for (std::size_t i = 0; i + 1 <
size(); ++i) {
1489 if (this->
template boundaryAt<false>(i).
intersects(other)) {
1496template <
class Po
intType,
class LabelType,
class Storage>
1497template<ConvexConcept OtherConvex>
1503 return other.contains((*
this)[0]);
1505 for (std::size_t i = 0; i + 1 <
size(); ++i) {
1506 if (this->
template boundaryAt<false>(i).
intersects(other)) {
1513template <
class Po
intType,
class LabelType,
class Storage>
1514template<DiskConcept OtherDisk>
1520 return other.contains((*
this)[0]);
1522 for (std::size_t i = 0; i + 1 <
size(); ++i) {
1523 if (this->
template boundaryAt<false>(i).
intersects(other)) {
1530template <
class Po
intType,
class LabelType,
class Storage>
1531template<Po
intConcept OtherPo
int>
1534 [
this](
const auto& value) {
1540template <
class Po
intType,
class LabelType,
class Storage>
1541template<MonotoneChainConcept OtherChain>
1543 if (
empty() || other.empty()) {
1547 return other.contains((*
this)[0]);
1549 if (other.size() == 1) {
1552 if ((*
this)[
size() - 1].
x() < other[0].
x() || other[other.size() - 1].x() < (*
this)[0].x()) {
1560 const std::size_t iEnd =
size() - 1;
1561 const std::size_t jEnd = other.size() - 1;
1567 using XType = std::common_type_t<NumberType, typename OtherChain::PointType::NumberType>;
1568 const XType xlo = std::max<XType>((*
this)[0].
x(), other[0].
x());
1570 const auto jSeed = other.indexAtX(xlo);
1574 std::size_t i = (iSeed && jSeed) ? (*iSeed > 0 ? *iSeed - 1 : 0) : iEnd;
1575 std::size_t j = (iSeed && jSeed) ? (*jSeed > 0 ? *jSeed - 1 : 0) : jEnd;
1576 while (i < iEnd && j < jEnd) {
1579 if (!(mine.
max().x() < theirs.
min().x() || theirs.
max().x() < mine.
min().x()) &&
1583 const auto order = mine.
max() <=> theirs.
max();
1594template <
class Po
intType,
class LabelType>
1595template<MonotoneChainConcept OtherChain>
1597 if (other.empty()) {
1600 if (other.size() == 1) {
1603 for (std::size_t i = 0; i + 1 < other.size(); ++i) {
1618template <
class Po
intType,
class LabelType>
1619template<Po
intConcept OtherPo
int>
1624template <
class Po
intType,
class LabelType>
1625template<SegmentConcept OtherSegment>
1631 return other.contains((*
this)[0]);
1634 if (
edge.intersects(other)) {
1641template <
class Po
intType,
class LabelType>
1642template<OrientedSegmentConcept OtherOrientedSegment>
1652template <
class PolylineType,
class OtherShape>
1653constexpr bool polylineIntersects(
const PolylineType& polyline,
const OtherShape& other) {
1654 if (polyline.empty()) {
1657 if (polyline.size() == 1) {
1658 return other.contains(polyline[0]);
1660 for (
const auto&
edge : polyline.edgesView()) {
1661 if (
edge.intersects(other)) {
1670template <
class Po
intType,
class LabelType>
1671template<LineConcept OtherLine>
1673 return detail::polylineIntersects(*
this, other);
1676template <
class Po
intType,
class LabelType>
1677template<OrientedLineConcept OtherOrientedLine>
1679 return detail::polylineIntersects(*
this, other);
1682template <
class Po
intType,
class LabelType>
1683template<RayConcept OtherRay>
1685 return detail::polylineIntersects(*
this, other);
1688template <
class Po
intType,
class LabelType>
1689template<HalfplaneConcept OtherHalfplane>
1691 return detail::polylineIntersects(*
this, other);
1694template <
class Po
intType,
class LabelType>
1695template<RectangleConcept OtherRectangle>
1697 if (other.empty()) {
1704 return detail::polylineIntersects(*
this, other);
1707template <
class Po
intType,
class LabelType>
1708template<TriangleConcept OtherTriangle>
1710 return detail::polylineIntersects(*
this, other);
1713template <
class Po
intType,
class LabelType>
1714template<ConvexConcept OtherConvex>
1716 return detail::polylineIntersects(*
this, other);
1719template <
class Po
intType,
class LabelType>
1720template<DiskConcept OtherDisk>
1722 return detail::polylineIntersects(*
this, other);
1725template <
class Po
intType,
class LabelType>
1726template<MonotoneChainConcept OtherChain>
1728 if (
empty() || other.empty()) {
1732 return other.contains((*
this)[0]);
1734 if (other.size() == 1) {
1743 if (other.intersects(
edge)) {
1750template <
class Po
intType,
class LabelType>
1751template<PolylineConcept OtherPolyline>
1753 if (
empty() || other.empty()) {
1757 return other.contains((*
this)[0]);
1759 if (other.size() == 1) {
1766 for (
const auto& theirs : other.edgesView()) {
1767 if (mine.intersects(theirs)) {
1775template <
class Po
intType,
class LabelType>
1776template<Po
intConcept OtherPo
int>
1779 [
this](
const auto& value) {
1785template <
class Po
intType,
class LabelType>
1786template<PolylineConcept OtherPolyline>
1788 if (other.empty()) {
1791 if (other.size() == 1) {
1794 for (std::size_t i = 0; i + 1 < other.size(); ++i) {
1806template <
class Po
intType,
class LabelType>
1807template <Po
intConcept OtherPo
int>
1812template <
class Po
intType,
class LabelType>
1813template <SegmentConcept OtherSegment>
1818 if (halfplanes_.empty()) {
1821 if (other.isDegenerate()) {
1828 const auto clip = clipLine(along);
1832 if (clip.entry >= 0 && constraintSide(
static_cast<std::size_t
>(clip.entry), other.max()) < 0) {
1835 if (clip.exit >= 0 && constraintSide(
static_cast<std::size_t
>(clip.exit), other.min()) < 0) {
1841template <
class Po
intType,
class LabelType>
1842template <OrientedSegmentConcept OtherOrientedSegment>
1847template <
class Po
intType,
class LabelType>
1848template <LineConcept OtherLine>
1853 if (halfplanes_.empty()) {
1857 return !clipLine(along).empty;
1860template <
class Po
intType,
class LabelType>
1861template <OrientedLineConcept OtherOrientedLine>
1866template <
class Po
intType,
class LabelType>
1867template <RayConcept OtherRay>
1872 if (halfplanes_.empty()) {
1876 const auto clip = clipLine(along);
1882 return clip.exit < 0 || constraintSide(
static_cast<std::size_t
>(clip.exit), other.source()) >= 0;
1885template <
class Po
intType,
class LabelType>
1886template <HalfplaneConcept OtherHalfplane>
1891 if (halfplanes_.empty()) {
1896 return supStatus(other.opposite()) != SupStatus::below;
1899template <
class Po
intType,
class LabelType>
1900template <RectangleConcept OtherRectangle>
1902 if (other.empty()) {
1911template <
class Po
intType,
class LabelType>
1912template <TriangleConcept OtherTriangle>
1917template <
class Po
intType,
class LabelType>
1918template <ConvexConcept OtherConvex>
1920 if (other.size() == 0) {
1926template <
class Po
intType,
class LabelType>
1927template <DiskConcept OtherDisk>
1932 if (halfplanes_.empty()) {
1937 using E = detail::region_exact_number_t<NumberType>;
1938 const auto clipped = detail::regionClippedToBox(*
this, other.bbox());
1939 if (clipped.empty()) {
1942 return clipped.template
asConvex<E>().intersects(other);
1945template <
class Po
intType,
class LabelType>
1946template <MonotoneChainConcept OtherChain>
1948 if (
empty() || other.size() == 0) {
1951 if (other.size() == 1) {
1954 for (
const auto&
edge : other.edgesView()) {
1962template <
class Po
intType,
class LabelType>
1963template <PolylineConcept OtherPolyline>
1965 if (
empty() || other.size() == 0) {
1968 if (other.size() == 1) {
1971 for (
const auto&
edge : other.edgesView()) {
1979template <
class Po
intType,
class LabelType>
1980template <PolygonConcept OtherPolygon>
1982 if (
empty() || other.size() == 0) {
1987 for (std::size_t i = 0; i < other.size(); ++i) {
1992 for (
const auto&
edge : other.edgesView()) {
1997 using E = detail::region_exact_number_t<NumberType>;
2001template <
class Po
intType,
class LabelType>
2002template <HalfplaneIntersectionConcept OtherRegion>
2006 if (
empty() || other.empty()) {
2012template <
class Po
intType,
class LabelType>
2013template <Po
intConcept OtherPo
int>
2016 [
this](
const auto& value) {
2026template <
class Po
intType,
class LabelType>
2027template <SegmentConcept OtherSegment>
2029 if (!outer_.intersects(other)) {
2032 if (holes_.empty()) {
2038 if (anyBoundaryEdge([&other](
const auto&
edge) {
return edge.intersects(other); })) {
2047template <
class Po
intType,
class LabelType>
2048template <OrientedSegmentConcept OtherOrientedSegment>
2058template <
class Po
intType,
class LabelType>
2059template <LineConcept OtherLine>
2061 if (other.isDegenerate()) {
2064 return outer_.intersects(other);
2067template <
class Po
intType,
class LabelType>
2068template <OrientedLineConcept OtherOrientedLine>
2073template <
class Po
intType,
class LabelType>
2074template <RayConcept OtherRay>
2076 if (other.isDegenerate()) {
2079 return outer_.intersects(other);
2082template <
class Po
intType,
class LabelType>
2083template <HalfplaneConcept OtherHalfplane>
2085 if (other.isDegenerate()) {
2088 return outer_.intersects(other);
2095template <
class Po
intType,
class LabelType>
2096template <
class OtherArea>
2097constexpr bool PolygonWithHoles<PointType, LabelType>::areaIntersects(
const OtherArea& other)
const {
2098 if (!other.intersects(outer_)) {
2101 if (holes_.empty()) {
2104 if (anyBoundaryEdge([&other](
const auto&
edge) {
return edge.intersects(other); })) {
2107 const auto edges = other.edges();
2108 return !edges.empty() && contains(edges.front().min());
2111template <
class Po
intType,
class LabelType>
2112template <RectangleConcept OtherRectangle>
2114 if (other.empty()) {
2118 return areaIntersects(other);
2121template <
class Po
intType,
class LabelType>
2122template <TriangleConcept OtherTriangle>
2124 return areaIntersects(other);
2127template <
class Po
intType,
class LabelType>
2128template <ConvexConcept OtherConvex>
2130 return areaIntersects(other);
2133template <
class Po
intType,
class LabelType>
2134template <PolygonConcept OtherPolygon>
2136 return areaIntersects(other);
2139template <
class Po
intType,
class LabelType>
2140template <PolygonWithHolesConcept OtherRegion>
2142 return areaIntersects(other);
2147template <
class Po
intType,
class LabelType>
2148template <MonotoneChainConcept OtherChain>
2150 return chainRelation(other,
false, [
this](
const auto&
edge) {
return this->
intersects(
edge); });
2153template <
class Po
intType,
class LabelType>
2154template <PolylineConcept OtherPolyline>
2156 return chainRelation(other,
false, [
this](
const auto&
edge) {
return this->
intersects(
edge); });
2163template <
class Po
intType,
class LabelType>
2164template <DiskConcept OtherDisk>
2166 if (other.isDegenerate()) {
2171 if (!other.intersects(outer_)) {
2174 if (holes_.empty()) {
2177 if (anyBoundaryEdge([&other](
const auto&
edge) {
return other.intersects(
edge); })) {
2186template <
class Po
intType,
class LabelType>
2187template <HalfplaneIntersectionConcept OtherIntersection>
2189 if (other.empty()) {
2192 if (!other.intersects(outer_)) {
2195 if (holes_.empty()) {
2198 if (anyBoundaryEdge([&other](
const auto&
edge) {
return other.intersects(
edge); })) {
2201 using E = detail::region_exact_number_t<typename OtherIntersection::NumberType>;
2215template <
class Po
intType,
class LabelType>
2216template <Po
intConcept OtherPo
int>
2219 [
this](
const auto& value) {
2232template <
class Po
intType,
class LabelType>
2233template <detail::SetOperandConcept OtherShape>
2238template <
class Po
intType,
class LabelType>
2239template <PolygonSetConcept OtherSet>
2249template <
class Po
intType,
class LabelType>
2250template <Po
intConcept OtherPo
int>
2252 return std::visit([
this](
const auto& value) {
return this->
intersects(value); },
Exact rational number class template.
Definition rational.hpp:106
Implementations of the 'interiorsIntersect' predicate.
Definition arrangement.hpp:67
@ y
Definition intervaltree.hpp:24
@ x
Definition intervaltree.hpp:24
constexpr auto inCircleDeterminant(const Point< ANumber, ALabel > &a, const Point< BNumber, BLabel > &b, const Point< CNumber, CLabel > &c, const Point< DNumber, DLabel > &d)
Returns the signed in-circle determinant of a query point.
Definition orientation.hpp:857
constexpr bool is_Rational_v
Definition rational.hpp:37
@ edge
Definition bitmatrix.hpp:37
@ vertex
Definition bitmatrix.hpp:37
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 auto orientationDeterminant(const Point< ANumber, ALabel > &a, const Point< BNumber, BLabel > &b, const Point< CNumber, CLabel > &c)
Returns the signed orientation determinant of three points.
Definition orientation.hpp:518
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 intersects(const OtherSegment &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:716
constexpr auto edgesView() const
Returns a lazy view over the edges, materializing each Segment on the fly instead of allocating a vec...
Definition convex.hpp:575
constexpr bool separates(const EmptyShape< EmptyPoint > &) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition convex.hpp:1345
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1135
size_t size() const
Returns the number of vertices in the convex polygon.
Definition convex.hpp:840
PointType_ PointType
Definition convex.hpp:171
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 intersects(const OtherSegment &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:904
constexpr std::optional< PointType > getIfPoint() const
Returns the point the disk collapses to, if it does.
Definition disk.hpp:372
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 EmptyShape< EmptyPoint > intersection(const EmptyShape< EmptyPoint > &) const
Returns the intersection of the two shapes (A ∩ B), empty when they are disjoint.
Definition halfplaneintersection.hpp:1762
constexpr Convex< Point< ResultNumber, typename PointType::LabelType > > asConvex() const
Returns the region as a convex polygon.
Definition halfplaneintersection.hpp:955
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1808
constexpr Point< ResultNumber > pointInside() const
Returns a representative point of the region: a point of its interior when the region is full-dimensi...
Definition measures.hpp:1350
constexpr std::variant< Segment< Point< ResultNumber, typename PointType::LabelType > >, Ray< Point< ResultNumber, typename PointType::LabelType > >, Line< Point< ResultNumber, typename PointType::LabelType > > > edge(std::size_t i) const
Returns the boundary contribution of half-plane i as a typed one-dimensional shape.
Definition halfplaneintersection.hpp:919
Closed half-plane defined by an oriented boundary line.
Definition halfplane.hpp:51
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:622
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 bool parallel(const OtherLine &other) const
Returns whether another line is parallel to this line.
Definition predicates.hpp:508
constexpr const PointType & min() const
Returns the smallest stored defining point.
Definition line.hpp:180
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:312
constexpr bool isDegenerate() const
Returns whether the defining points coincide.
Definition predicates.hpp:451
constexpr std::optional< std::size_t > indexAtX(const OtherNumber &x) const
Locates the vertex or edge of the chain at a given x-coordinate.
Definition atxy.hpp:346
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1353
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1822
constexpr std::size_t size() const
Returns the number of vertices in the chain.
Definition monotonechain.hpp:393
constexpr bool empty() const
Checks whether the chain has no vertex.
Definition monotonechain.hpp:400
constexpr Line< PointType > asLine() const
Returns the line without orientation.
Definition orientedline.hpp:321
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:364
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:278
Two-dimensional point with optional label payload.
Definition point.hpp:129
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:25
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
PolygonWithHoles< PointType > ComponentType
Definition polygonset.hpp:169
Point< ResultNumber > pointInside() const
Returns a point strictly inside the region.
Definition triangulation.hpp:6989
constexpr bool intersects(const OtherPoint &point) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition polygonwithholes.hpp:1649
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2945
constexpr bool intersects(const OtherChain &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1596
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 boundariesIntersect(const OtherPolygon &other) const
Tests whether the two polygon boundaries share at least one point (∂A ∩ ∂B ≠ ∅).
Definition interiorsintersect.hpp:1197
constexpr std::size_t size() const
Returns the number of vertices in the polygon.
Definition polygon.hpp:259
constexpr std::vector< PointType > vertices() const
Returns the vertices of the polygon (translation applied).
Definition polygon.hpp:587
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 polygon.hpp:169
constexpr bool separates(const OtherPoint &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:1864
constexpr const Rectangle< PointType > & bbox() const
Computes the bounding box of the polyline.
Definition bounding.hpp:515
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2134
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1620
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 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 intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:409
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:625
constexpr Line< PointType > asLine() const
Returns the supporting line without orientation.
Definition ray.hpp:319
constexpr const PointType & source() const
Returns the source point of the ray.
Definition ray.hpp:181
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:502
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 std::array< PointType, 4 > vertices() const
Returns the four vertices in counterclockwise order.
Definition bounding.hpp:188
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 bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:48
constexpr bool containsCollinear(const OtherPoint &point) const
Returns whether the segment contains the given point that is collinear with the segment.
Definition predicates.hpp:161
constexpr const PointType & max() const
Returns the largest stored endpoint.
Definition segment.hpp:199
constexpr const PointType & min() const
Returns the smallest stored endpoint.
Definition segment.hpp:190
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 const PointType & a() const
Returns the first vertex.
Definition triangle.hpp:208
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:134
constexpr Rectangle< PointType > bbox() const
Returns the axis-aligned bounding box of the vertices.
Definition bounding.hpp:224
constexpr std::array< Segment< PointType >, 3 > edges() const
Returns the three unoriented boundary edges.
Definition bounding.hpp:240
constexpr const PointType & c() const
Returns the third vertex.
Definition triangle.hpp:226