Pangolin
Header-only C++20 plane computational geometry library
Loading...
Searching...
No Matches
halfplaneintersection.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "shape/polygon.hpp"
4
16
17#include <algorithm>
18#include <cassert>
19#include <compare>
20#include <concepts>
21#include <cstddef>
22#include <functional>
23#include <optional>
24#include <ostream>
25#include <ranges>
26#include <stdexcept>
27#include <type_traits>
28#include <utility>
29#include <variant>
30#include <vector>
31
32
33namespace pgl::detail {
34
47template <HalfplaneConcept H>
48constexpr int pseudoAngleHalf(const H& h) {
49 const auto& s = h.source();
50 const auto& t = h.target();
51 if (t.y() != s.y()) {
52 return t.y() > s.y() ? 0 : 1;
53 }
54 return t.x() > s.x() ? 0 : 1;
55}
56
65template <HalfplaneConcept HA, HalfplaneConcept HB>
66constexpr std::partial_ordering directionCross(const HA& a, const HB& b) {
67 return crossSign(a.source(), a.target(), b.source(), b.target());
68}
69
76template <HalfplaneConcept HA, HalfplaneConcept HB>
77constexpr bool directionLess(const HA& a, const HB& b) {
78 const int halfA = pseudoAngleHalf(a);
79 const int halfB = pseudoAngleHalf(b);
80 if (halfA != halfB) {
81 return halfA < halfB;
82 }
83 return directionCross(a, b) > 0;
84}
85
89template <HalfplaneConcept HA, HalfplaneConcept HB>
90constexpr std::partial_ordering directionDot(const HA& a, const HB& b) {
91 return dotSign(a.source(), a.target(), b.source(), b.target());
92}
93
99template <HalfplaneConcept HF, HalfplaneConcept HT, HalfplaneConcept HX>
100constexpr bool arcContainsDirection(const HF& from, const HT& to, const HX& x) {
101 const auto crossFrom = directionCross(from, x);
102 if (crossFrom < 0) {
103 return false;
104 }
105 if (crossFrom == 0 && directionDot(from, x) <= 0) {
106 return false; // opposite to the arc start, not on it
107 }
108 const auto crossTo = directionCross(x, to);
109 if (crossTo < 0) {
110 return false;
111 }
112 if (crossTo == 0 && directionDot(to, x) <= 0) {
113 return false; // opposite to the arc end
114 }
115 return true;
116}
117
121template <HalfplaneConcept HA, HalfplaneConcept HB>
122constexpr bool directionEqual(const HA& a, const HB& b) {
123 return pseudoAngleHalf(a) == pseudoAngleHalf(b) && directionCross(a, b) == 0;
124}
125
138template <HalfplaneConcept H1, HalfplaneConcept H2, HalfplaneConcept H3>
139constexpr auto boundaryLinesDeterminant(const H1& h1, const H2& h2, const H3& h3) {
140 using Common = std::common_type_t<typename H1::NumberType, typename H2::NumberType, typename H3::NumberType>;
141 using C = promoted_number_t<promoted_number_t<Common>>;
142 const auto row = [](const auto& h) {
143 const C sx = static_cast<C>(h.source().x());
144 const C sy = static_cast<C>(h.source().y());
145 const C tx = static_cast<C>(h.target().x());
146 const C ty = static_cast<C>(h.target().y());
147 struct Row { C ax, ay, b; };
148 return Row{ty - sy, sx - tx, sx * ty - sy * tx};
149 };
150 const auto r1 = row(h1);
151 const auto r2 = row(h2);
152 const auto r3 = row(h3);
153 return r1.ax * (r2.ay * r3.b - r3.ay * r2.b)
154 - r1.ay * (r2.ax * r3.b - r3.ax * r2.b)
155 + r1.b * (r2.ax * r3.ay - r3.ax * r2.ay);
156}
157
166template <HalfplaneConcept H1, HalfplaneConcept H2, HalfplaneConcept H3>
167constexpr int vertexSide(const H1& h1, const H2& h2, const H3& h3) {
168 const auto det = boundaryLinesDeterminant(h1, h2, h3);
169 const auto zero = decltype(det){};
170 const int detSign = det > zero ? 1 : det < zero ? -1 : 0;
171 return detSign * signOf(directionCross(h1, h2));
172}
173
174} // namespace pgl::detail
175
176
177namespace pgl {
178
179template <class PointType = Point<>, class Label>
181
183
184template <HalfplaneConcept H>
186
187template <std::ranges::input_range Range>
188 requires detail::is_halfplane_v<std::ranges::range_value_t<Range>>
190
191template <std::ranges::input_range Range>
192 requires detail::is_halfplane_v<std::ranges::range_value_t<Range>>
194
195template <RectangleConcept R>
197
198template <TriangleConcept T>
200
201template <ConvexConcept C>
203
204template <PointConcept P>
206
207template <SegmentConcept S>
209
210template <LineConcept L>
212
243template <class PointType_, class TLabel>
245 using PointType = PointType_;
246 using NumberType = PointType::NumberType;
247 using LabelType = TLabel;
249
250 static_assert(detail::is_point_v<PointType>, "HalfplaneIntersection requires pgl::Point defining points");
251
255 constexpr HalfplaneIntersection() = default;
256
260 template <HalfplaneConcept OtherHalfplane>
261 constexpr explicit HalfplaneIntersection(const OtherHalfplane& halfplane) {
262 insert(halfplane);
263 }
264
286 template <std::ranges::input_range Range = std::initializer_list<HalfplaneType>>
287 requires std::convertible_to<std::ranges::range_value_t<Range>, HalfplaneType> &&
288 (!detail::is_halfplane_intersection_v<Range>)
289 constexpr explicit HalfplaneIntersection(Range&& halfplanes, bool trusted = false) {
290 if (trusted) {
291 for (const auto& h : halfplanes) {
292 halfplanes_.push_back(h);
293 }
294 } else {
295 for (const auto& h : halfplanes) {
296 insert(h);
297 }
298 }
299 }
300
309 template <RectangleConcept OtherRectangle>
310 constexpr explicit HalfplaneIntersection(const OtherRectangle& rectangle) {
311 if (rectangle.empty()) {
312 empty_ = true;
313 return;
314 }
315 const PointType lo(rectangle.min());
316 const PointType hi(rectangle.max());
317 if (lo == hi) {
318 // A single point: the four edges would all be degenerate.
319 buildPointSlab(lo);
320 canonicalizeSorted();
321 return;
322 }
323 if (lo.x() == hi.x() || lo.y() == hi.y()) {
324 // A zero-width or zero-height rectangle is the segment lo-hi; two of
325 // the four edges would be degenerate, so clamp to the segment.
326 buildSegmentSlab(lo, hi);
327 canonicalizeSorted();
328 return;
329 }
330 const PointType lohi(lo.x(), hi.y());
331 const PointType hilo(hi.x(), lo.y());
332 // Directions 0, 90, 180, 270 degrees: already in sorted order.
333 halfplanes_.push_back(HalfplaneType(lo, hilo));
334 halfplanes_.push_back(HalfplaneType(hilo, hi));
335 halfplanes_.push_back(HalfplaneType(hi, lohi));
336 halfplanes_.push_back(HalfplaneType(lohi, lo));
337 }
338
345 template <TriangleConcept OtherTriangle>
346 constexpr explicit HalfplaneIntersection(const OtherTriangle& triangle) {
347 if (const auto vertex = triangle.getIfPoint()) {
348 // A single point: all three edges would be degenerate.
349 buildPointSlab(PointType(*vertex));
350 canonicalizeSorted();
351 return;
352 }
353 if (const auto carrier = triangle.getIfSegment()) {
354 // Collinear vertices: the edges span the carrier segment, and at
355 // least one of them would be degenerate.
356 buildSegmentSlab(PointType(carrier->min()), PointType(carrier->max()));
357 canonicalizeSorted();
358 return;
359 }
360 // Triangle vertices are CCW when non-degenerate, so each edge's
361 // half-plane has the interior on its left.
362 for (std::size_t i = 0; i < 3; ++i) {
363 halfplanes_.push_back(HalfplaneType(PointType(triangle[i]), PointType(triangle[(i + 1) % 3])));
364 }
365 canonicalizeSorted();
366 }
367
374 template <ConvexConcept OtherConvex>
375 constexpr explicit HalfplaneIntersection(const OtherConvex& convex) {
376 const std::size_t n = convex.size();
377 if (n == 0) {
378 empty_ = true;
379 return;
380 }
381 if (convex.isDegenerate()) {
382 // A point or a segment: clamp both slab directions. The convex
383 // polygon normalizes collinear input down to its two extremes.
384 const PointType a(convex[0]);
385 const PointType b(convex[n - 1]);
386 if (a == b) {
387 buildPointSlab(a);
388 } else {
389 buildSegmentSlab(a, b);
390 }
391 canonicalizeSorted();
392 return;
393 }
394 for (std::size_t i = 0; i < n; ++i) {
395 halfplanes_.push_back(HalfplaneType(PointType(convex[i]), PointType(convex[(i + 1) % n])));
396 }
397 canonicalizeSorted();
398 }
399
406 template <PointConcept OtherPoint>
407 constexpr explicit HalfplaneIntersection(const OtherPoint& point) {
408 buildPointSlab(PointType(point));
409 canonicalizeSorted();
410 }
411
419 template <SegmentConcept OtherSegment>
420 constexpr explicit HalfplaneIntersection(const OtherSegment& segment) {
421 const PointType a(segment[0]);
422 const PointType b(segment[1]);
423 if (a == b) {
424 buildPointSlab(a);
425 } else {
426 buildSegmentSlab(a, b);
427 }
428 canonicalizeSorted();
429 }
430
438 template <LineConcept OtherLine>
439 constexpr explicit HalfplaneIntersection(const OtherLine& line) {
440 const PointType a(line[0]);
441 const PointType b(line[1]);
442 assert(a != b);
443 halfplanes_.push_back(HalfplaneType(a, b));
444 halfplanes_.push_back(HalfplaneType(b, a));
445 degenerate_ = true;
446 canonicalizeSorted();
447 }
448
452 template <PointConcept OtherPointType, class OtherLabelType>
453 requires(std::constructible_from<PointType, const OtherPointType&>)
455 : empty_(other.empty()), degenerate_(other.empty() ? false : other.isDegenerate()) {
456 halfplanes_.reserve(other.size());
457 for (const auto& h : other) {
458 halfplanes_.push_back(HalfplaneType(h));
459 }
460 label_ = detail::copyLabel<LabelType>(other);
461 }
462
464 template <PointConcept OtherPointType, class OtherLabelType>
465 requires(std::constructible_from<PointType, const OtherPointType&>)
467 halfplanes_.clear();
468 halfplanes_.reserve(other.size());
469 for (const auto& h : other) {
470 halfplanes_.push_back(HalfplaneType(h));
471 }
472 empty_ = other.empty();
473 degenerate_ = empty_ ? false : other.isDegenerate();
474 label_ = detail::copyLabel<LabelType>(other);
475 resetCache();
476 return *this;
477 }
478
485 template <class A = LabelType>
486 requires(detail::has_label_v<A>)
487 constexpr A& label() const {
488 return label_;
489 }
490
508 template <HalfplaneConcept OtherHalfplane>
509 constexpr bool insert(const OtherHalfplane& other) {
510 if (empty_) {
511 return false;
512 }
513 const HalfplaneType h(PointType(other.source()), PointType(other.target()));
514 if (h.isUndefined()) {
515 return false;
516 }
517 if (halfplanes_.empty()) {
518 halfplanes_.push_back(h);
519 resetCache();
520 return true;
521 }
522 // sup a·p <= b over the region means the region is already inside h.
523 const SupStatus supremum = supStatus(h);
524 if (supremum == SupStatus::below || supremum == SupStatus::on) {
525 return false;
526 }
527 // The infimum side: inf a·p > b means no point of the region satisfies
528 // h; inf == b (attained) means the region collapses onto the minimum
529 // face, which has empty interior.
530 const SupStatus infimum = supStatus(h.opposite());
531 if (infimum == SupStatus::below) {
532 halfplanes_.clear();
533 empty_ = true;
534 degenerate_ = false;
535 resetCache();
536 return true;
537 }
538 if (infimum == SupStatus::on) {
539 degenerate_ = true;
540 }
541 std::size_t pos = linearLowerBound(h);
542 if (pos < halfplanes_.size() && detail::directionEqual(halfplanes_[pos], h)) {
543 // Same direction: h is strictly more restrictive, otherwise the
544 // supremum test above would have discarded it.
545 halfplanes_[pos] = h;
546 } else {
547 if (pos > halfplanes_.size()) {
548 pos = halfplanes_.size();
549 }
550 halfplanes_.insert(halfplanes_.begin() + static_cast<std::ptrdiff_t>(pos), h);
551 }
552 // Cascade: a stored half-plane g between angular neighbors pred and
553 // succ is redundant exactly when the wedge pred ∩ succ fits inside g,
554 // which (for an angular gap below pi) reduces to the wedge apex lying
555 // weakly inside g. Deletions are paid for once, so the cascade is
556 // amortized O(1) tests per insertion.
557 while (halfplanes_.size() >= 3) {
558 const std::size_t s1 = nextIndex(pos);
559 const std::size_t s2 = nextIndex(s1);
560 if (s2 == pos) {
561 break;
562 }
563 if (detail::directionCross(halfplanes_[pos], halfplanes_[s2]) > 0 &&
564 detail::vertexSide(halfplanes_[pos], halfplanes_[s2], halfplanes_[s1]) >= 0) {
565 halfplanes_.erase(halfplanes_.begin() + static_cast<std::ptrdiff_t>(s1));
566 if (s1 < pos) {
567 --pos;
568 }
569 } else {
570 break;
571 }
572 }
573 while (halfplanes_.size() >= 3) {
574 const std::size_t p1 = prevIndex(pos);
575 const std::size_t p2 = prevIndex(p1);
576 if (p2 == pos) {
577 break;
578 }
579 if (detail::directionCross(halfplanes_[p2], halfplanes_[pos]) > 0 &&
580 detail::vertexSide(halfplanes_[p2], halfplanes_[pos], halfplanes_[p1]) >= 0) {
581 halfplanes_.erase(halfplanes_.begin() + static_cast<std::ptrdiff_t>(p1));
582 if (p1 < pos) {
583 --pos;
584 }
585 } else {
586 break;
587 }
588 }
589 resetCache();
590 return true;
591 }
592
596 constexpr std::size_t size() const {
597 return halfplanes_.size();
598 }
599
604 constexpr const HalfplaneType& operator[](std::size_t index) const {
605 assert(index < size());
606 return halfplanes_[index];
607 }
608
613 constexpr const HalfplaneType& get(std::ptrdiff_t index) const {
614 const std::ptrdiff_t n = static_cast<std::ptrdiff_t>(size());
615 return (*this)[static_cast<std::size_t>(((index % n) + n) % n)];
616 }
617
624 constexpr std::ptrdiff_t index(const HalfplaneType& halfplane) const {
625 const std::size_t pos = linearLowerBound(halfplane);
626 if (pos < size() && halfplanes_[pos] == halfplane) {
627 return static_cast<std::ptrdiff_t>(pos);
628 }
629 return -1;
630 }
631
633 constexpr std::vector<HalfplaneType> halfplanes() const {
634 return halfplanes_;
635 }
636
638 constexpr auto begin() const { return halfplanes_.cbegin(); }
640 constexpr auto cbegin() const { return halfplanes_.cbegin(); }
642 constexpr auto end() const { return halfplanes_.cend(); }
644 constexpr auto cend() const { return halfplanes_.cend(); }
645
649 constexpr bool empty() const {
650 return empty_;
651 }
652
656 constexpr bool isPlane() const {
657 return !empty_ && halfplanes_.empty();
658 }
659
664 constexpr bool isDegenerate() const {
665 return empty_ || degenerate_;
666 }
667
678 constexpr bool isUndefined() const {
679 return false;
680 }
681
692 [[nodiscard]] constexpr bool isHalfplane() const;
693
701 [[nodiscard]] constexpr std::optional<HalfplaneType> getIfHalfplane() const;
702
712 [[nodiscard]] constexpr bool isLine() const;
713
722 [[nodiscard]] constexpr std::optional<Line<PointType>> getIfLine() const;
723
733 [[nodiscard]] constexpr bool isRay() const;
734
747 template <class ResultNumber = division_result_t<NumberType>>
748 [[nodiscard]] constexpr std::optional<Ray<Point<ResultNumber, typename PointType::LabelType>>>
749 getIfRay() const;
750
761 [[nodiscard]] constexpr bool isPoint() const;
762
775 template <class ResultNumber = division_result_t<NumberType>>
776 [[nodiscard]] constexpr std::optional<Point<ResultNumber, typename PointType::LabelType>>
777 getIfPoint() const;
778
784 [[nodiscard]] constexpr bool isSegment() const;
785
798 template <class ResultNumber = division_result_t<NumberType>>
799 [[nodiscard]] constexpr std::optional<Segment<Point<ResultNumber, typename PointType::LabelType>>>
801
811 constexpr bool isBounded() const {
812 if (empty_) {
813 return true;
814 }
815 const std::size_t n = size();
816 if (n < 3) {
817 return false;
818 }
819 for (std::size_t i = 0; i < n; ++i) {
820 if (!(detail::directionCross(halfplanes_[i], halfplanes_[nextIndex(i)]) > 0)) {
821 return false;
822 }
823 }
824 return true;
825 }
826
833 constexpr std::size_t vertexCount() const {
834 if (empty_) {
835 return 0;
836 }
837 const std::size_t n = size();
838 if (n < 2) {
839 return 0;
840 }
841 std::size_t count = 0;
842 for (std::size_t i = 0; i < n; ++i) {
843 if (detail::directionCross(halfplanes_[i], halfplanes_[nextIndex(i)]) > 0) {
844 ++count;
845 }
846 }
847 return count;
848 }
849
854 constexpr bool vertexExists(std::size_t i) const {
855 if (empty_ || size() < 2) {
856 return false;
857 }
858 return detail::directionCross(halfplanes_[i], halfplanes_[nextIndex(i)]) > 0;
859 }
860
874 template <class ResultNumber = division_result_t<NumberType>>
876 assert(vertexExists(i));
877 const auto isec = halfplanes_[i].asLine().template intersection<ResultNumber>(
878 halfplanes_[nextIndex(i)].asLine());
879 assert(isec && isec->index() == 0);
880 return std::get<0>(*isec);
881 }
882
889 template <class ResultNumber = division_result_t<NumberType>>
890 constexpr std::vector<Point<ResultNumber, typename PointType::LabelType>> vertices() const {
891 std::vector<Point<ResultNumber, typename PointType::LabelType>> result;
892 if (empty_ || size() < 2) {
893 return result;
894 }
895 for (std::size_t i = 0; i < size(); ++i) {
896 if (vertexExists(i)) {
897 result.push_back(vertex<ResultNumber>(i));
898 }
899 }
900 return result;
901 }
902
915 template <class ResultNumber = division_result_t<NumberType>>
916 constexpr std::variant<Segment<Point<ResultNumber, typename PointType::LabelType>>,
919 edge(std::size_t i) const {
921 assert(!empty_ && i < size());
922 const std::size_t prev = prevIndex(i);
923 const bool hasStart = size() >= 2 && detail::directionCross(halfplanes_[prev], halfplanes_[i]) > 0;
924 const bool hasEnd = vertexExists(i);
925 const auto& h = halfplanes_[i];
926 if (hasStart && hasEnd) {
928 }
929 const ResultPoint source(h.source());
930 const ResultPoint target(h.target());
931 const ResultNumber dx = target.x() - source.x();
932 const ResultNumber dy = target.y() - source.y();
933 if (hasStart) {
934 const ResultPoint start = vertex<ResultNumber>(prev);
935 return Ray<ResultPoint>(start, ResultPoint(start.x() + dx, start.y() + dy));
936 }
937 if (hasEnd) {
938 const ResultPoint finish = vertex<ResultNumber>(i);
939 return Ray<ResultPoint>(finish, ResultPoint(finish.x() - dx, finish.y() - dy));
940 }
941 return Line<ResultPoint>(source, target);
942 }
943
954 template <class ResultNumber = division_result_t<NumberType>>
956 if (empty_) {
957 return {};
958 }
959 if (!isBounded()) {
960 throw std::logic_error("HalfplaneIntersection::asConvex requires a bounded region");
961 }
963 }
964
971 template <class ResultNumber = division_result_t<NumberType>>
975
984 [[nodiscard]] constexpr bool operator==(const HalfplaneIntersection& other) const {
985 if (empty_ != other.empty_) {
986 return false;
987 }
988 if (empty_) {
989 return true;
990 }
991 if (halfplanes_.size() != other.halfplanes_.size()) {
992 return false;
993 }
994 for (std::size_t i = 0; i < halfplanes_.size(); ++i) {
995 if (!(halfplanes_[i] == other.halfplanes_[i])) {
996 return false;
997 }
998 }
999 return true;
1000 }
1001
1003 template<AnyShapeConcept OtherShape>
1004 [[nodiscard]] constexpr bool samePointSet(const OtherShape& other) const;
1005
1009 [[nodiscard]] constexpr auto operator<=>(const HalfplaneIntersection& other) const {
1010 if (auto cmp = empty_ <=> other.empty_; cmp != 0) {
1011 return cmp;
1012 }
1013 if (empty_) {
1014 return std::strong_ordering::equal;
1015 }
1016 if (auto cmp = halfplanes_.size() <=> other.halfplanes_.size(); cmp != 0) {
1017 return cmp;
1018 }
1019 for (std::size_t i = 0; i < halfplanes_.size(); ++i) {
1020 if (auto cmp = halfplanes_[i] <=> other.halfplanes_[i]; cmp != 0) {
1021 return cmp;
1022 }
1023 }
1024 return std::strong_ordering::equal;
1025 }
1026
1037 template <class ResultNumber = division_result_t<NumberType>>
1039
1056 template <class ResultNumber = grid_number_t<typename PointType_::NumberType>>
1057 requires(detail::extended_integral<ResultNumber> || std::same_as<ResultNumber, BigInt>)
1060
1066 template <std::floating_point ResultNumber = double>
1068
1090 template <class OtherShape>
1092 [[nodiscard]] constexpr auto minkowskiSum(const OtherShape& other) const;
1093
1117 template <class OtherShape>
1119 [[nodiscard]] constexpr auto minkowskiErosion(const OtherShape& other) const;
1120
1122 template <PointConcept OtherPoint>
1123 constexpr HalfplaneIntersection& operator+=(const OtherPoint& translation);
1124
1126 template <PointConcept OtherPoint>
1127 constexpr HalfplaneIntersection& operator-=(const OtherPoint& translation);
1128
1130 template <class Scalar>
1131 requires(!detail::is_point_v<Scalar> && !TransformationConcept<Scalar>)
1132 constexpr HalfplaneIntersection& operator*=(const Scalar& scalar);
1133
1135 template <class Scalar>
1136 requires(!detail::is_point_v<Scalar> && !TransformationConcept<Scalar>)
1137 constexpr HalfplaneIntersection& operator/=(const Scalar& scalar);
1138
1140 [[nodiscard]] constexpr HalfplaneIntersection rotated90(int k = 1) const;
1141
1143 constexpr void rotate90(int k = 1);
1144
1146 template <class OtherNumber>
1147 [[nodiscard]] constexpr HalfplaneIntersection scaledUpX(const OtherNumber scalar) const;
1148
1150 template <class OtherNumber>
1151 constexpr void scaleUpX(const OtherNumber scalar);
1152
1154 template <class OtherNumber>
1155 [[nodiscard]] constexpr HalfplaneIntersection scaledUpY(const OtherNumber scalar) const;
1156
1158 template <class OtherNumber>
1159 constexpr void scaleUpY(const OtherNumber scalar);
1160
1162 template <class OtherNumber>
1163 [[nodiscard]] constexpr HalfplaneIntersection scaledDownX(const OtherNumber scalar) const;
1164
1166 template <class OtherNumber>
1167 constexpr void scaleDownX(const OtherNumber scalar);
1168
1170 template <class OtherNumber>
1171 [[nodiscard]] constexpr HalfplaneIntersection scaledDownY(const OtherNumber scalar) const;
1172
1174 template <class OtherNumber>
1175 constexpr void scaleDownY(const OtherNumber scalar);
1176
1177 // --- predicates (defined in the implementation layer) ---
1178
1180 template <PointConcept OtherPoint>
1181 [[nodiscard]] constexpr bool contains(const OtherPoint& point) const;
1182
1184 template <SegmentConcept OtherSegment>
1185 [[nodiscard]] constexpr bool contains(const OtherSegment& other) const;
1186
1188 template <OrientedSegmentConcept OtherOrientedSegment>
1189 [[nodiscard]] constexpr bool contains(const OtherOrientedSegment& other) const;
1190
1192 template <LineConcept OtherLine>
1193 [[nodiscard]] constexpr bool contains(const OtherLine& other) const;
1194
1196 template <OrientedLineConcept OtherOrientedLine>
1197 [[nodiscard]] constexpr bool contains(const OtherOrientedLine& other) const;
1198
1200 template <RayConcept OtherRay>
1201 [[nodiscard]] constexpr bool contains(const OtherRay& other) const;
1202
1204 template <HalfplaneConcept OtherHalfplane>
1205 [[nodiscard]] constexpr bool contains(const OtherHalfplane& other) const;
1206
1208 template <RectangleConcept OtherRectangle>
1209 [[nodiscard]] constexpr bool contains(const OtherRectangle& other) const;
1210
1212 template <TriangleConcept OtherTriangle>
1213 [[nodiscard]] constexpr bool contains(const OtherTriangle& other) const;
1214
1216 template <DiskConcept OtherDisk>
1217 [[nodiscard]] constexpr bool contains(const OtherDisk& other) const;
1218
1220 template <ConvexConcept OtherConvex>
1221 [[nodiscard]] constexpr bool contains(const OtherConvex& other) const;
1222
1224 template <MonotoneChainConcept OtherChain>
1225 [[nodiscard]] constexpr bool contains(const OtherChain& other) const;
1226
1228 template <PolylineConcept OtherPolyline>
1229 [[nodiscard]] constexpr bool contains(const OtherPolyline& other) const;
1230
1232 template <PolygonConcept OtherPolygon>
1233 [[nodiscard]] constexpr bool contains(const OtherPolygon& other) const;
1234
1236 template <HalfplaneIntersectionConcept OtherRegion>
1237 [[nodiscard]] constexpr bool contains(const OtherRegion& other) const;
1238
1240 template <PointConcept OtherPoint>
1241 [[nodiscard]] constexpr bool boundaryContains(const OtherPoint& point) const;
1242
1244 template <SegmentConcept OtherSegment>
1245 [[nodiscard]] constexpr bool boundaryContains(const OtherSegment& other) const;
1246
1248 template <OrientedSegmentConcept OtherOrientedSegment>
1249 [[nodiscard]] constexpr bool boundaryContains(const OtherOrientedSegment& other) const;
1250
1252 template <LineConcept OtherLine>
1253 [[nodiscard]] constexpr bool boundaryContains(const OtherLine& other) const;
1254
1256 template <OrientedLineConcept OtherOrientedLine>
1257 [[nodiscard]] constexpr bool boundaryContains(const OtherOrientedLine& other) const;
1258
1260 template <RayConcept OtherRay>
1261 [[nodiscard]] constexpr bool boundaryContains(const OtherRay& other) const;
1262
1264 template <HalfplaneConcept OtherHalfplane>
1265 [[nodiscard]] constexpr bool boundaryContains(const OtherHalfplane& other) const;
1266
1268 template <RectangleConcept OtherRectangle>
1269 [[nodiscard]] constexpr bool boundaryContains(const OtherRectangle& other) const;
1270
1272 template <TriangleConcept OtherTriangle>
1273 [[nodiscard]] constexpr bool boundaryContains(const OtherTriangle& other) const;
1274
1276 template <DiskConcept OtherDisk>
1277 [[nodiscard]] constexpr bool boundaryContains(const OtherDisk& other) const;
1278
1280 template <ConvexConcept OtherConvex>
1281 [[nodiscard]] constexpr bool boundaryContains(const OtherConvex& other) const;
1282
1284 template <MonotoneChainConcept OtherChain>
1285 [[nodiscard]] constexpr bool boundaryContains(const OtherChain& other) const;
1286
1288 template <PolylineConcept OtherPolyline>
1289 [[nodiscard]] constexpr bool boundaryContains(const OtherPolyline& other) const;
1290
1292 template <PolygonConcept OtherPolygon>
1293 [[nodiscard]] constexpr bool boundaryContains(const OtherPolygon& other) const;
1294
1296 template <HalfplaneIntersectionConcept OtherRegion>
1297 [[nodiscard]] constexpr bool boundaryContains(const OtherRegion& other) const;
1298
1300 template <PointConcept OtherPoint>
1301 [[nodiscard]] constexpr bool interiorContains(const OtherPoint& point) const;
1302
1304 template <SegmentConcept OtherSegment>
1305 [[nodiscard]] constexpr bool interiorContains(const OtherSegment& other) const;
1306
1308 template <OrientedSegmentConcept OtherOrientedSegment>
1309 [[nodiscard]] constexpr bool interiorContains(const OtherOrientedSegment& other) const;
1310
1312 template <LineConcept OtherLine>
1313 [[nodiscard]] constexpr bool interiorContains(const OtherLine& other) const;
1314
1316 template <OrientedLineConcept OtherOrientedLine>
1317 [[nodiscard]] constexpr bool interiorContains(const OtherOrientedLine& other) const;
1318
1320 template <RayConcept OtherRay>
1321 [[nodiscard]] constexpr bool interiorContains(const OtherRay& other) const;
1322
1324 template <HalfplaneConcept OtherHalfplane>
1325 [[nodiscard]] constexpr bool interiorContains(const OtherHalfplane& other) const;
1326
1328 template <RectangleConcept OtherRectangle>
1329 [[nodiscard]] constexpr bool interiorContains(const OtherRectangle& other) const;
1330
1332 template <TriangleConcept OtherTriangle>
1333 [[nodiscard]] constexpr bool interiorContains(const OtherTriangle& other) const;
1334
1336 template <DiskConcept OtherDisk>
1337 [[nodiscard]] constexpr bool interiorContains(const OtherDisk& other) const;
1338
1340 template <ConvexConcept OtherConvex>
1341 [[nodiscard]] constexpr bool interiorContains(const OtherConvex& other) const;
1342
1344 template <MonotoneChainConcept OtherChain>
1345 [[nodiscard]] constexpr bool interiorContains(const OtherChain& other) const;
1346
1348 template <PolylineConcept OtherPolyline>
1349 [[nodiscard]] constexpr bool interiorContains(const OtherPolyline& other) const;
1350
1352 template <PolygonConcept OtherPolygon>
1353 [[nodiscard]] constexpr bool interiorContains(const OtherPolygon& other) const;
1354
1356 template <HalfplaneIntersectionConcept OtherRegion>
1357 [[nodiscard]] constexpr bool interiorContains(const OtherRegion& other) const;
1358
1360 template <PointConcept OtherPoint>
1361 [[nodiscard]] constexpr bool intersects(const OtherPoint& other) const;
1362
1364 template <SegmentConcept OtherSegment>
1365 [[nodiscard]] constexpr bool intersects(const OtherSegment& other) const;
1366
1368 template <OrientedSegmentConcept OtherOrientedSegment>
1369 [[nodiscard]] constexpr bool intersects(const OtherOrientedSegment& other) const;
1370
1372 template <LineConcept OtherLine>
1373 [[nodiscard]] constexpr bool intersects(const OtherLine& other) const;
1374
1376 template <OrientedLineConcept OtherOrientedLine>
1377 [[nodiscard]] constexpr bool intersects(const OtherOrientedLine& other) const;
1378
1380 template <RayConcept OtherRay>
1381 [[nodiscard]] constexpr bool intersects(const OtherRay& other) const;
1382
1384 template <HalfplaneConcept OtherHalfplane>
1385 [[nodiscard]] constexpr bool intersects(const OtherHalfplane& other) const;
1386
1388 template <RectangleConcept OtherRectangle>
1389 [[nodiscard]] constexpr bool intersects(const OtherRectangle& other) const;
1390
1392 template <TriangleConcept OtherTriangle>
1393 [[nodiscard]] constexpr bool intersects(const OtherTriangle& other) const;
1394
1396 template <DiskConcept OtherDisk>
1397 [[nodiscard]] constexpr bool intersects(const OtherDisk& other) const;
1398
1400 template <ConvexConcept OtherConvex>
1401 [[nodiscard]] constexpr bool intersects(const OtherConvex& other) const;
1402
1404 template <MonotoneChainConcept OtherChain>
1405 [[nodiscard]] constexpr bool intersects(const OtherChain& other) const;
1406
1408 template <PolylineConcept OtherPolyline>
1409 [[nodiscard]] constexpr bool intersects(const OtherPolyline& other) const;
1410
1412 template <PolygonConcept OtherPolygon>
1413 [[nodiscard]] constexpr bool intersects(const OtherPolygon& other) const;
1414
1416 template <HalfplaneIntersectionConcept OtherRegion>
1417 [[nodiscard]] constexpr bool intersects(const OtherRegion& other) const;
1418
1420 template <PointConcept OtherPoint>
1421 [[nodiscard]] constexpr bool interiorsIntersect(const OtherPoint& other) const;
1422
1424 template <SegmentConcept OtherSegment>
1425 [[nodiscard]] constexpr bool interiorsIntersect(const OtherSegment& other) const;
1426
1428 template <OrientedSegmentConcept OtherOrientedSegment>
1429 [[nodiscard]] constexpr bool interiorsIntersect(const OtherOrientedSegment& other) const;
1430
1432 template <LineConcept OtherLine>
1433 [[nodiscard]] constexpr bool interiorsIntersect(const OtherLine& other) const;
1434
1436 template <OrientedLineConcept OtherOrientedLine>
1437 [[nodiscard]] constexpr bool interiorsIntersect(const OtherOrientedLine& other) const;
1438
1440 template <RayConcept OtherRay>
1441 [[nodiscard]] constexpr bool interiorsIntersect(const OtherRay& other) const;
1442
1444 template <HalfplaneConcept OtherHalfplane>
1445 [[nodiscard]] constexpr bool interiorsIntersect(const OtherHalfplane& other) const;
1446
1448 template <RectangleConcept OtherRectangle>
1449 [[nodiscard]] constexpr bool interiorsIntersect(const OtherRectangle& other) const;
1450
1452 template <TriangleConcept OtherTriangle>
1453 [[nodiscard]] constexpr bool interiorsIntersect(const OtherTriangle& other) const;
1454
1456 template <DiskConcept OtherDisk>
1457 [[nodiscard]] constexpr bool interiorsIntersect(const OtherDisk& other) const;
1458
1460 template <ConvexConcept OtherConvex>
1461 [[nodiscard]] constexpr bool interiorsIntersect(const OtherConvex& other) const;
1462
1464 template <MonotoneChainConcept OtherChain>
1465 [[nodiscard]] constexpr bool interiorsIntersect(const OtherChain& other) const;
1466
1468 template <PolylineConcept OtherPolyline>
1469 [[nodiscard]] constexpr bool interiorsIntersect(const OtherPolyline& other) const;
1470
1472 template <PolygonConcept OtherPolygon>
1473 [[nodiscard]] constexpr bool interiorsIntersect(const OtherPolygon& other) const;
1474
1476 template <HalfplaneIntersectionConcept OtherRegion>
1477 [[nodiscard]] constexpr bool interiorsIntersect(const OtherRegion& other) const;
1478
1480 template <PointConcept OtherPoint>
1481 [[nodiscard]] constexpr bool separates(const OtherPoint& other) const;
1482
1484 template <SegmentConcept OtherSegment>
1485 [[nodiscard]] constexpr bool separates(const OtherSegment& other) const;
1486
1488 template <OrientedSegmentConcept OtherOrientedSegment>
1489 [[nodiscard]] constexpr bool separates(const OtherOrientedSegment& other) const;
1490
1492 template <LineConcept OtherLine>
1493 [[nodiscard]] constexpr bool separates(const OtherLine& other) const;
1494
1496 template <OrientedLineConcept OtherOrientedLine>
1497 [[nodiscard]] constexpr bool separates(const OtherOrientedLine& other) const;
1498
1500 template <RayConcept OtherRay>
1501 [[nodiscard]] constexpr bool separates(const OtherRay& other) const;
1502
1504 template <HalfplaneConcept OtherHalfplane>
1505 [[nodiscard]] constexpr bool separates(const OtherHalfplane& other) const;
1506
1508 template <RectangleConcept OtherRectangle>
1509 [[nodiscard]] constexpr bool separates(const OtherRectangle& other) const;
1510
1512 template <TriangleConcept OtherTriangle>
1513 [[nodiscard]] constexpr bool separates(const OtherTriangle& other) const;
1514
1516 template <DiskConcept OtherDisk>
1517 [[nodiscard]] constexpr bool separates(const OtherDisk& other) const;
1518
1520 template <ConvexConcept OtherConvex>
1521 [[nodiscard]] constexpr bool separates(const OtherConvex& other) const;
1522
1524 template <MonotoneChainConcept OtherChain>
1525 [[nodiscard]] constexpr bool separates(const OtherChain& other) const;
1526
1528 template <PolylineConcept OtherPolyline>
1529 [[nodiscard]] constexpr bool separates(const OtherPolyline& other) const;
1530
1532 template <PolygonConcept OtherPolygon>
1533 [[nodiscard]] constexpr bool separates(const OtherPolygon& other) const;
1534
1536 template <HalfplaneIntersectionConcept OtherRegion>
1537 [[nodiscard]] constexpr bool separates(const OtherRegion& other) const;
1538
1546 template <PolygonWithHolesConcept OtherHoledRegion>
1547 [[nodiscard]] constexpr bool contains(const OtherHoledRegion& other) const;
1548
1555 template <PolygonWithHolesConcept OtherHoledRegion>
1556 [[nodiscard]] constexpr bool boundaryContains(const OtherHoledRegion& other) const;
1557
1559 template <PolygonWithHolesConcept OtherHoledRegion>
1560 [[nodiscard]] constexpr bool interiorContains(const OtherHoledRegion& other) const;
1561
1569 template <PolygonWithHolesConcept OtherHoledRegion>
1570 [[nodiscard]] bool separates(const OtherHoledRegion& other) const;
1571
1572 // -------------------------------------------------------------------------
1573 // A set of regions
1574 //
1575 // It outranks every other shape, so the symmetric relations reach it through
1576 // the rank-based forwarders and only the asymmetric ones are answered here.
1577 // A set is the union of its components, so it is contained exactly when
1578 // every component is — no matter what this shape is.
1579
1581 template<PolygonSetConcept OtherSet>
1582 [[nodiscard]] constexpr bool contains(const OtherSet& other) const {
1583 for (const auto& component : other) {
1584 if (!contains(component)) {
1585 return false;
1586 }
1587 }
1588 return true;
1589 }
1590
1592 template<PolygonSetConcept OtherSet>
1593 [[nodiscard]] constexpr bool boundaryContains(const OtherSet& other) const {
1594 for (const auto& component : other) {
1595 if (!boundaryContains(component)) {
1596 return false;
1597 }
1598 }
1599 return true;
1600 }
1601
1603 template<PolygonSetConcept OtherSet>
1604 [[nodiscard]] constexpr bool interiorContains(const OtherSet& other) const {
1605 for (const auto& component : other) {
1606 if (!interiorContains(component)) {
1607 return false;
1608 }
1609 }
1610 return true;
1611 }
1612
1621 template<PolygonSetConcept OtherSet>
1622 [[nodiscard]] bool separates(const OtherSet& other) const;
1623
1625 template <PointConcept OtherPoint>
1626 [[nodiscard]] constexpr bool crosses(const OtherPoint& other) const;
1627
1629 template <SegmentConcept OtherSegment>
1630 [[nodiscard]] constexpr bool crosses(const OtherSegment& other) const;
1631
1633 template <OrientedSegmentConcept OtherOrientedSegment>
1634 [[nodiscard]] constexpr bool crosses(const OtherOrientedSegment& other) const;
1635
1637 template <LineConcept OtherLine>
1638 [[nodiscard]] constexpr bool crosses(const OtherLine& other) const;
1639
1641 template <OrientedLineConcept OtherOrientedLine>
1642 [[nodiscard]] constexpr bool crosses(const OtherOrientedLine& other) const;
1643
1645 template <RayConcept OtherRay>
1646 [[nodiscard]] constexpr bool crosses(const OtherRay& other) const;
1647
1649 template <HalfplaneConcept OtherHalfplane>
1650 [[nodiscard]] constexpr bool crosses(const OtherHalfplane& other) const;
1651
1653 template <RectangleConcept OtherRectangle>
1654 [[nodiscard]] constexpr bool crosses(const OtherRectangle& other) const;
1655
1657 template <TriangleConcept OtherTriangle>
1658 [[nodiscard]] constexpr bool crosses(const OtherTriangle& other) const;
1659
1661 template <DiskConcept OtherDisk>
1662 [[nodiscard]] constexpr bool crosses(const OtherDisk& other) const;
1663
1665 template <ConvexConcept OtherConvex>
1666 [[nodiscard]] constexpr bool crosses(const OtherConvex& other) const;
1667
1669 template <MonotoneChainConcept OtherChain>
1670 [[nodiscard]] constexpr bool crosses(const OtherChain& other) const;
1671
1673 template <PolylineConcept OtherPolyline>
1674 [[nodiscard]] constexpr bool crosses(const OtherPolyline& other) const;
1675
1677 template <PolygonConcept OtherPolygon>
1678 [[nodiscard]] constexpr bool crosses(const OtherPolygon& other) const;
1679
1681 template <HalfplaneIntersectionConcept OtherRegion>
1682 [[nodiscard]] constexpr bool crosses(const OtherRegion& other) const;
1683
1690 template <typename OtherShape>
1691 requires (!PointConcept<OtherShape> &&
1692 detail::shapeRank<OtherShape> > detail::shapeRank<HalfplaneIntersection>)
1693 [[nodiscard]] constexpr bool intersects(const OtherShape& other) const {
1694 return other.intersects(*this);
1695 }
1696
1703 template <typename OtherShape>
1704 requires (!PointConcept<OtherShape> &&
1705 detail::shapeRank<OtherShape> > detail::shapeRank<HalfplaneIntersection>)
1706 [[nodiscard]] constexpr bool interiorsIntersect(const OtherShape& other) const {
1707 return other.interiorsIntersect(*this);
1708 }
1709
1716 template <typename OtherShape>
1717 requires (!PointConcept<OtherShape> &&
1718 detail::shapeRank<OtherShape> > detail::shapeRank<HalfplaneIntersection> &&
1719 requires(const OtherShape& o, const HalfplaneIntersection& self) { o.crosses(self); })
1720 [[nodiscard]] constexpr bool crosses(const OtherShape& other) const {
1721 return other.crosses(*this);
1722 }
1723
1724 // The empty set is a subset of every shape and disjoint from all of them.
1726 template <class EmptyPoint>
1727 [[nodiscard]] constexpr bool contains(const EmptyShape<EmptyPoint>&) const {
1728 return true;
1729 }
1730
1731 template <class EmptyPoint>
1732 [[nodiscard]] constexpr bool boundaryContains(const EmptyShape<EmptyPoint>&) const {
1733 return true;
1734 }
1735
1736 template <class EmptyPoint>
1737 [[nodiscard]] constexpr bool interiorContains(const EmptyShape<EmptyPoint>&) const {
1738 return true;
1739 }
1740
1741 template <class EmptyPoint>
1742 [[nodiscard]] constexpr bool intersects(const EmptyShape<EmptyPoint>&) const {
1743 return false;
1744 }
1745
1746 template <class EmptyPoint>
1747 [[nodiscard]] constexpr bool interiorsIntersect(const EmptyShape<EmptyPoint>&) const {
1748 return false;
1749 }
1750
1751 template <class EmptyPoint>
1752 [[nodiscard]] constexpr bool separates(const EmptyShape<EmptyPoint>&) const {
1753 return false;
1754 }
1755
1756 template <class EmptyPoint>
1757 [[nodiscard]] constexpr bool crosses(const EmptyShape<EmptyPoint>&) const {
1758 return false;
1759 }
1760
1761 template <class ResultNumber = NumberType, class EmptyPoint>
1762 [[nodiscard]] constexpr EmptyShape<EmptyPoint> intersection(const EmptyShape<EmptyPoint>&) const {
1763 return {};
1764 }
1765
1766 // Runtime Shape argument: visit the wrapped alternative and re-dispatch to
1767 // the matching per-shape overload (defined in the implementation layer).
1768
1770 template <PointConcept OtherPoint>
1771 [[nodiscard]] constexpr bool contains(const Shape<OtherPoint>& other) const;
1772
1774 template <PointConcept OtherPoint>
1775 [[nodiscard]] constexpr bool boundaryContains(const Shape<OtherPoint>& other) const;
1776
1778 template <PointConcept OtherPoint>
1779 [[nodiscard]] constexpr bool interiorContains(const Shape<OtherPoint>& other) const;
1780
1782 template <PointConcept OtherPoint>
1783 [[nodiscard]] constexpr bool intersects(const Shape<OtherPoint>& other) const;
1784
1786 template <PointConcept OtherPoint>
1787 [[nodiscard]] constexpr bool interiorsIntersect(const Shape<OtherPoint>& other) const;
1788
1790 template <PointConcept OtherPoint>
1791 [[nodiscard]] constexpr bool separates(const Shape<OtherPoint>& other) const;
1792
1794 template <PointConcept OtherPoint>
1795 [[nodiscard]] constexpr bool crosses(const Shape<OtherPoint>& other) const;
1796
1798 template <class ResultNumber = NumberType, PointConcept OtherPoint>
1799 [[nodiscard]] constexpr std::optional<Point<ResultNumber, typename PointType::LabelType>>
1800 intersection(const OtherPoint& other) const;
1801
1803 template <class ResultNumber = division_result_t<NumberType>, LineConcept OtherLine>
1804 [[nodiscard]] constexpr std::optional<std::variant<Point<ResultNumber, typename PointType::LabelType>,
1808 intersection(const OtherLine& other) const;
1809
1811 template <class ResultNumber = division_result_t<NumberType>, OrientedLineConcept OtherOrientedLine>
1812 [[nodiscard]] constexpr std::optional<std::variant<Point<ResultNumber, typename PointType::LabelType>,
1816 intersection(const OtherOrientedLine& other) const;
1817
1819 template <class ResultNumber = division_result_t<NumberType>, SegmentConcept OtherSegment>
1820 [[nodiscard]] constexpr std::optional<std::variant<Point<ResultNumber, typename PointType::LabelType>,
1822 intersection(const OtherSegment& other) const;
1823
1825 template <class ResultNumber = division_result_t<NumberType>, OrientedSegmentConcept OtherOrientedSegment>
1826 [[nodiscard]] constexpr std::optional<std::variant<Point<ResultNumber, typename PointType::LabelType>,
1828 intersection(const OtherOrientedSegment& other) const;
1829
1831 template <class ResultNumber = division_result_t<NumberType>, RayConcept OtherRay>
1832 [[nodiscard]] constexpr std::optional<std::variant<Point<ResultNumber, typename PointType::LabelType>,
1835 intersection(const OtherRay& other) const;
1836
1846 template <class ResultNumber = NumberType, HalfplaneConcept OtherHalfplane>
1848 intersection(const OtherHalfplane& other) const;
1849
1859 template <class ResultNumber = NumberType, RectangleConcept OtherRectangle>
1861 intersection(const OtherRectangle& other) const;
1862
1868 template <class ResultNumber = NumberType, TriangleConcept OtherTriangle>
1870 intersection(const OtherTriangle& other) const;
1871
1877 template <class ResultNumber = NumberType, ConvexConcept OtherConvex>
1879 intersection(const OtherConvex& other) const;
1880
1885 template <class ResultNumber = NumberType, HalfplaneIntersectionConcept OtherRegion>
1887 intersection(const OtherRegion& other) const;
1888
1921 template <class ResultNumber = division_result_t<NumberType>, PolygonConcept OtherPolygon>
1922 [[nodiscard]] std::vector<std::variant<Point<ResultNumber, typename PointType::LabelType>,
1925 intersection(const OtherPolygon& other) const;
1926
1936 template <class ResultNumber = division_result_t<NumberType>, typename OtherShape>
1937 requires (!PointConcept<OtherShape> &&
1938 (detail::shapeRank<OtherShape> > detail::shapeRank<HalfplaneIntersection>) &&
1939 requires(const OtherShape& o, const HalfplaneIntersection& self) {
1940 o.template intersection<ResultNumber>(self);
1941 })
1942 [[nodiscard]] auto intersection(const OtherShape& other) const {
1943 return other.template intersection<ResultNumber>(*this);
1944 }
1945
1947 template <class ResultNumber = division_result_t<NumberType>, typename OtherShape>
1948 requires (!PointConcept<OtherShape>
1949 && (detail::shapeRank<OtherShape> > detail::shapeRank<HalfplaneIntersection>)
1950 && requires(const OtherShape& o, const HalfplaneIntersection& self) {
1952 })
1953 [[nodiscard]] auto regularizedIntersection(const OtherShape& other) const {
1954 return other.template regularizedIntersection<ResultNumber>(*this);
1955 }
1956
1957 // --- distances (defined in the implementation layer) ---
1958 //
1959 // Zero when the shapes intersect; otherwise the minimum over the region's
1960 // boundary edges of the edge-to-shape distance. Complexity: O(n) edge
1961 // queries for n stored half-planes. The empty region has no distance to
1962 // anything; querying it is undefined behavior.
1963
1965 template <class ResultNumber = division_result_t<NumberType>, PointConcept OtherPoint>
1966 [[nodiscard]] constexpr auto squaredDistance(const OtherPoint& other) const;
1967
1969 template <class ResultNumber = division_result_t<NumberType>, SegmentConcept OtherSegment>
1970 [[nodiscard]] constexpr auto squaredDistance(const OtherSegment& other) const;
1971
1973 template <class ResultNumber = division_result_t<NumberType>, OrientedSegmentConcept OtherOrientedSegment>
1974 [[nodiscard]] constexpr auto squaredDistance(const OtherOrientedSegment& other) const;
1975
1977 template <class ResultNumber = division_result_t<NumberType>, LineConcept OtherLine>
1978 [[nodiscard]] constexpr auto squaredDistance(const OtherLine& other) const;
1979
1981 template <class ResultNumber = division_result_t<NumberType>, OrientedLineConcept OtherOrientedLine>
1982 [[nodiscard]] constexpr auto squaredDistance(const OtherOrientedLine& other) const;
1983
1985 template <class ResultNumber = division_result_t<NumberType>, RayConcept OtherRay>
1986 [[nodiscard]] constexpr auto squaredDistance(const OtherRay& other) const;
1987
1989 template <class ResultNumber = division_result_t<NumberType>, HalfplaneConcept OtherHalfplane>
1990 [[nodiscard]] constexpr auto squaredDistance(const OtherHalfplane& other) const;
1991
1993 template <class ResultNumber = division_result_t<NumberType>, RectangleConcept OtherRectangle>
1994 [[nodiscard]] constexpr auto squaredDistance(const OtherRectangle& other) const;
1995
1997 template <class ResultNumber = division_result_t<NumberType>, TriangleConcept OtherTriangle>
1998 [[nodiscard]] constexpr auto squaredDistance(const OtherTriangle& other) const;
1999
2001 template <class ResultNumber = division_result_t<NumberType>, ConvexConcept OtherConvex>
2002 [[nodiscard]] constexpr auto squaredDistance(const OtherConvex& other) const;
2003
2005 template <class ResultNumber = division_result_t<NumberType>, MonotoneChainConcept OtherChain>
2006 [[nodiscard]] constexpr auto squaredDistance(const OtherChain& other) const;
2007
2009 template <class ResultNumber = division_result_t<NumberType>, PolylineConcept OtherPolyline>
2010 [[nodiscard]] constexpr auto squaredDistance(const OtherPolyline& other) const;
2011
2013 template <class ResultNumber = division_result_t<NumberType>, PolygonConcept OtherPolygon>
2014 [[nodiscard]] constexpr auto squaredDistance(const OtherPolygon& other) const;
2015
2023 template <class ResultNumber = double, DiskConcept OtherDisk>
2024 [[nodiscard]] detail::floating_result_t<ResultNumber> squaredDistance(const OtherDisk& other) const;
2025
2027 template <class ResultNumber = division_result_t<NumberType>, HalfplaneIntersectionConcept OtherRegion>
2028 [[nodiscard]] constexpr auto squaredDistance(const OtherRegion& other) const;
2029
2045 template <class ResultNumber = division_result_t<NumberType>, class OtherShape>
2046 requires detail::ClosestPointsPairConcept<HalfplaneIntersection<PointType_, TLabel>, OtherShape>
2047 [[nodiscard]] constexpr auto closestPoints(const OtherShape& other) const;
2048
2050 template <class ResultNumber = division_result_t<NumberType>, PointConcept OtherPoint>
2051 [[nodiscard]] constexpr auto distanceL1(const OtherPoint& other) const;
2052
2054 template <class ResultNumber = division_result_t<NumberType>, SegmentConcept OtherSegment>
2055 [[nodiscard]] constexpr auto distanceL1(const OtherSegment& other) const;
2056
2058 template <class ResultNumber = division_result_t<NumberType>, OrientedSegmentConcept OtherOrientedSegment>
2059 [[nodiscard]] constexpr auto distanceL1(const OtherOrientedSegment& other) const;
2060
2062 template <class ResultNumber = division_result_t<NumberType>, LineConcept OtherLine>
2063 [[nodiscard]] constexpr auto distanceL1(const OtherLine& other) const;
2064
2066 template <class ResultNumber = division_result_t<NumberType>, OrientedLineConcept OtherOrientedLine>
2067 [[nodiscard]] constexpr auto distanceL1(const OtherOrientedLine& other) const;
2068
2070 template <class ResultNumber = division_result_t<NumberType>, RayConcept OtherRay>
2071 [[nodiscard]] constexpr auto distanceL1(const OtherRay& other) const;
2072
2074 template <class ResultNumber = division_result_t<NumberType>, HalfplaneConcept OtherHalfplane>
2075 [[nodiscard]] constexpr auto distanceL1(const OtherHalfplane& other) const;
2076
2078 template <class ResultNumber = division_result_t<NumberType>, RectangleConcept OtherRectangle>
2079 [[nodiscard]] constexpr auto distanceL1(const OtherRectangle& other) const;
2080
2082 template <class ResultNumber = division_result_t<NumberType>, TriangleConcept OtherTriangle>
2083 [[nodiscard]] constexpr auto distanceL1(const OtherTriangle& other) const;
2084
2086 template <class ResultNumber = division_result_t<NumberType>, ConvexConcept OtherConvex>
2087 [[nodiscard]] constexpr auto distanceL1(const OtherConvex& other) const;
2088
2090 template <class ResultNumber = division_result_t<NumberType>, MonotoneChainConcept OtherChain>
2091 [[nodiscard]] constexpr auto distanceL1(const OtherChain& other) const;
2092
2094 template <class ResultNumber = division_result_t<NumberType>, PolylineConcept OtherPolyline>
2095 [[nodiscard]] constexpr auto distanceL1(const OtherPolyline& other) const;
2096
2098 template <class ResultNumber = division_result_t<NumberType>, PolygonConcept OtherPolygon>
2099 [[nodiscard]] constexpr auto distanceL1(const OtherPolygon& other) const;
2100
2102 template <class ResultNumber = division_result_t<NumberType>, HalfplaneIntersectionConcept OtherRegion>
2103 [[nodiscard]] constexpr auto distanceL1(const OtherRegion& other) const;
2104
2120 template <class ResultNumber = division_result_t<NumberType>, PointConcept OtherPoint>
2121 [[nodiscard]] constexpr auto intersection(const Shape<OtherPoint>& other) const {
2122 return other.template intersection<ResultNumber>(*this);
2123 }
2124
2126 template <class ResultNumber = division_result_t<NumberType>, PointConcept OtherPoint>
2127 [[nodiscard]] auto regularizedIntersection(const Shape<OtherPoint>& other) const {
2128 return other.template regularizedIntersection<ResultNumber>(*this);
2129 }
2130
2135 template <class ResultNumber = double, PointConcept OtherPoint>
2136 [[nodiscard]] constexpr auto distanceL1(const Shape<OtherPoint>& other) const {
2137 return other.template distanceL1<ResultNumber>(*this);
2138 }
2139
2141 template <class ResultNumber = division_result_t<NumberType>, PointConcept OtherPoint>
2142 [[nodiscard]] constexpr auto distanceLInf(const OtherPoint& other) const;
2143
2145 template <class ResultNumber = division_result_t<NumberType>, SegmentConcept OtherSegment>
2146 [[nodiscard]] constexpr auto distanceLInf(const OtherSegment& other) const;
2147
2149 template <class ResultNumber = division_result_t<NumberType>, OrientedSegmentConcept OtherOrientedSegment>
2150 [[nodiscard]] constexpr auto distanceLInf(const OtherOrientedSegment& other) const;
2151
2153 template <class ResultNumber = division_result_t<NumberType>, LineConcept OtherLine>
2154 [[nodiscard]] constexpr auto distanceLInf(const OtherLine& other) const;
2155
2157 template <class ResultNumber = division_result_t<NumberType>, OrientedLineConcept OtherOrientedLine>
2158 [[nodiscard]] constexpr auto distanceLInf(const OtherOrientedLine& other) const;
2159
2161 template <class ResultNumber = division_result_t<NumberType>, RayConcept OtherRay>
2162 [[nodiscard]] constexpr auto distanceLInf(const OtherRay& other) const;
2163
2165 template <class ResultNumber = division_result_t<NumberType>, HalfplaneConcept OtherHalfplane>
2166 [[nodiscard]] constexpr auto distanceLInf(const OtherHalfplane& other) const;
2167
2169 template <class ResultNumber = division_result_t<NumberType>, RectangleConcept OtherRectangle>
2170 [[nodiscard]] constexpr auto distanceLInf(const OtherRectangle& other) const;
2171
2173 template <class ResultNumber = division_result_t<NumberType>, TriangleConcept OtherTriangle>
2174 [[nodiscard]] constexpr auto distanceLInf(const OtherTriangle& other) const;
2175
2177 template <class ResultNumber = division_result_t<NumberType>, ConvexConcept OtherConvex>
2178 [[nodiscard]] constexpr auto distanceLInf(const OtherConvex& other) const;
2179
2181 template <class ResultNumber = division_result_t<NumberType>, MonotoneChainConcept OtherChain>
2182 [[nodiscard]] constexpr auto distanceLInf(const OtherChain& other) const;
2183
2185 template <class ResultNumber = division_result_t<NumberType>, PolylineConcept OtherPolyline>
2186 [[nodiscard]] constexpr auto distanceLInf(const OtherPolyline& other) const;
2187
2189 template <class ResultNumber = division_result_t<NumberType>, PolygonConcept OtherPolygon>
2190 [[nodiscard]] constexpr auto distanceLInf(const OtherPolygon& other) const;
2191
2193 template <class ResultNumber = division_result_t<NumberType>, HalfplaneIntersectionConcept OtherRegion>
2194 [[nodiscard]] constexpr auto distanceLInf(const OtherRegion& other) const;
2195
2200 template <class ResultNumber = double, PointConcept OtherPoint>
2201 [[nodiscard]] constexpr auto distanceLInf(const Shape<OtherPoint>& other) const {
2202 return other.template distanceLInf<ResultNumber>(*this);
2203 }
2204
2205 // Distances to a higher-ranked shape, forwarded so that each unordered pair
2206 // needs its implementation only once, on that shape.
2207
2209 template <class ResultNumber = division_result_t<NumberType>, typename OtherShape>
2210 requires ((detail::shapeRank<OtherShape> > detail::shapeRank<HalfplaneIntersection>) &&
2211 requires(const OtherShape& o, const HalfplaneIntersection& self) {
2212 o.template squaredDistance<ResultNumber>(self);
2213 })
2214 [[nodiscard]] constexpr auto squaredDistance(const OtherShape& other) const {
2215 return other.template squaredDistance<ResultNumber>(*this);
2216 }
2217
2219 template <class ResultNumber = division_result_t<NumberType>, typename OtherShape>
2220 requires ((detail::shapeRank<OtherShape> > detail::shapeRank<HalfplaneIntersection>) &&
2221 requires(const OtherShape& o, const HalfplaneIntersection& self) {
2222 o.template distanceL1<ResultNumber>(self);
2223 })
2224 [[nodiscard]] constexpr auto distanceL1(const OtherShape& other) const {
2225 return other.template distanceL1<ResultNumber>(*this);
2226 }
2227
2229 template <class ResultNumber = division_result_t<NumberType>, typename OtherShape>
2230 requires ((detail::shapeRank<OtherShape> > detail::shapeRank<HalfplaneIntersection>) &&
2231 requires(const OtherShape& o, const HalfplaneIntersection& self) {
2232 o.template distanceLInf<ResultNumber>(self);
2233 })
2234 [[nodiscard]] constexpr auto distanceLInf(const OtherShape& other) const {
2235 return other.template distanceLInf<ResultNumber>(*this);
2236 }
2237
2238 // --- measures (defined in the implementation layer) ---
2239
2250 template <class ResultNumber = division_result_t<NumberType>>
2251 [[nodiscard]] constexpr auto twiceArea() const;
2252
2257 template <class ResultNumber = division_result_t<NumberType>>
2258 [[nodiscard]] constexpr auto area() const;
2259
2270 template <class ResultNumber = division_result_t<NumberType>>
2271 [[nodiscard]] constexpr Point<ResultNumber> centroid() const;
2272
2283 template <class ResultNumber = division_result_t<NumberType>>
2284 [[nodiscard]] constexpr Point<ResultNumber> pointInside() const;
2285
2292 template <class OtherShape>
2293 [[nodiscard]] constexpr bool pointInsideInteriorContainedIn(const OtherShape& shape) const;
2294
2295 private:
2296 std::vector<HalfplaneType> halfplanes_{};
2297 bool empty_ = false;
2298 bool degenerate_ = false;
2299 [[no_unique_address]] mutable LabelType label_{};
2300
2301 // Memoized hash, mirroring Convex: hashUnset_ means "not yet computed" and
2302 // the one true hash colliding with it is remapped to hashUnset_ - 1.
2303 static constexpr std::size_t hashUnset_ = pgl::detail::numeric_limits<std::size_t>::max();
2304 mutable std::size_t hash_ = hashUnset_;
2305 friend struct std::hash<HalfplaneIntersection>;
2306
2307 template <class OtherPointType, class OtherLabelType>
2309
2310 constexpr void resetCache() const {
2311 hash_ = hashUnset_;
2312 }
2313
2314 constexpr std::size_t nextIndex(std::size_t i) const {
2315 return i + 1 < halfplanes_.size() ? i + 1 : 0;
2316 }
2317
2318 constexpr std::size_t prevIndex(std::size_t i) const {
2319 return i == 0 ? halfplanes_.size() - 1 : i - 1;
2320 }
2321
2322 // Appends the four half-planes of the axis-aligned slab pinning the single
2323 // point p and marks the region degenerate. Assumes the region is empty.
2324 constexpr void buildPointSlab(const PointType& p) {
2325 const PointType px(p.x() + NumberType(1), p.y());
2326 const PointType py(p.x(), p.y() + NumberType(1));
2327 halfplanes_.push_back(HalfplaneType(p, px));
2328 halfplanes_.push_back(HalfplaneType(px, p));
2329 halfplanes_.push_back(HalfplaneType(p, py));
2330 halfplanes_.push_back(HalfplaneType(py, p));
2331 degenerate_ = true;
2332 }
2333
2334 // Appends the four half-planes clamping to the segment a-b (a != b): the
2335 // supporting-line slab plus a perpendicular clamp through each endpoint
2336 // (rotating the direction by 90 degrees keeps integer coordinates). Marks
2337 // the region degenerate. Assumes the region is empty.
2338 constexpr void buildSegmentSlab(const PointType& a, const PointType& b) {
2339 const NumberType dx = b.x() - a.x();
2340 const NumberType dy = b.y() - a.y();
2341 const PointType aPerp(a.x() - dy, a.y() + dx);
2342 const PointType bPerp(b.x() - dy, b.y() + dx);
2343 halfplanes_.push_back(HalfplaneType(a, b));
2344 halfplanes_.push_back(HalfplaneType(b, a));
2345 halfplanes_.push_back(HalfplaneType(aPerp, a));
2346 halfplanes_.push_back(HalfplaneType(b, bPerp));
2347 degenerate_ = true;
2348 }
2349
2350 // Restores the sorted-by-pseudo-angle invariant after bulk construction or
2351 // a transformation. The input is assumed pairwise direction-distinct.
2352 constexpr void canonicalizeSorted() {
2353 std::sort(halfplanes_.begin(), halfplanes_.end(),
2354 [](const HalfplaneType& a, const HalfplaneType& b) { return detail::directionLess(a, b); });
2355 resetCache();
2356 }
2357
2358 // First stored index whose boundary direction is >= the query's in the
2359 // linear pseudo-angle order; may equal size().
2360 template <HalfplaneConcept Query>
2361 constexpr std::size_t linearLowerBound(const Query& query) const {
2362 const auto it = std::lower_bound(
2363 halfplanes_.begin(), halfplanes_.end(), query,
2364 [](const HalfplaneType& element, const Query& value) { return detail::directionLess(element, value); });
2365 return static_cast<std::size_t>(it - halfplanes_.begin());
2366 }
2367
2368 // First stored index whose boundary direction is > the query's in the
2369 // linear pseudo-angle order; may equal size().
2370 template <HalfplaneConcept Query>
2371 constexpr std::size_t linearUpperBound(const Query& query) const {
2372 const auto it = std::upper_bound(
2373 halfplanes_.begin(), halfplanes_.end(), query,
2374 [](const Query& value, const HalfplaneType& element) { return detail::directionLess(value, element); });
2375 return static_cast<std::size_t>(it - halfplanes_.begin());
2376 }
2377
2378 // Index of the stored half-plane with the query's boundary direction, or
2379 // -1 when there is none.
2380 template <HalfplaneConcept Query>
2381 constexpr std::ptrdiff_t sameDirectionIndex(const Query& query) const {
2382 const std::size_t pos = linearLowerBound(query);
2383 if (pos < halfplanes_.size() && detail::directionEqual(halfplanes_[pos], query)) {
2384 return static_cast<std::ptrdiff_t>(pos);
2385 }
2386 return -1;
2387 }
2388
2389 // The stored half-planes whose boundary direction lies strictly inside the
2390 // open half-circle counterclockwise from the query's direction — exactly
2391 // those whose outward normal has positive dot product with it, i.e. the
2392 // constraints imposing an upper bound on the parameter along the query
2393 // line. Returns {first cyclic index, count}; the range is contiguous in
2394 // cyclic order. Precondition: size() >= 1.
2395 template <HalfplaneConcept Query>
2396 constexpr std::pair<std::size_t, std::size_t> leftArc(const Query& query) const {
2397 const std::size_t n = halfplanes_.size();
2398 std::size_t lo = linearUpperBound(query);
2399 if (lo == n) {
2400 lo = 0;
2401 }
2402 std::size_t hi = linearLowerBound(query.opposite());
2403 if (hi == n) {
2404 hi = 0;
2405 }
2406 std::size_t count = (hi + n - lo) % n;
2407 if (count == 0 && detail::directionCross(query, halfplanes_[lo]) > 0) {
2408 count = n; // every stored direction lies inside the half-circle
2409 }
2410 return {lo, count};
2411 }
2412
2413 // Among the leftArc constraints, the one whose boundary the directed query
2414 // line crosses first (the binding upper bound). Returns -1 when the arc is
2415 // empty (the line never leaves the region going forward).
2416 // Precondition: size() >= 1 and the query is not degenerate.
2417 template <HalfplaneConcept Query>
2418 constexpr std::ptrdiff_t exitConstraint(const Query& query) const {
2419 const auto [lo, count] = leftArc(query);
2420 if (count == 0) {
2421 return -1;
2422 }
2423 const std::size_t n = halfplanes_.size();
2424 // The crossing parameters along the arc first decrease, then increase
2425 // (the arc's boundary lines wrap a convex chain), so a valley binary
2426 // search finds the minimum. The consecutive-pair comparison is the
2427 // vertex side test: the shared vertex strictly outside the query
2428 // half-plane means the parameters are still decreasing.
2429 std::size_t first = 0;
2430 std::size_t last = count - 1;
2431 while (first < last) {
2432 const std::size_t mid = first + (last - first) / 2;
2433 const std::size_t i = (lo + mid) % n;
2434 const std::size_t j = (lo + mid + 1) % n;
2435 if (detail::vertexSide(halfplanes_[i], halfplanes_[j], query) < 0) {
2436 first = mid + 1;
2437 } else {
2438 last = mid;
2439 }
2440 }
2441 return static_cast<std::ptrdiff_t>((lo + first) % n);
2442 }
2443
2444 // Side of a point relative to stored constraint i: positive means strictly
2445 // inside, zero on the boundary, negative strictly outside.
2446 template <PointConcept OtherPoint>
2447 constexpr std::partial_ordering constraintSide(std::size_t i, const OtherPoint& point) const {
2448 return orientationSign(halfplanes_[i].source(), halfplanes_[i].target(), point);
2449 }
2450
2451 enum class SupStatus { unbounded, above, on, below };
2452
2453 // Status of sup_{p in region} a·p compared to b, where the query
2454 // half-plane is {p : a·p <= b}: `below`/`on`/`above` when the supremum is
2455 // attained and compares so with b, `unbounded` when it is infinite.
2456 // Querying with the opposite half-plane gives the infimum side: `below`
2457 // then means inf > b, `on` means inf == b (attained).
2458 // Precondition: !empty_ and size() >= 1; a degenerate query is UB.
2459 template <HalfplaneConcept Query>
2460 constexpr SupStatus supStatus(const Query& query) const {
2461 const std::size_t n = halfplanes_.size();
2462 // The supremum in direction of the query's outward normal is attained
2463 // where the stored boundary directions bracket the query's direction.
2464 const std::size_t pos = linearUpperBound(query);
2465 const std::size_t predIdx = (pos == 0 ? n : pos) - 1;
2466 const auto& pred = halfplanes_[predIdx];
2467 if (detail::directionEqual(pred, query)) {
2468 // Attained along pred's whole boundary line, where a·p is
2469 // constant: compare via any boundary point.
2470 const auto side = orientationSign(query.source(), query.target(), pred.source());
2471 if (side > 0) {
2472 return SupStatus::below;
2473 }
2474 return side == 0 ? SupStatus::on : SupStatus::above;
2475 }
2476 const std::size_t succIdx = pos == n ? 0 : pos;
2477 if (succIdx == predIdx) {
2478 return SupStatus::unbounded; // single stored half-plane, gap 2*pi
2479 }
2480 if (!(detail::directionCross(pred, halfplanes_[succIdx]) > 0)) {
2481 // The query direction lies strictly inside a gap of at least pi:
2482 // the region is unbounded toward the query's outward normal.
2483 return SupStatus::unbounded;
2484 }
2485 const int side = detail::vertexSide(pred, halfplanes_[succIdx], query);
2486 if (side > 0) {
2487 return SupStatus::below;
2488 }
2489 return side == 0 ? SupStatus::on : SupStatus::above;
2490 }
2491
2492 // Exact clip of the directed query line against the region.
2493 // entry/exit are constraint indices (-1: unbounded on that side);
2494 // onParallelBoundary reports a constraint parallel to the line whose
2495 // boundary contains it (the line runs along a face).
2496 // Precondition: !empty_ and size() >= 1; a degenerate query is UB.
2497 struct ClipResult {
2498 bool empty = false;
2499 bool onParallelBoundary = false;
2500 std::ptrdiff_t entry = -1;
2501 std::ptrdiff_t exit = -1;
2502 };
2503
2504 template <HalfplaneConcept Query>
2505 constexpr ClipResult clipLine(const Query& query) const {
2506 ClipResult result;
2507 const auto reversed = query.opposite();
2508 // Constraints parallel to the line hold (or fail) along all of it.
2509 for (const std::ptrdiff_t parallelIdx : {sameDirectionIndex(query), sameDirectionIndex(reversed)}) {
2510 if (parallelIdx >= 0) {
2511 const auto side = constraintSide(static_cast<std::size_t>(parallelIdx), query.source());
2512 if (side < 0) {
2513 result.empty = true;
2514 return result;
2515 }
2516 if (side == 0) {
2517 result.onParallelBoundary = true;
2518 }
2519 }
2520 }
2521 result.exit = exitConstraint(query);
2522 result.entry = exitConstraint(reversed);
2523 if (result.entry >= 0 && result.exit >= 0) {
2524 // The interval is nonempty exactly when t_entry <= t_exit, which
2525 // (with the entry denominator negative and the exit denominator
2526 // positive) is the sign of the three-line determinant.
2527 const auto det = detail::boundaryLinesDeterminant(
2528 halfplanes_[static_cast<std::size_t>(result.entry)],
2529 halfplanes_[static_cast<std::size_t>(result.exit)], query);
2530 if (det > decltype(det){}) {
2531 result.empty = true;
2532 }
2533 }
2534 return result;
2535 }
2536
2537 // Compares the clip parameters of the entry and exit constraints strictly:
2538 // true when t_entry < t_exit (the clipped set has positive length).
2539 template <HalfplaneConcept Query>
2540 constexpr bool clipHasLength(const ClipResult& clip, const Query& query) const {
2541 if (clip.empty) {
2542 return false;
2543 }
2544 if (clip.entry < 0 || clip.exit < 0) {
2545 return true;
2546 }
2547 const auto det = detail::boundaryLinesDeterminant(
2548 halfplanes_[static_cast<std::size_t>(clip.entry)],
2549 halfplanes_[static_cast<std::size_t>(clip.exit)], query);
2550 return det < decltype(det){};
2551 }
2552
2553 // -1: the point is outside the region, 0: on its boundary, +1: in its
2554 // interior. O(log n): only the constraints binding along the vertical
2555 // line through the point (plus the vertical ones) need testing.
2556 template <PointConcept OtherPoint>
2557 constexpr int pointStatus(const OtherPoint& point) const {
2558 if (empty_) {
2559 return -1;
2560 }
2561 if (halfplanes_.empty()) {
2562 return 1;
2563 }
2564 using OtherNumber = typename OtherPoint::NumberType;
2565 using QueryPoint = Point<OtherNumber>;
2566 const QueryPoint base(point.x(), point.y());
2567 const Halfplane<QueryPoint> upward(base, QueryPoint(point.x(), point.y() + OtherNumber(1)));
2568 int result = 1;
2569 const std::ptrdiff_t candidates[4] = {
2570 exitConstraint(upward), exitConstraint(upward.opposite()),
2571 sameDirectionIndex(upward), sameDirectionIndex(upward.opposite())};
2572 for (const std::ptrdiff_t idx : candidates) {
2573 if (idx < 0) {
2574 continue;
2575 }
2576 const auto side = constraintSide(static_cast<std::size_t>(idx), point);
2577 if (side < 0) {
2578 return -1;
2579 }
2580 if (side == 0) {
2581 result = 0;
2582 }
2583 }
2584 return result;
2585 }
2586
2587 // Whether the direction belongs to the region's recession cone: the
2588 // region contains a translate of every ray with this direction. `strict`
2589 // additionally requires the interior recession (a·u < 0 for every stored
2590 // constraint). Precondition: !empty_.
2591 template <HalfplaneConcept Query>
2592 constexpr bool recessionContains(const Query& query, bool strict = false) const {
2593 if (halfplanes_.empty()) {
2594 return true;
2595 }
2596 // a_i·u <= 0 for all i means no stored boundary direction lies
2597 // strictly inside the open half-circle to the left of u.
2598 const auto [lo, count] = leftArc(query);
2599 (void)lo;
2600 if (count > 0) {
2601 return false;
2602 }
2603 if (!strict) {
2604 return true;
2605 }
2606 return sameDirectionIndex(query) < 0 && sameDirectionIndex(query.opposite()) < 0;
2607 }
2608
2609 // The recession cone as up to two closed angular arcs, each reported as a
2610 // pair of half-plane copies whose boundary directions delimit the arc
2611 // (from, to). A gap of length g >= pi from direction d_i to d_{i+1}
2612 // contributes the arc [d_i, -d_{i+1}] of length g - pi. O(n).
2613 // Precondition: !empty_ and size() >= 2 (a single half-plane's recession
2614 // half-circle and the whole plane are handled by the callers).
2615 constexpr std::vector<std::pair<HalfplaneType, HalfplaneType>> recessionArcs() const {
2616 std::vector<std::pair<HalfplaneType, HalfplaneType>> arcs;
2617 const std::size_t n = halfplanes_.size();
2618 for (std::size_t i = 0; i < n; ++i) {
2619 const std::size_t j = nextIndex(i);
2620 const auto cross = detail::directionCross(halfplanes_[i], halfplanes_[j]);
2621 // Antiparallel consecutive directions (cross == 0) leave a gap of
2622 // exactly pi and count as wide too; the same direction is
2623 // impossible in the canonical form for distinct consecutive
2624 // constraints, but a single pair wraps twice.
2625 const bool wide = cross <= 0;
2626 if (i == j) {
2627 break; // n == 1, excluded by precondition but stay safe
2628 }
2629 if (wide) {
2630 arcs.emplace_back(halfplanes_[i], halfplanes_[j].opposite());
2631 }
2632 }
2633 return arcs;
2634 }
2635};
2636
2647template <class PointType_, class TLabel>
2648constexpr std::optional<HalfplaneIntersection<PointType_>>
2650 using RegionType = HalfplaneIntersection<PointType>;
2651 if (const auto vertex = getIfPoint()) {
2652 return RegionType(*vertex);
2653 }
2654 if (const auto carrier = getIfSegment()) {
2655 return RegionType(*carrier);
2656 }
2657 if (empty() || isUndefined()) {
2658 // The empty polygon has no point to see it from, and an undefined one
2659 // has no interior side for its edges to bound. Either way the kernel is
2660 // empty, which is reported as no kernel at all.
2661 return std::nullopt;
2662 }
2663 RegionType kernel;
2664 const std::ptrdiff_t n = static_cast<std::ptrdiff_t>(size());
2665 for (std::ptrdiff_t i = 0; i < n; ++i) {
2666 const PointType source = get(i);
2667 const PointType target = get(i + 1);
2668 if (source == target) {
2669 continue;
2670 }
2671 kernel.insert(Halfplane<PointType>(source, target));
2672 if (kernel.empty()) {
2673 return std::nullopt;
2674 }
2675 }
2676 return kernel;
2677}
2678
2682template <class PointType, class LabelType, class TranslationNumber, class TranslationLabel>
2684 const Point<TranslationNumber, TranslationLabel>& translation) {
2685 return region + (-translation);
2686}
2687
2694template <class PointType, class LabelType, class Scalar>
2695 requires(!detail::is_point_v<Scalar> && !TransformationConcept<Scalar>)
2696constexpr auto operator*(const HalfplaneIntersection<PointType, LabelType>& region, const Scalar& scalar) {
2697 using ResultPointType = Point<decltype(std::declval<PointType>().x() * scalar), typename PointType::LabelType>;
2699 result *= scalar;
2700 if constexpr (detail::has_label_v<LabelType>) {
2701 result.label() = LabelType{};
2702 }
2703 return result;
2704}
2705
2707template <class Scalar, class PointType, class LabelType>
2708 requires(!detail::is_point_v<Scalar> && !TransformationConcept<Scalar>)
2709constexpr auto operator*(const Scalar& scalar, const HalfplaneIntersection<PointType, LabelType>& region) {
2710 return region * scalar;
2711}
2712
2718template <class PointType, class LabelType, class Scalar>
2719 requires(!detail::is_point_v<Scalar> && !TransformationConcept<Scalar>)
2720constexpr auto operator/(const HalfplaneIntersection<PointType, LabelType>& region, const Scalar& scalar) {
2721 using ResultPointType = Point<decltype(std::declval<PointType>().x() / scalar), typename PointType::LabelType>;
2723 result /= scalar;
2724 if constexpr (detail::has_label_v<LabelType>) {
2725 result.label() = LabelType{};
2726 }
2727 return result;
2728}
2729
2730template <class PointType, class LabelType>
2731std::ostream& operator<<(std::ostream& stream, const HalfplaneIntersection<PointType, LabelType>& region);
2732
2733} // namespace pgl
Shape pairs whose Minkowski sum Pangolin can represent.
Definition forward.hpp:476
Definition forward.hpp:306
Definition forward.hpp:324
Definition arrangement.hpp:67
HalfplaneIntersection() -> HalfplaneIntersection< Point<>, NoLabel >
Definition halfplaneintersection.hpp:2308
@ y
Definition intervaltree.hpp:24
@ x
Definition intervaltree.hpp:24
@ vertex
Definition bitmatrix.hpp:37
Line() -> Line< Point<>, NoLabel >
Point() -> Point< int >
constexpr std::partial_ordering dotSign(const Point< ANumber, ALabel > &a, const Point< BNumber, BLabel > &b)
Tells if the angle between two vectors is acute, right, or obtuse.
Definition orientation.hpp:688
constexpr auto operator-(const Point< LeftNumber, LeftLabel > &left, const Point< RightNumber, RightLabel > &right)
Translates a point by the opposite of another point.
Definition transformations.hpp:130
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
std::ostream & operator<<(std::ostream &stream, const Point< Number, Label > &point)
Streams a point as (x,y) or label:(x,y).
Definition io.hpp:27
Segment() -> Segment< Point<>, NoLabel >
Halfplane() -> Halfplane< Point<>, NoLabel >
Ray() -> Ray< Point<>, NoLabel >
Closed convex polygon stored by its vertices.
Definition convex.hpp:170
The empty set of points in the plane.
Definition emptyshape.hpp:33
Intersection of closed half-planes; convex but possibly unbounded or empty.
Definition halfplaneintersection.hpp:244
constexpr bool crosses(const OtherConvex &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:1119
constexpr bool crosses(const OtherOrientedSegment &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:1065
constexpr Rectangle< Point< ResultNumber, typename PointType::LabelType > > bbox() const
Computes the bounding box of the region.
Definition bounding.hpp:538
constexpr bool boundaryContains(const OtherConvex &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1496
constexpr bool separates(const OtherRectangle &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4165
constexpr bool intersects(const OtherOrientedLine &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1862
constexpr bool boundaryContains(const Shape< OtherPoint > &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1585
constexpr auto minkowskiSum(const OtherShape &other) const
Returns the Minkowski sum of this shape and another (A ⊕ B).
Definition minkowski.hpp:808
constexpr auto minkowskiErosion(const OtherShape &other) const
Returns the Minkowski erosion of this shape by another (A ⊖ B).
Definition minkowskierosion.hpp:641
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2511
constexpr bool boundaryContains(const OtherDisk &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1486
constexpr bool interiorContains(const OtherSegment &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1824
constexpr bool intersects(const OtherRectangle &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1901
constexpr bool crosses(const OtherDisk &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:1113
constexpr bool crosses(const OtherLine &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:1071
detail::floating_result_t< ResultNumber > squaredDistance(const OtherDisk &other) const
Returns the squared Euclidean distance to the given disk.
Definition distance.hpp:1799
constexpr bool boundaryContains(const OtherHalfplane &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1454
constexpr bool interiorContains(const OtherChain &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1940
constexpr auto distanceLInf(const OtherShape &other) const
Returns the Chebyshev (L∞) distance to the given shape.
Definition halfplaneintersection.hpp:2234
constexpr bool intersects(const OtherOrientedSegment &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1843
constexpr bool boundaryContains(const OtherOrientedLine &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1430
constexpr auto operator<=>(const HalfplaneIntersection &other) const
Provides an ordering compatible with operator==.
Definition halfplaneintersection.hpp:1009
constexpr bool crosses(const OtherPoint &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:1052
constexpr auto distanceL1(const Shape< OtherPoint > &other) const
Returns the Manhattan (L1) distance to the given shape, using symmetry to re-dispatch through the wra...
Definition halfplaneintersection.hpp:2136
constexpr auto squaredDistance(const OtherPoint &other) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:1780
constexpr bool contains(const OtherLine &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2530
constexpr bool boundaryContains(const OtherPolygon &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1547
constexpr HalfplaneIntersection< Point< ResultNumber, typename PointType::LabelType > > intersection(const OtherTriangle &other) const
Returns the intersection with a triangle, as a half-plane intersection.
Definition intersection.hpp:3371
constexpr HalfplaneIntersection(Range &&halfplanes, bool trusted=false)
Creates the intersection of a range of half-planes.
Definition halfplaneintersection.hpp:289
constexpr auto distanceL1(const OtherTriangle &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition distancel1.hpp:1440
Halfplane< PointType > HalfplaneType
Definition halfplaneintersection.hpp:248
constexpr HalfplaneIntersection rotated90(int k=1) const
Returns the region rotated by 90k degrees around the origin.
Definition transformations.hpp:2460
constexpr auto cend() const
Returns a constant iterator past the last half-plane.
Definition halfplaneintersection.hpp:644
constexpr bool crosses(const EmptyShape< EmptyPoint > &) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition halfplaneintersection.hpp:1757
constexpr bool crosses(const OtherShape &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition halfplaneintersection.hpp:1720
constexpr bool contains(const OtherDisk &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2605
constexpr std::optional< Segment< Point< ResultNumber, typename PointType::LabelType > > > getIfSegment() const
Returns the segment the region collapses to, if it is one.
Definition predicates.hpp:1243
constexpr bool interiorContains(const OtherConvex &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1929
constexpr bool contains(const OtherSegment &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2517
constexpr bool interiorsIntersect(const OtherRectangle &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:2205
constexpr std::ptrdiff_t index(const HalfplaneType &halfplane) const
Definition halfplaneintersection.hpp:624
constexpr HalfplaneIntersection(const OtherLine &line)
Creates the degenerate region consisting of a line.
Definition halfplaneintersection.hpp:439
constexpr bool contains(const OtherRay &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2553
constexpr bool crosses(const OtherChain &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:1125
constexpr bool interiorContains(const OtherPolyline &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1951
constexpr void scaleDownX(const OtherNumber scalar)
Divides the region's x-coordinates by a divisor in place.
Definition transformations.hpp:2521
constexpr std::optional< std::variant< Point< ResultNumber, typename PointType::LabelType >, Segment< Point< ResultNumber, typename PointType::LabelType > >, Ray< Point< ResultNumber, typename PointType::LabelType > >, Line< Point< ResultNumber, typename PointType::LabelType > > > > intersection(const OtherOrientedLine &other) const
Returns the intersection of the two shapes (A ∩ B), empty when they are disjoint.
Definition intersection.hpp:3195
constexpr auto distanceLInf(const Shape< OtherPoint > &other) const
Returns the Chebyshev (L∞) distance to the given shape, using symmetry to re-dispatch through the wra...
Definition halfplaneintersection.hpp:2201
constexpr bool interiorContains(const EmptyShape< EmptyPoint > &) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition halfplaneintersection.hpp:1737
constexpr bool empty() const
Returns whether the region is the empty set.
Definition halfplaneintersection.hpp:649
constexpr auto distanceL1(const OtherHalfplane &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition distancel1.hpp:1438
constexpr auto distanceL1(const OtherRectangle &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition distancel1.hpp:1439
constexpr auto squaredDistance(const OtherOrientedLine &other) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:1784
constexpr auto distanceL1(const OtherShape &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition halfplaneintersection.hpp:2224
constexpr bool separates(const OtherPolygon &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4250
constexpr auto squaredDistance(const OtherChain &other) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:1790
constexpr bool boundaryContains(const EmptyShape< EmptyPoint > &) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition halfplaneintersection.hpp:1732
constexpr bool isHalfplane() const
Returns whether the region is exactly one closed half-plane.
Definition predicates.hpp:1152
constexpr HalfplaneIntersection & operator-=(const OtherPoint &translation)
Translates the region by the negation of the given point in place.
constexpr bool intersects(const OtherShape &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition halfplaneintersection.hpp:1693
constexpr auto squaredDistance(const OtherPolyline &other) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:1791
constexpr bool contains(const OtherConvex &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2625
constexpr bool vertexExists(std::size_t i) const
Returns whether the half-plane pair (i, i+1) (cyclically) defines a vertex of the region.
Definition halfplaneintersection.hpp:854
constexpr HalfplaneIntersection(const OtherTriangle &triangle)
Creates the region of a triangle as three half-planes.
Definition halfplaneintersection.hpp:346
constexpr auto distanceLInf(const OtherSegment &other) const
Returns the Chebyshev (L∞) distance to the given shape.
Definition distancelinf.hpp:1422
constexpr auto squaredDistance(const OtherShape &other) const
Returns the squared Euclidean distance to the given shape.
Definition halfplaneintersection.hpp:2214
constexpr bool contains(const OtherRegion &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2674
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 auto distanceLInf(const OtherOrientedLine &other) const
Returns the Chebyshev (L∞) distance to the given shape.
Definition distancelinf.hpp:1425
constexpr bool separates(const OtherPolyline &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4280
TLabel LabelType
Definition halfplaneintersection.hpp:247
constexpr auto distanceLInf(const OtherPoint &other) const
Returns the Chebyshev (L∞) distance to the given shape.
Definition distancelinf.hpp:1421
constexpr bool interiorsIntersect(const OtherPolygon &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:2285
constexpr HalfplaneIntersection(const OtherPoint &point)
Creates the degenerate region consisting of a single point.
Definition halfplaneintersection.hpp:407
constexpr HalfplaneIntersection scaledDownX(const OtherNumber scalar) const
Returns the region with its x-coordinates divided by a divisor.
constexpr bool crosses(const OtherSegment &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:1059
constexpr bool boundaryContains(const OtherSet &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition halfplaneintersection.hpp:1593
constexpr auto squaredDistance(const OtherOrientedSegment &other) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:1782
constexpr bool boundaryContains(const OtherRay &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1436
constexpr bool interiorContains(const OtherLine &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1838
constexpr bool separates(const OtherDisk &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4232
constexpr auto area() const
Returns the area of the region.
Definition measures.hpp:1325
constexpr bool crosses(const OtherRay &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:1083
constexpr std::optional< std::variant< Point< ResultNumber, typename PointType::LabelType >, Segment< Point< ResultNumber, typename PointType::LabelType > >, Ray< Point< ResultNumber, typename PointType::LabelType > >, Line< Point< ResultNumber, typename PointType::LabelType > > > > intersection(const OtherLine &other) const
Returns the intersection of the two shapes (A ∩ B), empty when they are disjoint.
Definition intersection.hpp:3139
constexpr void scaleDownY(const OtherNumber scalar)
Divides the region's y-coordinates by a divisor in place.
Definition transformations.hpp:2539
constexpr std::optional< std::variant< Point< ResultNumber, typename PointType::LabelType >, Segment< Point< ResultNumber, typename PointType::LabelType > > > > intersection(const OtherOrientedSegment &other) const
Returns the intersection of the two shapes (A ∩ B), empty when they are disjoint.
Definition intersection.hpp:3269
constexpr bool contains(const OtherHalfplane &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2569
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 bool intersects(const OtherPolyline &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1964
constexpr HalfplaneIntersection< Point< ResultNumber, typename PointType::LabelType > > intersection(const OtherHalfplane &other) const
Returns the intersection with a half-plane, as a half-plane intersection.
Definition intersection.hpp:3333
constexpr auto distanceLInf(const OtherChain &other) const
Returns the Chebyshev (L∞) distance to the given shape.
Definition distancelinf.hpp:1431
constexpr bool boundaryContains(const OtherSegment &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1385
constexpr bool interiorContains(const OtherRay &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1860
constexpr auto distanceLInf(const OtherConvex &other) const
Returns the Chebyshev (L∞) distance to the given shape.
Definition distancelinf.hpp:1430
constexpr HalfplaneIntersection(const OtherHalfplane &halfplane)
Creates the region bounded by a single half-plane.
Definition halfplaneintersection.hpp:261
constexpr bool interiorContains(const OtherTriangle &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1907
constexpr bool interiorsIntersect(const OtherOrientedSegment &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:2145
constexpr auto squaredDistance(const OtherTriangle &other) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:1788
constexpr bool intersects(const OtherConvex &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1919
std::vector< Point< ResultNumber, typename PointType::LabelType > > latticePoints() const
Returns the integer points the region contains.
Definition lattice.hpp:673
constexpr bool intersects(const OtherHalfplane &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1887
constexpr bool intersects(const OtherTriangle &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1913
constexpr auto squaredDistance(const OtherPolygon &other) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:1792
constexpr bool interiorContains(const OtherPoint &point) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1816
constexpr HalfplaneIntersection scaledDownY(const OtherNumber scalar) const
Returns the region with its y-coordinates divided by a divisor.
constexpr auto distanceL1(const OtherRay &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition distancel1.hpp:1437
constexpr auto closestPoints(const OtherShape &other) const
Returns the pair of points realizing the distance, nothing when the shapes meet.
Definition closest.hpp:482
constexpr HalfplaneIntersection scaledUpX(const OtherNumber scalar) const
Returns the region with its x-coordinates multiplied by a factor.
constexpr void rotate90(int k=1)
Rotates the region by 90k degrees around the origin in place.
Definition transformations.hpp:2467
constexpr bool intersects(const OtherSegment &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1814
constexpr bool separates(const OtherRay &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4094
constexpr bool isSegment() const
Returns whether the region is a segment of positive length.
Definition predicates.hpp:1232
constexpr bool interiorsIntersect(const OtherRay &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:2171
constexpr A & label() const
Returns the label.
Definition halfplaneintersection.hpp:487
constexpr bool isBounded() const
Returns whether the region is bounded.
Definition halfplaneintersection.hpp:811
constexpr HalfplaneIntersection(const HalfplaneIntersection< OtherPointType, OtherLabelType > &other)
Converts a half-plane intersection with a compatible point type.
Definition halfplaneintersection.hpp:454
constexpr bool separates(const OtherLine &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4073
std::vector< std::variant< Point< ResultNumber, typename PointType::LabelType >, Polyline< Point< ResultNumber, typename PointType::LabelType > >, Polygon< Point< ResultNumber, typename PointType::LabelType > > > > intersection(const OtherPolygon &other) const
Returns the intersection with a simple polygon (A ∩ B), as components.
Definition intersection.hpp:3440
minkowskiErosionPoint_t< A, B > PointType
Definition halfplaneintersection.hpp:245
constexpr bool separates(const OtherChain &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4268
constexpr bool contains(const OtherChain &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2637
constexpr bool boundaryContains(const OtherLine &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1414
constexpr auto distanceL1(const OtherOrientedSegment &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition distancel1.hpp:1434
constexpr bool interiorContains(const OtherOrientedSegment &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1832
constexpr bool separates(const OtherSegment &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4058
constexpr bool isDegenerate() const
Returns whether the region has empty interior (it is empty or lower-dimensional: a line,...
Definition halfplaneintersection.hpp:664
PointType::NumberType NumberType
Definition halfplaneintersection.hpp:246
constexpr bool contains(const OtherOrientedLine &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2547
constexpr bool interiorContains(const OtherHalfplane &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1877
constexpr auto squaredDistance(const OtherLine &other) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:1783
constexpr auto squaredDistance(const OtherRegion &other) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:1823
constexpr auto squaredDistance(const OtherSegment &other) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:1781
constexpr auto squaredDistance(const OtherRay &other) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:1785
constexpr void scaleUpY(const OtherNumber scalar)
Multiplies the region's y-coordinates by a factor in place.
Definition transformations.hpp:2503
constexpr bool boundaryContains(const OtherPoint &point) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1376
constexpr std::optional< Ray< Point< ResultNumber, typename PointType::LabelType > > > getIfRay() const
Returns the ray the region equals, if it is one.
Definition predicates.hpp:1194
constexpr bool contains(const OtherTriangle &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2599
constexpr bool interiorContains(const Shape< OtherPoint > &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1997
constexpr bool interiorsIntersect(const OtherPoint &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:2111
constexpr bool crosses(const OtherTriangle &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:1107
constexpr Convex< Point< ResultNumber, typename PointType::LabelType > > asConvex() const
Returns the region as a convex polygon.
Definition halfplaneintersection.hpp:955
constexpr bool interiorContains(const OtherSet &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition halfplaneintersection.hpp:1604
constexpr bool intersects(const OtherRegion &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:2003
constexpr bool contains(const OtherPolyline &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2649
constexpr bool interiorContains(const OtherDisk &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1913
constexpr std::optional< Point< ResultNumber, typename PointType::LabelType > > intersection(const OtherPoint &other) const
Returns the intersection of the two shapes (A ∩ B), empty when they are disjoint.
Definition intersection.hpp:3126
constexpr HalfplaneIntersection(const OtherConvex &convex)
Creates the region of a convex polygon as its edge half-planes.
Definition halfplaneintersection.hpp:375
constexpr bool intersects(const Shape< OtherPoint > &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:2014
constexpr bool interiorsIntersect(const OtherTriangle &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:2220
constexpr bool crosses(const OtherPolyline &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:1131
constexpr bool boundaryContains(const OtherChain &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1513
bool separates(const OtherSet &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:6017
constexpr bool contains(const OtherRectangle &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2581
constexpr bool intersects(const OtherLine &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1849
constexpr bool interiorsIntersect(const OtherChain &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:2255
constexpr bool separates(const Shape< OtherPoint > &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4542
constexpr auto distanceLInf(const OtherPolyline &other) const
Returns the Chebyshev (L∞) distance to the given shape.
Definition distancelinf.hpp:1432
constexpr std::size_t size() const
Returns the number of stored (non-redundant) half-planes.
Definition halfplaneintersection.hpp:596
constexpr bool interiorContains(const OtherOrientedLine &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1854
constexpr std::size_t vertexCount() const
Returns the number of vertices of the region.
Definition halfplaneintersection.hpp:833
constexpr const HalfplaneType & operator[](std::size_t index) const
Accesses a stored half-plane by index, in boundary (counterclockwise pseudo-angle) order.
Definition halfplaneintersection.hpp:604
constexpr auto distanceL1(const OtherLine &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition distancel1.hpp:1435
constexpr bool interiorsIntersect(const OtherDisk &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:2238
constexpr auto distanceLInf(const OtherRay &other) const
Returns the Chebyshev (L∞) distance to the given shape.
Definition distancelinf.hpp:1426
constexpr auto distanceL1(const OtherConvex &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition distancel1.hpp:1441
constexpr auto distanceL1(const OtherPolyline &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition distancel1.hpp:1443
auto regularizedIntersection(const Shape< OtherPoint > &other) const
Re-dispatches a regularized intersection through a runtime shape.
Definition halfplaneintersection.hpp:2127
constexpr bool separates(const OtherOrientedSegment &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4067
constexpr bool contains(const EmptyShape< EmptyPoint > &) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition halfplaneintersection.hpp:1727
constexpr auto cbegin() const
Returns a constant iterator to the first half-plane, in boundary order.
Definition halfplaneintersection.hpp:640
constexpr bool separates(const OtherTriangle &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4187
constexpr bool isPoint() const
Returns whether the region is a single point.
Definition predicates.hpp:1212
constexpr bool boundaryContains(const OtherRectangle &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1462
friend struct HalfplaneIntersection
Definition halfplaneintersection.hpp:2308
constexpr bool operator==(const HalfplaneIntersection &other) const
Tests equality of the stored regions.
Definition halfplaneintersection.hpp:984
constexpr auto distanceLInf(const OtherOrientedSegment &other) const
Returns the Chebyshev (L∞) distance to the given shape.
Definition distancelinf.hpp:1423
constexpr bool separates(const OtherPoint &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4050
constexpr bool interiorsIntersect(const OtherRegion &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:2304
constexpr bool pointInsideInteriorContainedIn(const OtherShape &shape) const
Tests whether an exact interior witness of this region lies in the interior of the given shape.
Definition measures.hpp:1400
constexpr bool crosses(const OtherOrientedLine &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:1077
constexpr std::optional< std::variant< Point< ResultNumber, typename PointType::LabelType >, Segment< Point< ResultNumber, typename PointType::LabelType > > > > intersection(const OtherSegment &other) const
Returns the intersection of the two shapes (A ∩ B), empty when they are disjoint.
Definition intersection.hpp:3203
constexpr bool intersects(const OtherPolygon &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1981
constexpr std::optional< HalfplaneType > getIfHalfplane() const
Returns the half-plane the region equals, if it is one.
Definition predicates.hpp:1158
constexpr bool separates(const OtherOrientedLine &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4088
constexpr bool separates(const OtherHalfplane &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4113
constexpr const HalfplaneType & get(std::ptrdiff_t index) const
Cyclic access: same as operator[] but index is taken modulo size(); negative indices wrap from the en...
Definition halfplaneintersection.hpp:613
constexpr bool contains(const OtherHoledRegion &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:3340
constexpr bool isRay() const
Returns whether the region is exactly one ray.
Definition predicates.hpp:1184
constexpr bool isLine() const
Returns whether the region is exactly one line.
Definition predicates.hpp:1166
constexpr HalfplaneIntersection scaledUpY(const OtherNumber scalar) const
Returns the region with its y-coordinates multiplied by a factor.
constexpr bool interiorsIntersect(const OtherSegment &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:2118
constexpr bool separates(const OtherConvex &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4205
constexpr auto twiceArea() const
Returns twice the area of the region.
Definition measures.hpp:1313
constexpr bool insert(const OtherHalfplane &other)
Intersects the region with one more half-plane.
Definition halfplaneintersection.hpp:509
constexpr HalfplaneIntersection()=default
Creates the whole plane (the intersection of no half-planes).
constexpr bool boundaryContains(const OtherRegion &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1569
constexpr bool boundaryContains(const OtherHoledRegion &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:2073
constexpr std::vector< HalfplaneType > halfplanes() const
Definition halfplaneintersection.hpp:633
auto intersection(const OtherShape &other) const
Returns the intersection of the two shapes (A ∩ B), empty when they are disjoint.
Definition halfplaneintersection.hpp:1942
constexpr bool boundaryContains(const OtherPolyline &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1530
constexpr bool interiorsIntersect(const OtherShape &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition halfplaneintersection.hpp:1706
constexpr bool intersects(const OtherRay &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1868
constexpr bool crosses(const Shape< OtherPoint > &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:1149
constexpr HalfplaneIntersection & operator+=(const OtherPoint &translation)
Translates the region by the given point in place.
constexpr auto distanceL1(const OtherOrientedLine &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition distancel1.hpp:1436
constexpr HalfplaneIntersection< Point< ResultNumber, typename PointType::LabelType > > intersection(const OtherRectangle &other) const
Returns the intersection with a rectangle, as a half-plane intersection.
Definition intersection.hpp:3345
constexpr bool interiorsIntersect(const OtherOrientedLine &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:2165
constexpr HalfplaneIntersection< Point< ResultNumber, typename PointType::LabelType > > intersection(const OtherConvex &other) const
Returns the intersection with a convex polygon, as a half-plane intersection.
Definition intersection.hpp:3383
constexpr bool contains(const OtherPolygon &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2661
auto regularizedIntersection(const OtherShape &other) const
Forwards a regularized intersection to the shape that owns it.
Definition halfplaneintersection.hpp:1953
constexpr bool contains(const OtherSet &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition halfplaneintersection.hpp:1582
constexpr HalfplaneIntersection(const OtherRectangle &rectangle)
Creates the region of a rectangle as four half-planes.
Definition halfplaneintersection.hpp:310
constexpr bool boundaryContains(const OtherOrientedSegment &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1408
constexpr auto distanceL1(const OtherChain &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition distancel1.hpp:1442
constexpr auto distanceLInf(const OtherRegion &other) const
Returns the Chebyshev (L∞) distance to the given shape.
Definition distancelinf.hpp:1439
constexpr auto squaredDistance(const OtherRectangle &other) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:1787
constexpr bool intersects(const OtherDisk &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1928
constexpr bool interiorsIntersect(const OtherLine &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:2151
constexpr Convex< Point< ResultNumber, typename PointType::LabelType > > convexHull() const
Returns the region's convex hull.
Definition halfplaneintersection.hpp:972
constexpr bool crosses(const OtherPolygon &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:1137
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1808
constexpr bool contains(const OtherOrientedSegment &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2524
constexpr auto distanceL1(const OtherRegion &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition distancel1.hpp:1450
constexpr bool intersects(const EmptyShape< EmptyPoint > &) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition halfplaneintersection.hpp:1742
constexpr auto intersection(const Shape< OtherPoint > &other) const
Returns the intersection of the two shapes (A ∩ B), re-dispatching through the wrapper's own intersec...
Definition halfplaneintersection.hpp:2121
constexpr bool intersects(const OtherChain &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1947
constexpr bool interiorsIntersect(const OtherConvex &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:2229
constexpr auto distanceLInf(const OtherTriangle &other) const
Returns the Chebyshev (L∞) distance to the given shape.
Definition distancelinf.hpp:1429
bool separates(const OtherHoledRegion &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:5773
constexpr Point< ResultNumber > centroid() const
Returns the centroid of the region.
Definition measures.hpp:1337
constexpr bool separates(const EmptyShape< EmptyPoint > &) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition halfplaneintersection.hpp:1752
constexpr bool interiorContains(const OtherRectangle &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1888
constexpr auto distanceLInf(const OtherHalfplane &other) const
Returns the Chebyshev (L∞) distance to the given shape.
Definition distancelinf.hpp:1427
constexpr auto end() const
Returns a constant iterator past the last half-plane.
Definition halfplaneintersection.hpp:642
constexpr bool interiorContains(const OtherPolygon &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1962
constexpr bool interiorsIntersect(const OtherHalfplane &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:2189
constexpr bool interiorsIntersect(const Shape< OtherPoint > &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:2316
constexpr bool interiorContains(const OtherHoledRegion &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:2553
constexpr HalfplaneIntersection(const OtherSegment &segment)
Creates the degenerate region consisting of a segment.
Definition halfplaneintersection.hpp:420
constexpr bool interiorContains(const OtherRegion &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1975
constexpr auto squaredDistance(const OtherHalfplane &other) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:1786
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 bool crosses(const OtherRectangle &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:1097
constexpr auto distanceLInf(const OtherLine &other) const
Returns the Chebyshev (L∞) distance to the given shape.
Definition distancelinf.hpp:1424
constexpr bool boundaryContains(const OtherTriangle &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1478
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
constexpr bool crosses(const OtherRegion &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:1143
constexpr auto distanceL1(const OtherPolygon &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition distancel1.hpp:1444
constexpr bool separates(const OtherRegion &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4515
constexpr Rectangle< Point< ResultNumber > > fbox() const
Computes the floating-point bounding box of the region.
Definition bounding.hpp:623
constexpr HalfplaneIntersection< Point< ResultNumber, typename PointType::LabelType > > intersection(const OtherRegion &other) const
Returns the intersection with another half-plane intersection.
Definition intersection.hpp:3403
constexpr std::optional< std::variant< Point< ResultNumber, typename PointType::LabelType >, Segment< Point< ResultNumber, typename PointType::LabelType > >, Ray< Point< ResultNumber, typename PointType::LabelType > > > > intersection(const OtherRay &other) const
Returns the intersection of the two shapes (A ∩ B), empty when they are disjoint.
Definition intersection.hpp:3278
constexpr Point< ResultNumber, typename PointType::LabelType > vertex(std::size_t i) const
Definition halfplaneintersection.hpp:875
constexpr auto squaredDistance(const OtherConvex &other) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:1789
constexpr auto distanceLInf(const OtherRectangle &other) const
Returns the Chebyshev (L∞) distance to the given shape.
Definition distancelinf.hpp:1428
constexpr auto distanceLInf(const OtherPolygon &other) const
Returns the Chebyshev (L∞) distance to the given shape.
Definition distancelinf.hpp:1433
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:2025
constexpr std::optional< Line< PointType > > getIfLine() const
Returns the line the region equals, if it is one.
Definition predicates.hpp:1174
constexpr auto begin() const
Returns a constant iterator to the first half-plane, in boundary order.
Definition halfplaneintersection.hpp:638
constexpr bool contains(const Shape< OtherPoint > &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2693
constexpr auto distanceL1(const OtherPoint &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition distancel1.hpp:1432
constexpr auto distanceL1(const OtherSegment &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition distancel1.hpp:1433
constexpr bool interiorsIntersect(const OtherPolyline &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:2271
constexpr bool isUndefined() const
Returns whether the region is undefined.
Definition halfplaneintersection.hpp:678
constexpr bool crosses(const OtherHalfplane &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:1089
constexpr bool isPlane() const
Returns whether the region is the whole plane (no half-planes).
Definition halfplaneintersection.hpp:656
constexpr bool interiorsIntersect(const EmptyShape< EmptyPoint > &) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition halfplaneintersection.hpp:1747
constexpr std::optional< Point< ResultNumber, typename PointType::LabelType > > getIfPoint() const
Returns the point the region collapses to, if it is one.
Definition predicates.hpp:1223
constexpr void scaleUpX(const OtherNumber scalar)
Multiplies the region's x-coordinates by a factor in place.
Definition transformations.hpp:2485
Closed half-plane defined by an oriented boundary line.
Definition halfplane.hpp:51
constexpr Halfplane opposite() const
Returns the complementary half-plane with reversed boundary orientation.
Definition halfplane.hpp:223
constexpr bool isUndefined() const
Returns whether the half-plane is degenerate without collapsing to a point or to a segment.
Definition predicates.hpp:957
Unoriented infinite line.
Definition line.hpp:52
Sentinel type used when a point carries no extra label.
Definition point.hpp:31
Two-dimensional point with optional label payload.
Definition point.hpp:129
Closed simple polygon stored by its vertices.
Definition polygon.hpp:59
constexpr std::optional< PointType > getIfPoint() const
Returns the point the polygon collapses to, if it does.
Definition polygon.hpp:341
constexpr std::optional< HalfplaneIntersection< PointType > > getStarShapedKernel() const
Returns the kernel: the set of points that see the whole polygon.
Definition halfplaneintersection.hpp:2649
constexpr bool isUndefined() const
Checks whether the polygon is degenerate without covering a point or a segment.
Definition polygon.hpp:388
constexpr std::optional< BoundaryType< false > > getIfSegment() const
Returns the segment the polygon collapses to, if it does.
Definition polygon.hpp:369
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 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 empty() const
Returns whether the polygon is the empty set of points.
Definition polygon.hpp:302
Open polygonal chain stored in traversal order; may self-intersect.
Definition polyline.hpp:69
Half-infinite line starting from one source point plus optional ray label.
Definition ray.hpp:51
Axis-aligned rectangle stored by minimum and maximum corners.
Definition rectangle.hpp:75
Unoriented closed segment between two endpoints plus optional segment label.
Definition segment.hpp:58
Runtime variant wrapper over the supported primitive shapes.
Definition shape.hpp:160