Pangolin
Header-only C++20 plane computational geometry library
Loading...
Searching...
No Matches
disk.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "shape/triangle.hpp"
4
15
16#include <array>
17#include <cassert>
18#include <cmath>
19#include <compare>
20#include <concepts>
21#include <cstddef>
22#include <iterator>
23#include <numbers>
24#include <optional>
25#include <vector>
26#include <ostream>
27#include <type_traits>
28#include <utility>
29#include <stdexcept>
30
31
32namespace pgl {
33
34template <class PointType = Point<>, class Label = NoLabel>
35struct Disk;
36
39
41template <class PointType>
42Disk(PointType, typename PointType::NumberType) -> Disk<PointType, NoLabel>;
43
45template <PointConcept PointType>
46Disk(PointType, PointType, PointType) -> Disk<PointType, NoLabel>;
47
49template <class Number>
50Disk(Number, Number, Number) -> Disk<Point<Number>, NoLabel>;
51
65template <class PointType_, class TLabel>
66struct Disk {
67 using PointType = PointType_;
70 using LabelType = TLabel;
71
72 static_assert(detail::is_point_v<PointType>, "Disk requires pgl::Point boundary points");
73
77 constexpr Disk() = default;
78
85 constexpr Disk(PointType first, PointType second, PointType third)
87 : points_(canonicalizePoints(std::move(first), std::move(second), std::move(third))) {}
88
95 template <class A>
96 requires(detail::has_label_v<LabelType> && std::constructible_from<LabelType, A&&>)
97 constexpr Disk(PointType first, PointType second, PointType third, A&& label)
99 : Disk(std::move(first), std::move(second), std::move(third)) {
100 label_ = std::forward<A>(label);
101 }
102
112 requires PointConcept<PointType> {
113 const NumberType zero{};
114 const NumberType r = radius < zero ? -radius : radius;
115 const NumberType cx = center.x();
116 const NumberType cy = center.y();
117 const auto point_label = detail::copyLabel<PointLabelType>(center);
118
119 points_ = canonicalizePoints(
120 Point<NumberType, PointLabelType>(cx - r, cy, point_label),
121 Point<NumberType, PointLabelType>(cx + r, cy, point_label),
122 Point<NumberType, PointLabelType>(cx, cy + r, point_label)
123 );
124 }
125
126 template <class A>
127 requires(detail::has_label_v<LabelType> && std::constructible_from<LabelType, A&&>)
129 requires PointConcept<PointType> : Disk(std::move(center), radius) {
130 label_ = std::forward<A>(label);
131 }
132
138
140 template <class A>
141 requires(detail::has_label_v<LabelType> && std::constructible_from<LabelType, A&&>)
143 : Disk(PointType(x, y), radius, std::forward<A>(label)) {}
144
152 template <PointConcept OtherPointType, class OtherLabelType>
153 requires(std::constructible_from<PointType, const OtherPointType&>)
155 : points_(canonicalizePoints(PointType(other.a()), PointType(other.b()), PointType(other.c()))),
156 label_(detail::copyLabel<LabelType>(other)) {}
157
165 template <PointConcept OtherPointType, class OtherLabelType>
166 requires(std::constructible_from<PointType, const OtherPointType&>)
168 points_ = canonicalizePoints(PointType(other.a()), PointType(other.b()), PointType(other.c()));
169 label_ = detail::copyLabel<LabelType>(other);
170 return *this;
171 }
172
181 template <class A = LabelType>
182 requires(detail::has_label_v<A>)
183 constexpr A& label() const {
184 return label_;
185 }
186
191 constexpr const PointType& operator[](std::size_t index) const {
192 assert(index < size());
193 return points_[index];
194 }
195
199 static constexpr std::size_t size() {
200 return 3;
201 }
202
207 constexpr const PointType& get(std::ptrdiff_t index) const {
208 const std::ptrdiff_t n = static_cast<std::ptrdiff_t>(size());
209 return (*this)[static_cast<std::size_t>(((index % n) + n) % n)];
210 }
211
216 constexpr std::ptrdiff_t index(const PointType& point) const {
217 for (std::ptrdiff_t i = 0; i < static_cast<std::ptrdiff_t>(size()); ++i) {
218 if ((*this)[static_cast<std::size_t>(i)] == point) {
219 return i;
220 }
221 }
222 return -1;
223 }
224
228 constexpr const PointType& a() const {
229 return points_[0];
230 }
231
235 constexpr const PointType& b() const {
236 return points_[1];
237 }
238
244 constexpr const PointType& c() const {
245 return points_[2];
246 }
247
251 constexpr auto begin() const {
252 return PointIterator(this, 0);
253 }
254
258 constexpr auto cbegin() const {
259 return PointIterator(this, 0);
260 }
261
265 constexpr auto end() const {
266 return PointIterator(this, size());
267 }
268
272 constexpr auto cend() const {
273 return PointIterator(this, size());
274 }
275
283 template <class ResultNumber = division_result_t<NumberType>>
284 [[nodiscard]] constexpr Point<ResultNumber, PointLabelType> center() const {
285 if (auto cr = centerAndRadius()) {
286 return Point<ResultNumber, PointLabelType>(cr->first);
287 }
288
289 if (isDegenerate()) {
291 }
292
293 using Coordinate = detail::promoted_number_t<std::common_type_t<NumberType, ResultNumber>>;
294 const Coordinate ax = static_cast<Coordinate>(a().x()), ay = static_cast<Coordinate>(a().y());
295 const Coordinate bx = static_cast<Coordinate>(b().x()), by = static_cast<Coordinate>(b().y());
296 const Coordinate cx = static_cast<Coordinate>(c().x()), cy = static_cast<Coordinate>(c().y());
297
298 const Coordinate aa = ax * ax + ay * ay;
299 const Coordinate bb = bx * bx + by * by;
300 const Coordinate cc = cx * cx + cy * cy;
301 const Coordinate two = static_cast<Coordinate>(2);
302
303 const Coordinate denominator = two * (ax * (by - cy) + bx * (cy - ay) + cx * (ay - by));
304
306 (aa * (by - cy) + bb * (cy - ay) + cc * (ay - by)) / denominator,
307 (aa * (cx - bx) + bb * (ax - cx) + cc * (bx - ax)) / denominator,
309 );
310 }
311
312 // /**
313 // * @brief Returns the center in this disk's exact coordinate type.
314 // *
315 // * For integral coordinates the circumcenter is generally rational, so the
316 // * result is `Rational<promoted NumberType>`; for floating-point coordinates
317 // * it is the promoted floating-point type.
318 // */
319 // [[nodiscard]] constexpr auto center() const {
320 // using ResultNumber = std::conditional_t<
321 // detail::extended_integral<NumberType>,
322 // Rational<detail::promoted_number_t<NumberType>>,
323 // detail::promoted_number_t<NumberType>>;
324 // return center<ResultNumber>();
325 // }
326
332 template <class ResultNumber = double>
333 [[nodiscard]] constexpr ResultNumber radius() const {
334 if (auto cr = centerAndRadius()) {
335 return static_cast<ResultNumber>(cr->second);
336 }
337
338 if constexpr (!requires(ResultNumber v) { std::sqrt(v); }) {
339 throw std::runtime_error("std::sqrt is not available for the requested ResultNumber type");
340 } else {
341 return std::sqrt(squaredRadius<ResultNumber>());
342 }
343 }
344
348 constexpr bool isDegenerate() const {
349 return orientationSign(a(), b(), c()) == std::partial_ordering::equivalent;
350 }
351
360 [[nodiscard]] constexpr bool isPoint() const {
361 return a() == b() && b() == c();
362 }
363
372 [[nodiscard]] constexpr std::optional<PointType> getIfPoint() const {
373 if (!isPoint()) {
374 return std::nullopt;
375 }
376 return a();
377 }
378
391 [[nodiscard]] constexpr bool isUndefined() const {
392 return !isPoint() && isDegenerate();
393 }
394
401 template <class ResultNumber = division_result_t<NumberType>>
402 [[nodiscard]] constexpr ResultNumber squaredRadius() const {
403 if (auto cr = centerAndRadius()) {
404 return detail::asNumber<ResultNumber>(cr->second) * detail::asNumber<ResultNumber>(cr->second);
405 }
406
407 if (isDegenerate()) {
408 return ResultNumber{};
409 }
410
411 // Circumradius formula:
412 // R^2 = |AB|^2 |BC|^2 |CA|^2 / (4 * det(A,B,C)^2),
413 // where det(A,B,C) is twice the signed area of triangle ABC
414 const ResultNumber ab2 = a().template squaredDistance<ResultNumber>(b());
415 const ResultNumber bc2 = b().template squaredDistance<ResultNumber>(c());
416 const ResultNumber ca2 = c().template squaredDistance<ResultNumber>(a());
417 const ResultNumber determinant = static_cast<ResultNumber>(orientationDeterminant(a(), b(), c()));
418 const ResultNumber four = static_cast<ResultNumber>(4);
419
420 return (ab2 * bc2 * ca2) / (four * determinant * determinant);
421 }
422
423 // /**
424 // * @brief Returns the squared radius in this disk's exact result type.
425 // *
426 // * Exact for integral coordinates, where the result is
427 // * `Rational<promoted NumberType>`; for floating-point coordinates it is the
428 // * promoted floating-point type.
429 // */
430 // [[nodiscard]] constexpr auto squaredRadius() const {
431 // using ResultNumber = std::conditional_t<
432 // detail::extended_integral<NumberType>,
433 // Rational<detail::promoted_number_t<NumberType>>,
434 // detail::promoted_number_t<NumberType>>;
435 // return squaredRadius<ResultNumber>();
436 // }
437
443 template <std::floating_point ResultNumber = double>
444 [[nodiscard]] constexpr ResultNumber area() const {
445 return std::numbers::pi_v<ResultNumber> * squaredRadius<ResultNumber>();
446 }
447
457 [[nodiscard]] constexpr Rectangle<PointType> bbox() const {
458 // Exact when built from a center and radius: center +/- (radius, radius).
459 if (auto cr = centerAndRadius()) {
460 const auto radius = cr->second;
461 return Rectangle<PointType>(cr->first - PointType(radius, radius),
462 cr->first + PointType(radius, radius));
463 }
464
465 // Degenerate disk (collinear boundary points): no finite circle, so the
466 // bounding box of the three boundary points contains it.
467 if (isDegenerate()) {
468 const auto lo = [](NumberType u, NumberType v, NumberType w) { return u < v ? (u < w ? u : w) : (v < w ? v : w); };
469 const auto hi = [](NumberType u, NumberType v, NumberType w) { return u > v ? (u > w ? u : w) : (v > w ? v : w); };
471 PointType(lo(a().x(), b().x(), c().x()), lo(a().y(), b().y(), c().y())),
472 PointType(hi(a().x(), b().x(), c().x()), hi(a().y(), b().y(), c().y())));
473 }
474
475 // General case: the circumcenter is the rational point (nx/d, ny/d) and
476 // the radius is sqrt(s)/d, where d = 2*det(A,B,C) > 0 and
477 // s = |AB|^2 |BC|^2 |CA|^2 = (radius*d)^2. The box spans
478 // [cx +/- r] x [cy +/- r]; how it is rounded depends on the coordinate
479 // type, but the result always contains the disk (and may be larger).
480 if constexpr (std::floating_point<NumberType>) {
481 // Real square root is available: center +/- radius, tight up to
482 // floating-point rounding.
483 const NumberType r = radius<NumberType>();
484 const auto ctr = center<NumberType>();
485 return Rectangle<PointType>(ctr - PointType(r, r), ctr + PointType(r, r));
486 } else {
487 // The circumcentre numerators are degree three in the coordinates,
488 // and the radius bound below multiplies three side lengths, so a
489 // single promotion overflows well inside the coordinate type's own
490 // range — an `int` disk spanning a few million already lost its box.
491 // Promote twice for an integral coordinate, as @ref inCircleDeterminant
492 // does, which puts every `int` input safely inside the intermediate.
493 // A rational coordinate promotes once: its storage grows as needed.
494 using Wide = std::conditional_t<
495 detail::extended_integral<NumberType>,
496 detail::promoted_number_t<detail::promoted_number_t<NumberType>>,
497 detail::promoted_number_t<NumberType>>;
498 const Wide ax = a().x(), ay = a().y();
499 const Wide bx = b().x(), by = b().y();
500 const Wide cx = c().x(), cy = c().y();
501 const Wide aa = ax * ax + ay * ay;
502 const Wide bb = bx * bx + by * by;
503 const Wide cc = cx * cx + cy * cy;
504
505 Wide d = Wide{2} * (ax * (by - cy) + bx * (cy - ay) + cx * (ay - by));
506 Wide nx = aa * (by - cy) + bb * (cy - ay) + cc * (ay - by);
507 Wide ny = aa * (cx - bx) + bb * (ax - cx) + cc * (bx - ax);
508 if (d < Wide{0}) { // normalize to d > 0
509 d = -d; nx = -nx; ny = -ny;
510 }
511
512 const Wide ab2 = (ax - bx) * (ax - bx) + (ay - by) * (ay - by);
513 const Wide bc2 = (bx - cx) * (bx - cx) + (by - cy) * (by - cy);
514 const Wide ca2 = (cx - ax) * (cx - ax) + (cy - ay) * (cy - ay);
515 // ceil(sqrt(n)) for a non-negative *integer* n: floor-sqrt (std::sqrt
516 // when usable, else integer Newton) followed by an upward correction.
517 // The argument is always an integer, so this terminates.
518 const auto ceilIntSqrt = [](auto n) {
519 using Int = decltype(n);
520 Int r{};
521 if constexpr (requires { std::sqrt(n); }) {
522 r = static_cast<Int>(std::sqrt(n));
523 } else if (n >= Int{2}) {
524 Int x = n, y = (n + Int{1}) / Int{2};
525 while (y < x) { x = y; y = (x + n / x) / Int{2}; }
526 r = x;
527 } else {
528 r = n;
529 }
530 while (r * r < n) { ++r; }
531 return r;
532 };
533
534 if constexpr (pgl::is_Rational_v<Wide>) {
535 // sqrt(s) = sqrt(sn*sd)/sd <= ceil(sqrt(sn*sd))/sd =: u, an exact
536 // rational upper bound whose only square root is over the integer
537 // sn*sd -- so it never iterates on the (irrational) sqrt itself.
538 // Reduced once up front: both parts are wanted, and it also keeps
539 // the integer square root below off a needlessly wide sn*sd.
540 const Wide s = (ab2 * bc2 * ca2).simplified(); // (radius * d)^2
541 using Int = std::remove_cvref_t<decltype(s.numerator())>;
542 const Int sn = s.numerator();
543 const Int sd = s.denominator();
544 const Wide u(ceilIntSqrt(sn * sd), sd); // u >= sqrt(s)
546 PointType(static_cast<NumberType>((nx - u) / d),
547 static_cast<NumberType>((ny - u) / d)),
548 PointType(static_cast<NumberType>((nx + u) / d),
549 static_cast<NumberType>((ny + u) / d)));
550 } else {
551 // Integer coordinates: round (nx +/- q)/d outward to integers,
552 // with q >= radius*d = sqrt(ab2*bc2*ca2).
553 //
554 // Bound each factor's root separately rather than forming that
555 // product: it is degree six in the coordinates, so it overflows
556 // a fixed-width Wide at coordinates around a thousand — where
557 // the box quietly stopped containing its disk. Each ceil-sqrt is
558 // at least the real root, so their product is at least the root
559 // of the product, which is all the radius needs; every
560 // intermediate stays as wide as a single squared distance. The
561 // box remains the outer bound promised above, wider by under one
562 // unit per factor.
563 const Wide q = ceilIntSqrt(ab2) * ceilIntSqrt(bc2) * ceilIntSqrt(ca2);
564 const auto floorDiv = [](Wide p, Wide den) { // den > 0
565 return p >= Wide{0} ? p / den : -((-p + den - Wide{1}) / den);
566 };
567 const auto ceilDiv = [](Wide p, Wide den) { // den > 0
568 return p >= Wide{0} ? (p + den - Wide{1}) / den : -((-p) / den);
569 };
571 PointType(static_cast<NumberType>(floorDiv(nx - q, d)),
572 static_cast<NumberType>(floorDiv(ny - q, d))),
573 PointType(static_cast<NumberType>(ceilDiv(nx + q, d)),
574 static_cast<NumberType>(ceilDiv(ny + q, d))));
575 }
576 }
577 }
578
595 template <class ResultNumber = grid_number_t<typename PointType_::NumberType>>
596 requires(detail::extended_integral<ResultNumber> || std::same_as<ResultNumber, BigInt>)
599
609 template <std::floating_point ResultNumber = double>
610 [[nodiscard]] constexpr Rectangle<Point<ResultNumber>> fbox() const {
611 const ResultNumber r = radius<ResultNumber>();
612 const auto center_point = center<ResultNumber>();
613 const ResultNumber cx = center_point.x();
614 const ResultNumber cy = center_point.y();
616 Point<ResultNumber>(cx - r, cy - r),
617 Point<ResultNumber>(cx + r, cy + r));
618 }
619
629 template <class ResultNumber = division_result_t<NumberType>>
630 [[nodiscard]] constexpr Point<ResultNumber, PointLabelType> pointInside() const {
631 const ResultNumber two = static_cast<ResultNumber>(2);
633 (detail::asNumber<ResultNumber>(a().x()) + detail::asNumber<ResultNumber>(b().x())) / two,
634 (detail::asNumber<ResultNumber>(a().y()) + detail::asNumber<ResultNumber>(b().y())) / two,
636 }
637
648 template <class ResultNumber = division_result_t<NumberType>>
649 [[nodiscard]] constexpr Segment<Point<ResultNumber, PointLabelType>> diameter() const {
650 using ResultPoint = Point<ResultNumber, PointLabelType>;
651
652 if (auto cr = centerAndRadius()) {
653 return Segment<ResultPoint>(a(),b());
654 }
655
656 if (isDegenerate()) {
657 return Segment<ResultPoint>();
658 }
659
660 const ResultPoint center_point = center<ResultNumber>();
661 ResultPoint anti_a = center_point + (center_point-a());
662 return Segment<ResultPoint>(static_cast<ResultPoint>(a()), anti_a);
663 }
664
677 template <class ResultNumber = double, PointConcept OtherPoint>
678 [[nodiscard]] detail::floating_result_t<ResultNumber> squaredDistance(const OtherPoint& point) const;
679
693 template <class ResultNumber = double, SegmentConcept OtherSegment>
694 [[nodiscard]] detail::floating_result_t<ResultNumber> squaredDistance(const OtherSegment& other) const;
695
697 template <class ResultNumber = double, OrientedSegmentConcept OtherOrientedSegment>
698 [[nodiscard]] detail::floating_result_t<ResultNumber> squaredDistance(const OtherOrientedSegment& other) const;
699
701 template <class ResultNumber = double, LineConcept OtherLine>
702 [[nodiscard]] detail::floating_result_t<ResultNumber> squaredDistance(const OtherLine& other) const;
703
705 template <class ResultNumber = double, OrientedLineConcept OtherOrientedLine>
706 [[nodiscard]] detail::floating_result_t<ResultNumber> squaredDistance(const OtherOrientedLine& other) const;
707
709 template <class ResultNumber = double, RayConcept OtherRay>
710 [[nodiscard]] detail::floating_result_t<ResultNumber> squaredDistance(const OtherRay& other) const;
711
713 template <class ResultNumber = double, HalfplaneConcept OtherHalfplane>
714 [[nodiscard]] detail::floating_result_t<ResultNumber> squaredDistance(const OtherHalfplane& other) const;
715
717 template <class ResultNumber = double, RectangleConcept OtherRectangle>
718 [[nodiscard]] detail::floating_result_t<ResultNumber> squaredDistance(const OtherRectangle& other) const;
719
721 template <class ResultNumber = double, TriangleConcept OtherTriangle>
722 [[nodiscard]] detail::floating_result_t<ResultNumber> squaredDistance(const OtherTriangle& other) const;
723
733 template <class ResultNumber = double, DiskConcept OtherDisk>
734 [[nodiscard]] detail::floating_result_t<ResultNumber> squaredDistance(const OtherDisk& other) const;
735
743 template <class ResultNumber = double, typename OtherShape>
744 requires (!PointConcept<OtherShape> && detail::shapeRank<OtherShape> > detail::shapeRank<Disk>
745 && requires(const OtherShape& o, const Disk& self) { o.squaredDistance(self); })
746 [[nodiscard]] detail::floating_result_t<ResultNumber> squaredDistance(const OtherShape& other) const {
747 return other.template squaredDistance<ResultNumber>(*this);
748 }
749
760 template <class ResultNumber = double, PointConcept OtherPoint>
761 [[nodiscard]] detail::floating_result_t<ResultNumber> distanceL1(const OtherPoint& point) const;
762
768 template <class ResultNumber = double, PointConcept OtherPoint>
769 [[nodiscard]] detail::floating_result_t<ResultNumber> distanceLInf(const OtherPoint& point) const;
770
786 template <class ResultNumber = division_result_t<NumberType>, PointConcept OtherPoint>
787 [[nodiscard]] constexpr auto intersection(const Shape<OtherPoint>& other) const {
788 return other.template intersection<ResultNumber>(*this);
789 }
790
801 template <class ResultNumber = double, PointConcept OtherPoint>
802 [[nodiscard]] detail::floating_result_t<ResultNumber>
803 distanceL1(const Shape<OtherPoint>& other) const {
804 using FloatingResult = detail::floating_result_t<ResultNumber>;
805 return other.template distanceL1<FloatingResult>(*this);
806 }
807
809 template <class ResultNumber = double, PointConcept OtherPoint>
810 [[nodiscard]] detail::floating_result_t<ResultNumber>
811 distanceLInf(const Shape<OtherPoint>& other) const {
812 using FloatingResult = detail::floating_result_t<ResultNumber>;
813 return other.template distanceLInf<FloatingResult>(*this);
814 }
815
826 template <PointConcept OtherPoint>
827 [[nodiscard]] constexpr bool contains(const OtherPoint& other) const;
828
837 template <class ResultNumber = NumberType, PointConcept OtherPoint>
838 [[nodiscard]] constexpr std::optional<Point<ResultNumber, typename PointType::LabelType>>
839 intersection(const OtherPoint& other) const;
840
842 template <class ResultNumber = NumberType, class EmptyPoint>
843 [[nodiscard]] constexpr EmptyShape<EmptyPoint> intersection(const EmptyShape<EmptyPoint>&) const {
844 return {};
845 }
846
848 template <SegmentConcept OtherSegment>
849 [[nodiscard]] constexpr bool contains(const OtherSegment& other) const;
850
852 template <OrientedSegmentConcept OtherOrientedSegment>
853 [[nodiscard]] constexpr bool contains(const OtherOrientedSegment& other) const;
854
856 template <LineConcept OtherLine>
857 [[nodiscard]] constexpr bool contains(const OtherLine& other) const;
858
860 template <OrientedLineConcept OtherOrientedLine>
861 [[nodiscard]] constexpr bool contains(const OtherOrientedLine& other) const;
862
864 template <RayConcept OtherRay>
865 [[nodiscard]] constexpr bool contains(const OtherRay& other) const;
866
868 template <HalfplaneConcept OtherHalfplane>
869 [[nodiscard]] constexpr bool contains(const OtherHalfplane& other) const;
870
872 template <TriangleConcept OtherTriangle>
873 [[nodiscard]] constexpr bool contains(const OtherTriangle& other) const;
874
876 template <RectangleConcept OtherRectangle>
877 [[nodiscard]] constexpr bool contains(const OtherRectangle& other) const;
878
880 template <ConvexConcept OtherConvex>
881 [[nodiscard]] constexpr bool contains(const OtherConvex& other) const;
882
884 template<PolygonConcept OtherPolygon>
885 [[nodiscard]] constexpr bool contains(const OtherPolygon& other) const;
886
888 template <DiskConcept OtherDisk>
889 [[nodiscard]] constexpr bool contains(const OtherDisk& other) const;
890
892 [[nodiscard]] constexpr bool contains(const Shape<PointType>& other) const;
893
894 // The empty set is a subset of every shape, so its containment relations are
895 // true; the symmetric intersection/crossing predicates reach the empty set
896 // through Disk's existing generic OtherShape fallbacks.
898 template <class EmptyPoint>
899 [[nodiscard]] constexpr bool contains(const EmptyShape<EmptyPoint>&) const {
900 return true;
901 }
902
903 template <class EmptyPoint>
904 [[nodiscard]] constexpr bool boundaryContains(const EmptyShape<EmptyPoint>&) const {
905 return true;
906 }
907
908 template <class EmptyPoint>
909 [[nodiscard]] constexpr bool interiorContains(const EmptyShape<EmptyPoint>&) const {
910 return true;
911 }
912
920 template <PointConcept OtherPoint>
921 [[nodiscard]] constexpr bool interiorContains(const OtherPoint& other) const;
922
924 template <SegmentConcept OtherSegment>
925 [[nodiscard]] constexpr bool interiorContains(const OtherSegment& other) const;
926
928 template <OrientedSegmentConcept OtherOrientedSegment>
929 [[nodiscard]] constexpr bool interiorContains(const OtherOrientedSegment& other) const;
930
932 template <LineConcept OtherLine>
933 [[nodiscard]] constexpr bool interiorContains(const OtherLine& other) const;
934
936 template <OrientedLineConcept OtherOrientedLine>
937 [[nodiscard]] constexpr bool interiorContains(const OtherOrientedLine& other) const;
938
940 template <RayConcept OtherRay>
941 [[nodiscard]] constexpr bool interiorContains(const OtherRay& other) const;
942
944 template <HalfplaneConcept OtherHalfplane>
945 [[nodiscard]] constexpr bool interiorContains(const OtherHalfplane& other) const;
946
948 template <TriangleConcept OtherTriangle>
949 [[nodiscard]] constexpr bool interiorContains(const OtherTriangle& other) const;
950
952 template <RectangleConcept OtherRectangle>
953 [[nodiscard]] constexpr bool interiorContains(const OtherRectangle& other) const;
954
956 template <ConvexConcept OtherConvex>
957 [[nodiscard]] constexpr bool interiorContains(const OtherConvex& other) const;
958
960 template <DiskConcept OtherDisk>
961 [[nodiscard]] constexpr bool interiorContains(const OtherDisk& other) const;
962
966 template <SegmentConcept OtherSegment>
967 [[nodiscard]] constexpr bool intersects(const OtherSegment& other) const;
968
975 template <DiskConcept OtherDisk>
976 [[nodiscard]] constexpr bool intersects(const OtherDisk& other) const;
977
987 template <PointConcept OtherPoint>
988 [[nodiscard]] constexpr bool boundaryContains(const OtherPoint& other) const;
989
991 template <SegmentConcept OtherSegment>
992 [[nodiscard]] constexpr bool boundaryContains(const OtherSegment& other) const;
993
995 template <OrientedSegmentConcept OtherOrientedSegment>
996 [[nodiscard]] constexpr bool boundaryContains(const OtherOrientedSegment& other) const;
997
999 template <LineConcept OtherLine>
1000 [[nodiscard]] constexpr bool boundaryContains(const OtherLine& other) const;
1001
1003 template <OrientedLineConcept OtherOrientedLine>
1004 [[nodiscard]] constexpr bool boundaryContains(const OtherOrientedLine& other) const;
1005
1007 template <RayConcept OtherRay>
1008 [[nodiscard]] constexpr bool boundaryContains(const OtherRay& other) const;
1009
1011 template <HalfplaneConcept OtherHalfplane>
1012 [[nodiscard]] constexpr bool boundaryContains(const OtherHalfplane& other) const;
1013
1015 template <TriangleConcept OtherTriangle>
1016 [[nodiscard]] constexpr bool boundaryContains(const OtherTriangle& other) const;
1017
1019 template <RectangleConcept OtherRectangle>
1020 [[nodiscard]] constexpr bool boundaryContains(const OtherRectangle& other) const;
1021
1023 template <ConvexConcept OtherConvex>
1024 [[nodiscard]] constexpr bool boundaryContains(const OtherConvex& other) const;
1025
1027 template<PolygonConcept OtherPolygon>
1028 [[nodiscard]] constexpr bool boundaryContains(const OtherPolygon& other) const;
1029
1031 template <DiskConcept OtherDisk>
1032 [[nodiscard]] constexpr bool boundaryContains(const OtherDisk& other) const;
1033
1035 [[nodiscard]] constexpr bool boundaryContains(const Shape<PointType>& other) const;
1036
1037 // --- not-yet-implemented predicate pairs (throw); see implementation ---
1039 template<PolygonConcept OtherPolygon>
1040 [[nodiscard]] constexpr bool interiorContains(const OtherPolygon& other) const;
1041
1043 template<PolygonConcept OtherPolygon>
1044 [[nodiscard]] constexpr bool separates(const OtherPolygon& other) const;
1045
1047 template<MonotoneChainConcept OtherChain>
1048 [[nodiscard]] constexpr bool contains(const OtherChain& other) const;
1049
1051 template<MonotoneChainConcept OtherChain>
1052 [[nodiscard]] constexpr bool boundaryContains(const OtherChain& other) const;
1053
1055 template<MonotoneChainConcept OtherChain>
1056 [[nodiscard]] constexpr bool interiorContains(const OtherChain& other) const;
1057
1059 template<MonotoneChainConcept OtherChain>
1060 [[nodiscard]] constexpr bool separates(const OtherChain& other) const;
1061
1063 template<PolylineConcept OtherPolyline>
1064 [[nodiscard]] constexpr bool contains(const OtherPolyline& other) const;
1065
1067 template<PolylineConcept OtherPolyline>
1068 [[nodiscard]] constexpr bool boundaryContains(const OtherPolyline& other) const;
1069
1071 template<PolylineConcept OtherPolyline>
1072 [[nodiscard]] constexpr bool interiorContains(const OtherPolyline& other) const;
1073
1075 template<PolylineConcept OtherPolyline>
1076 [[nodiscard]] constexpr bool separates(const OtherPolyline& other) const;
1077
1079 template<HalfplaneIntersectionConcept OtherRegion>
1080 [[nodiscard]] constexpr bool contains(const OtherRegion& other) const;
1081
1083 template<HalfplaneIntersectionConcept OtherRegion>
1084 [[nodiscard]] constexpr bool boundaryContains(const OtherRegion& other) const;
1085
1087 template<HalfplaneIntersectionConcept OtherRegion>
1088 [[nodiscard]] constexpr bool interiorContains(const OtherRegion& other) const;
1089
1091 template<HalfplaneIntersectionConcept OtherRegion>
1092 [[nodiscard]] constexpr bool separates(const OtherRegion& other) const;
1093
1101 template<PolygonWithHolesConcept OtherRegion>
1102 [[nodiscard]] constexpr bool contains(const OtherRegion& other) const;
1103
1110 template<PolygonWithHolesConcept OtherRegion>
1111 [[nodiscard]] constexpr bool boundaryContains(const OtherRegion& other) const;
1112
1114 template<PolygonWithHolesConcept OtherRegion>
1115 [[nodiscard]] constexpr bool interiorContains(const OtherRegion& other) const;
1116
1126 template<PolygonWithHolesConcept OtherRegion>
1127 [[nodiscard]] bool separates(const OtherRegion& other) const;
1128
1129 // -------------------------------------------------------------------------
1130 // A set of regions
1131 //
1132 // It outranks every other shape, so the symmetric relations reach it through
1133 // the rank-based forwarders and only the asymmetric ones are answered here.
1134 // A set is the union of its components, so it is contained exactly when
1135 // every component is — no matter what this shape is.
1136
1138 template<PolygonSetConcept OtherSet>
1139 [[nodiscard]] constexpr bool contains(const OtherSet& other) const {
1140 for (const auto& component : other) {
1141 if (!contains(component)) {
1142 return false;
1143 }
1144 }
1145 return true;
1146 }
1147
1149 template<PolygonSetConcept OtherSet>
1150 [[nodiscard]] constexpr bool boundaryContains(const OtherSet& other) const {
1151 for (const auto& component : other) {
1152 if (!boundaryContains(component)) {
1153 return false;
1154 }
1155 }
1156 return true;
1157 }
1158
1160 template<PolygonSetConcept OtherSet>
1161 [[nodiscard]] constexpr bool interiorContains(const OtherSet& other) const {
1162 for (const auto& component : other) {
1163 if (!interiorContains(component)) {
1164 return false;
1165 }
1166 }
1167 return true;
1168 }
1169
1178 template<PolygonSetConcept OtherSet>
1179 [[nodiscard]] bool separates(const OtherSet& other) const;
1180
1181
1183 template<PointConcept OtherPoint>
1184 [[nodiscard]] constexpr bool separates(const OtherPoint& other) const;
1185
1189 template <SegmentConcept OtherSegment>
1190 [[nodiscard]] constexpr bool separates(const OtherSegment& other) const;
1191
1193 template <OrientedSegmentConcept OtherOrientedSegment>
1194 [[nodiscard]] constexpr bool separates(const OtherOrientedSegment& other) const;
1195
1197 template <LineConcept OtherLine>
1198 [[nodiscard]] constexpr bool separates(const OtherLine& other) const;
1199
1201 template <OrientedLineConcept OtherOrientedLine>
1202 [[nodiscard]] constexpr bool separates(const OtherOrientedLine& other) const;
1203
1205 template <ConvexConcept OtherConvex>
1206 [[nodiscard]] constexpr bool separates(const OtherConvex& other) const;
1207
1209 template<RayConcept OtherRay>
1210 [[nodiscard]] constexpr bool separates(const OtherRay& other) const;
1211
1213 template<HalfplaneConcept OtherHalfplane>
1214 [[nodiscard]] constexpr bool separates(const OtherHalfplane& other) const;
1215
1217 template<RectangleConcept OtherRectangle>
1218 [[nodiscard]] constexpr bool separates(const OtherRectangle& other) const;
1219
1221 template<TriangleConcept OtherTriangle>
1222 [[nodiscard]] constexpr bool separates(const OtherTriangle& other) const;
1223
1225 template<DiskConcept OtherDisk>
1226 [[nodiscard]] constexpr bool separates(const OtherDisk& other) const;
1227
1228 // --- Symmetric predicate dispatch: intersects / interiorsIntersect / crosses ---
1229 // For a symmetric predicate a.method(b) == b.method(a). The canonical
1230 // implementor of each pair is the shape that appears later in pgl.hpp; the
1231 // earlier shape forwards to it. Disk is therefore canonical against every
1232 // shape up to and including Disk, and forwards to Convex/Polygon (which come
1233 // later). Pairs whose disk-side geometry is not yet implemented throw, in the
1234 // style of the other "not implemented yet" stubs.
1235
1237 template<PointConcept OtherPoint>
1238 [[nodiscard]] constexpr bool intersects(const OtherPoint& other) const;
1240 template<OrientedSegmentConcept OtherOrientedSegment>
1241 [[nodiscard]] constexpr bool intersects(const OtherOrientedSegment& other) const;
1243 template<LineConcept OtherLine>
1244 [[nodiscard]] constexpr bool intersects(const OtherLine& other) const;
1246 template<OrientedLineConcept OtherOrientedLine>
1247 [[nodiscard]] constexpr bool intersects(const OtherOrientedLine& other) const;
1249 template<RayConcept OtherRay>
1250 [[nodiscard]] constexpr bool intersects(const OtherRay& other) const;
1252 template<HalfplaneConcept OtherHalfplane>
1253 [[nodiscard]] constexpr bool intersects(const OtherHalfplane& other) const;
1255 template<RectangleConcept OtherRectangle>
1256 [[nodiscard]] constexpr bool intersects(const OtherRectangle& other) const;
1258 template<TriangleConcept OtherTriangle>
1259 [[nodiscard]] constexpr bool intersects(const OtherTriangle& other) const;
1260
1262 template<PointConcept OtherPoint>
1263 [[nodiscard]] constexpr bool interiorsIntersect(const OtherPoint& other) const;
1265 template<SegmentConcept OtherSegment>
1266 [[nodiscard]] constexpr bool interiorsIntersect(const OtherSegment& other) const;
1268 template<OrientedSegmentConcept OtherOrientedSegment>
1269 [[nodiscard]] constexpr bool interiorsIntersect(const OtherOrientedSegment& other) const;
1271 template<LineConcept OtherLine>
1272 [[nodiscard]] constexpr bool interiorsIntersect(const OtherLine& other) const;
1274 template<OrientedLineConcept OtherOrientedLine>
1275 [[nodiscard]] constexpr bool interiorsIntersect(const OtherOrientedLine& other) const;
1277 template<RayConcept OtherRay>
1278 [[nodiscard]] constexpr bool interiorsIntersect(const OtherRay& other) const;
1280 template<HalfplaneConcept OtherHalfplane>
1281 [[nodiscard]] constexpr bool interiorsIntersect(const OtherHalfplane& other) const;
1283 template<RectangleConcept OtherRectangle>
1284 [[nodiscard]] constexpr bool interiorsIntersect(const OtherRectangle& other) const;
1286 template<TriangleConcept OtherTriangle>
1287 [[nodiscard]] constexpr bool interiorsIntersect(const OtherTriangle& other) const;
1289 template<DiskConcept OtherDisk>
1290 [[nodiscard]] constexpr bool interiorsIntersect(const OtherDisk& other) const;
1291
1293 template<PointConcept OtherPoint>
1294 [[nodiscard]] constexpr bool crosses(const OtherPoint& other) const;
1296 template<SegmentConcept OtherSegment>
1297 [[nodiscard]] constexpr bool crosses(const OtherSegment& other) const;
1299 template<OrientedSegmentConcept OtherOrientedSegment>
1300 [[nodiscard]] constexpr bool crosses(const OtherOrientedSegment& other) const;
1302 template<LineConcept OtherLine>
1303 [[nodiscard]] constexpr bool crosses(const OtherLine& other) const;
1305 template<OrientedLineConcept OtherOrientedLine>
1306 [[nodiscard]] constexpr bool crosses(const OtherOrientedLine& other) const;
1308 template<RayConcept OtherRay>
1309 [[nodiscard]] constexpr bool crosses(const OtherRay& other) const;
1311 template<HalfplaneConcept OtherHalfplane>
1312 [[nodiscard]] constexpr bool crosses(const OtherHalfplane& other) const;
1314 template<RectangleConcept OtherRectangle>
1315 [[nodiscard]] constexpr bool crosses(const OtherRectangle& other) const;
1317 template<TriangleConcept OtherTriangle>
1318 [[nodiscard]] constexpr bool crosses(const OtherTriangle& other) const;
1320 template<DiskConcept OtherDisk>
1321 [[nodiscard]] constexpr bool crosses(const OtherDisk& other) const;
1322
1324 template<PointConcept OtherPoint>
1325 [[nodiscard]] constexpr bool intersects(const Shape<OtherPoint>& other) const;
1327 template<PointConcept OtherPoint>
1328 [[nodiscard]] constexpr bool interiorsIntersect(const Shape<OtherPoint>& other) const;
1330 template<PointConcept OtherPoint>
1331 [[nodiscard]] constexpr bool crosses(const Shape<OtherPoint>& other) const;
1332
1334 template<typename OtherShape>
1335 requires (!PointConcept<OtherShape> && detail::shapeRank<OtherShape> > detail::shapeRank<Disk>)
1336 [[nodiscard]] constexpr bool intersects(const OtherShape& other) const {
1337 return other.intersects(*this);
1338 }
1339
1341 template <class EmptyPoint>
1342 [[nodiscard]] constexpr bool intersects(const EmptyShape<EmptyPoint>&) const {
1343 return false;
1344 }
1345
1346 template<typename OtherShape>
1347 requires (!PointConcept<OtherShape> && detail::shapeRank<OtherShape> > detail::shapeRank<Disk>)
1348 [[nodiscard]] constexpr bool interiorsIntersect(const OtherShape& other) const {
1349 return other.interiorsIntersect(*this);
1350 }
1351
1353 template <class EmptyPoint>
1354 [[nodiscard]] constexpr bool interiorsIntersect(const EmptyShape<EmptyPoint>&) const {
1355 return false;
1356 }
1357
1358 template<typename OtherShape>
1359 requires (!PointConcept<OtherShape> && detail::shapeRank<OtherShape> > detail::shapeRank<Disk>)
1360 [[nodiscard]] constexpr bool crosses(const OtherShape& other) const {
1361 return other.crosses(*this);
1362 }
1363
1365 template <class EmptyPoint>
1366 [[nodiscard]] constexpr bool crosses(const EmptyShape<EmptyPoint>&) const {
1367 return false;
1368 }
1369
1375 template <class Scalar>
1376 requires(!detail::is_point_v<Scalar> && !TransformationConcept<Scalar>)
1377 constexpr Disk& operator/=(const Scalar& scalar) {
1378 for (auto& point : points_) {
1379 point /= scalar;
1380 }
1381 points_ = canonicalizePoints(points_[0], points_[1], points_[2]);
1382 return *this;
1383 }
1384
1391 constexpr bool operator==(const Disk& other) const {
1392 // Degenerate == non-degenerate: false
1393 // Degenerate == degenerate with same points: true
1394 // Degenerate == degenerate with different points: false
1395 if (isDegenerate() || other.isDegenerate()) {
1396 if (isDegenerate() != other.isDegenerate()) {
1397 return false;
1398 }
1399
1400 return a() == other.a() &&
1401 b() == other.b() &&
1402 c() == other.c();
1403 }
1404
1405 // For true circles, three non-collinear boundary points define the
1406 // circle uniquely. So the other disk is the same if its three stored points lies on the disk boundary.
1407 return inCircleSign(a(), b(), c(), other.a()) == std::partial_ordering::equivalent &&
1408 inCircleSign(a(), b(), c(), other.b()) == std::partial_ordering::equivalent &&
1409 inCircleSign(a(), b(), c(), other.c()) == std::partial_ordering::equivalent;
1410 }
1411
1413 template<AnyShapeConcept OtherShape>
1414 [[nodiscard]] constexpr bool samePointSet(const OtherShape& other) const;
1415
1432 constexpr std::partial_ordering operator<=>(const Disk& other) const {
1433 // Keep degenerate disks in a separate ordering class from true circles.
1434 if (isDegenerate() != other.isDegenerate()) {
1435 return isDegenerate() ? std::partial_ordering::less : std::partial_ordering::greater;
1436 }
1437
1438 // Order true circles from smaller to larger, then by center.
1439 if (!isDegenerate()) {
1440 using ExactNumber = division_result_t<NumberType>;
1441 const auto radius_order = pgl::detail::threeWay(squaredRadius<ExactNumber>(),
1442 other.template squaredRadius<ExactNumber>());
1443 if (radius_order != 0) {
1444 return radius_order;
1445 }
1446 return center<ExactNumber>() <=> other.template center<ExactNumber>();
1447 }
1448
1449 // Degenerate disks fall back to their canonical point representation.
1450 const auto first_point_order = a() <=> other.a();
1451 if (first_point_order != 0) {
1452 return first_point_order;
1453 }
1454
1455 const auto second_point_order = b() <=> other.b();
1456 if (second_point_order != 0) {
1457 return second_point_order;
1458 }
1459
1460 return c() <=> other.c();
1461 }
1462
1469 [[nodiscard]] constexpr Disk rotated90(int k = 1) const;
1470
1476 constexpr void rotate90(int k = 1);
1477
1491 template <class OtherShape>
1493 [[nodiscard]] constexpr auto minkowskiSum(const OtherShape& other) const;
1494
1517 template <class OtherShape>
1519 [[nodiscard]] constexpr auto minkowskiErosion(const OtherShape& other) const;
1520
1546 template <class ResultNumber = double, DiskConcept OtherDisk>
1547 [[nodiscard]] std::optional<Disk<Point<ResultNumber, PointLabelType>>>
1548 minkowskiErosion(const OtherDisk& other) const;
1549
1564 template <class ResultNumber = double, HalfplaneConcept OtherHalfplane>
1566 minkowskiErosion(const OtherHalfplane& other) const;
1567
1598 template <class ResultNumber = double, DiskConcept OtherDisk>
1600 minkowskiSum(const OtherDisk& other) const;
1601
1611 template <class ResultNumber = double, HalfplaneConcept OtherHalfplane>
1613 minkowskiSum(const OtherHalfplane& other) const;
1614
1619 template <PointConcept OtherPoint>
1620 constexpr Disk& operator+=(const OtherPoint& translation) {
1621 for (auto& point : points_) {
1622 point += translation;
1623 }
1624 return *this;
1625 }
1626
1631 template <PointConcept OtherPoint>
1632 constexpr Disk& operator-=(const OtherPoint& translation) {
1633 for (auto& point : points_) {
1634 point -= translation;
1635 }
1636 return *this;
1637 }
1638
1644 template <class Scalar>
1645 requires(!detail::is_point_v<Scalar> && !TransformationConcept<Scalar>)
1646 constexpr Disk& operator*=(const Scalar& scalar) {
1647 for (auto& point : points_) {
1648 point *= scalar;
1649 }
1650 points_ = canonicalizePoints(points_[0], points_[1], points_[2]);
1651 return *this;
1652 }
1653
1658 public:
1659 using iterator_category = std::forward_iterator_tag;
1660 using iterator_concept = std::forward_iterator_tag;
1662 using difference_type = std::ptrdiff_t;
1663 using reference = const PointType&;
1664
1666 constexpr PointIterator() = default;
1667
1669 constexpr reference operator*() const {
1670 assert(disk != nullptr);
1671 return (*disk)[index];
1672 }
1673
1676 ++index;
1677 return *this;
1678 }
1679
1681 constexpr PointIterator operator++(int) {
1682 PointIterator copy(*this);
1683 ++(*this);
1684 return copy;
1685 }
1686
1688 constexpr bool operator==(const PointIterator& other) const = default;
1689
1690 private:
1691 friend struct Disk;
1692
1694 constexpr PointIterator(const Disk* disk_arg, std::size_t index_arg)
1695 : disk(disk_arg), index(index_arg) {}
1696
1697 const Disk* disk = nullptr;
1698 std::size_t index = 0;
1699 };
1700
1713 template <class OtherShape>
1714 [[nodiscard]] constexpr bool pointInsideInteriorContainedIn(const OtherShape& shape) const {
1715 const auto p = pointInside<NumberType>();
1716 if (interiorContains(p)) {
1717 return shape.interiorContains(p);
1718 }
1719 return (shape * 2).interiorContains((*this * 2).template pointInside<NumberType>());
1720 }
1721
1722 private:
1730 static constexpr std::array<PointType, 3> canonicalizePoints(PointType first, PointType second, PointType third) {
1731 std::array<PointType, 3> points{
1732 std::move(first),
1733 std::move(second),
1734 std::move(third),
1735 };
1736
1737 // Sort the three stored boundary points lexicographically
1738 if (points[1] < points[0]) {
1739 std::swap(points[0], points[1]);
1740 }
1741 if (points[2] < points[1]) {
1742 std::swap(points[1], points[2]);
1743 }
1744 if (points[1] < points[0]) {
1745 std::swap(points[0], points[1]);
1746 }
1747
1748 // Keep non-degenerate disks in counterclockwise order
1749 if (orientationSign(points[0], points[1], points[2]) == std::partial_ordering::less) {
1750 std::swap(points[1], points[2]);
1751 }
1752
1753 return points;
1754 }
1755
1760 [[nodiscard]] constexpr std::optional<std::pair<PointType, NumberType>> centerAndRadius() const {
1761 if (a().y() == b().y()) {
1762 NumberType r = c().y() - a().y();
1763 NumberType center_x = a().x() + r;
1764 if (r >= 0 && b().x() == center_x + r && c().x() == center_x) {
1765 return std::make_pair(PointType(center_x, a().y()), r);
1766 }
1767 }
1768 return std::nullopt;
1769 }
1770
1771 std::array<PointType, 3> points_{};
1772 [[no_unique_address]] mutable LabelType label_{};
1773};
1774
1776
1778
1780template <class PointType, class LabelType, class TranslationNumber, class TranslationLabel>
1782 auto result = disk;
1783 result -= translation;
1784 if constexpr (detail::has_label_v<LabelType>) {
1785 result.label() = LabelType{};
1786 }
1787 return result;
1788}
1789
1791template <class PointType, class LabelType, class Scalar>
1792 requires(!detail::is_point_v<Scalar> && !TransformationConcept<Scalar>)
1793constexpr auto operator*(const Disk<PointType, LabelType>& disk, const Scalar& scalar) {
1794 auto result = disk;
1795 result *= scalar;
1796 if constexpr (detail::has_label_v<LabelType>) {
1797 result.label() = LabelType{};
1798 }
1799 return result;
1800}
1801
1803template <class Scalar, class PointType, class LabelType>
1804 requires(!detail::is_point_v<Scalar> && !TransformationConcept<Scalar>)
1805constexpr auto operator*(const Scalar& scalar, const Disk<PointType, LabelType>& disk) {
1806 return disk * scalar;
1807}
1808
1810template <class PointType, class LabelType, class Scalar>
1811 requires(!detail::is_point_v<Scalar> && !TransformationConcept<Scalar>)
1812constexpr auto operator/(const Disk<PointType, LabelType>& disk, const Scalar& scalar) {
1813 auto result = disk;
1814 result /= scalar;
1815 if constexpr (detail::has_label_v<LabelType>) {
1816 result.label() = LabelType{};
1817 }
1818 return result;
1819}
1820
1822template <class PointType, class LabelType>
1823std::ostream& operator<<(std::ostream& stream, const Disk<PointType, LabelType>& disk);
1824
1825} // namespace pgl
friend struct Disk
Deduces a default disk with Point<> boundary points and no label.
Definition disk.hpp:1691
constexpr bool operator==(const PointIterator &other) const =default
Returns whether both iterators refer to the same position.
const PointType & reference
Definition disk.hpp:1663
constexpr PointIterator()=default
Creates a singular (past-the-end style) iterator.
constexpr PointIterator & operator++()
Advances to the next boundary point (pre-increment).
Definition disk.hpp:1675
std::forward_iterator_tag iterator_concept
Definition disk.hpp:1660
constexpr PointIterator operator++(int)
Advances to the next boundary point (post-increment).
Definition disk.hpp:1681
std::ptrdiff_t difference_type
Definition disk.hpp:1662
std::forward_iterator_tag iterator_category
Definition disk.hpp:1659
constexpr reference operator*() const
Returns the boundary point at the current position.
Definition disk.hpp:1669
PointType value_type
Definition disk.hpp:1661
Shape pairs whose Minkowski sum Pangolin can represent.
Definition forward.hpp:476
Definition forward.hpp:306
Definition forward.hpp:324
Definition arrangement.hpp:67
constexpr std::partial_ordering inCircleSign(const Point< ANumber, ALabel > &a, const Point< BNumber, BLabel > &b, const Point< CNumber, CLabel > &c, const Point< DNumber, DLabel > &d)
Classifies a point with respect to the circumcircle of three others.
Definition orientation.hpp:894
@ y
Definition intervaltree.hpp:24
@ x
Definition intervaltree.hpp:24
constexpr bool is_Rational_v
Definition rational.hpp:37
typename DivisionResult< Number >::type division_result_t
Convenience alias for DivisionResult.
Definition rational.hpp:1175
Point() -> Point< int >
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
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 >
constexpr auto orientationDeterminant(const Point< ANumber, ALabel > &a, const Point< BNumber, BLabel > &b, const Point< CNumber, CLabel > &c)
Returns the signed orientation determinant of three points.
Definition orientation.hpp:518
Disk() -> Disk< Point<>, NoLabel >
Deduces a default disk with Point<> boundary points and no label.
Definition disk.hpp:1691
Closed Euclidean disk stored by boundary points plus optional disk label.
Definition disk.hpp:66
constexpr ResultNumber squaredRadius() const
Definition disk.hpp:402
constexpr bool boundaryContains(const OtherPoint &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:489
constexpr Point< ResultNumber, PointLabelType > center() const
Definition disk.hpp:284
constexpr bool boundaryContains(const OtherDisk &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:620
constexpr bool interiorContains(const OtherTriangle &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1149
constexpr bool intersects(const OtherSegment &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:904
constexpr bool interiorsIntersect(const OtherLine &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:1464
constexpr bool contains(const EmptyShape< EmptyPoint > &) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition disk.hpp:899
constexpr bool interiorsIntersect(const OtherSegment &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:1409
constexpr Disk rotated90(int k=1) const
Returns the disk rotated by 90k degrees around the origin.
Definition transformations.hpp:2183
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines exactly the same point set.
Definition samepointset.hpp:1995
constexpr bool crosses(const OtherTriangle &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:784
constexpr std::optional< PointType > getIfPoint() const
Returns the point the disk collapses to, if it does.
Definition disk.hpp:372
constexpr bool intersects(const OtherLine &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1194
constexpr bool interiorContains(const OtherOrientedSegment &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1119
constexpr bool boundaryContains(const OtherRegion &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1726
constexpr bool contains(const OtherLine &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1041
constexpr bool boundaryContains(const OtherPolygon &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1014
constexpr bool boundaryContains(const OtherLine &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:526
constexpr bool interiorContains(const OtherLine &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1125
constexpr bool boundaryContains(const EmptyShape< EmptyPoint > &) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition disk.hpp:904
constexpr bool isDegenerate() const
Returns whether the three boundary points are collinear.
Definition disk.hpp:348
constexpr bool intersects(const OtherShape &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition disk.hpp:1336
constexpr const PointType & c() const
Definition disk.hpp:244
constexpr bool crosses(const OtherSegment &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:738
constexpr bool pointInsideInteriorContainedIn(const OtherShape &shape) const
Tests whether some point strictly inside this disk lies in the strict interior of shape.
Definition disk.hpp:1714
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 disk.hpp:787
constexpr const PointType & operator[](std::size_t index) const
Returns boundary point index in canonical order.
Definition disk.hpp:191
Disk< Point< ResultNumber, PointLabelType > > minkowskiSum(const OtherDisk &other) const
Returns the Minkowski sum of the two disks (A ⊕ B), a disk.
constexpr bool separates(const OtherPolyline &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4006
constexpr bool separates(const OtherPoint &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:1712
constexpr bool boundaryContains(const OtherRegion &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
constexpr bool intersects(const OtherOrientedLine &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1228
constexpr bool boundaryContains(const OtherSegment &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:502
detail::floating_result_t< ResultNumber > squaredDistance(const OtherOrientedSegment &other) const
Returns the squared Euclidean distance from this disk to a shape.
Definition distance.hpp:1223
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1182
constexpr bool boundaryContains(const OtherOrientedLine &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:538
constexpr bool separates(const OtherTriangle &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:1826
constexpr bool crosses(const OtherPoint &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:732
constexpr bool contains(const OtherOrientedLine &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1047
constexpr bool interiorContains(const OtherOrientedLine &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1131
constexpr bool crosses(const OtherRectangle &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:774
constexpr bool contains(const OtherPoint &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1015
constexpr auto end() const
Returns an iterator past the last boundary point.
Definition disk.hpp:265
constexpr bool interiorContains(const OtherPoint &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1107
detail::floating_result_t< ResultNumber > squaredDistance(const OtherSegment &other) const
Returns the squared Euclidean distance from this disk to a shape.
Definition distance.hpp:1212
constexpr bool intersects(const EmptyShape< EmptyPoint > &) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition disk.hpp:1342
constexpr bool crosses(const OtherHalfplane &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:768
constexpr bool contains(const OtherHalfplane &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1059
constexpr Disk(PointType first, PointType second, PointType third)
Creates the disk through three boundary points.
Definition disk.hpp:85
constexpr bool contains(const OtherPolyline &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2448
constexpr Disk & operator=(const Disk< OtherPointType, OtherLabelType > &other)
Assigns from a disk with compatible point and label types.
Definition disk.hpp:167
constexpr bool interiorsIntersect(const Shape< OtherPoint > &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:1610
detail::floating_result_t< ResultNumber > squaredDistance(const OtherShape &other) const
Returns the squared Euclidean distance to the given shape.
Definition disk.hpp:746
constexpr bool contains(const OtherRegion &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2834
constexpr auto cend() const
Returns a const iterator past the last boundary point.
Definition disk.hpp:272
constexpr bool interiorContains(const EmptyShape< EmptyPoint > &) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition disk.hpp:909
constexpr bool contains(const OtherRectangle &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1071
constexpr bool intersects(const OtherTriangle &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1301
bool separates(const OtherSet &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:6008
detail::floating_result_t< ResultNumber > distanceLInf(const OtherPoint &point) const
Returns the Chebyshev (LInf) distance from this disk to a point.
Definition distancelinf.hpp:191
std::vector< Point< ResultNumber, typename PointType::LabelType > > latticePoints() const
Returns the integer points the disk contains.
Definition lattice.hpp:594
detail::floating_result_t< ResultNumber > squaredDistance(const OtherPoint &point) const
Returns the squared Euclidean distance from this disk to a point.
Definition distance.hpp:1194
Halfplane< Point< ResultNumber, PointLabelType > > minkowskiSum(const OtherHalfplane &other) const
Returns the Minkowski sum of this disk and a half-plane (A ⊕ B), a half-plane.
detail::floating_result_t< ResultNumber > squaredDistance(const OtherHalfplane &other) const
Returns the squared Euclidean distance from this disk to a shape.
Definition distance.hpp:1267
constexpr bool interiorContains(const OtherChain &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1529
constexpr ResultNumber radius() const
Definition disk.hpp:333
detail::floating_result_t< ResultNumber > squaredDistance(const OtherRectangle &other) const
Returns the squared Euclidean distance from this disk to a shape.
Definition distance.hpp:1278
constexpr bool separates(const OtherConvex &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:1748
constexpr bool interiorsIntersect(const OtherRay &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:1497
constexpr Disk & operator-=(const OtherPoint &translation)
Translates the disk by -translation in place.
Definition disk.hpp:1632
constexpr bool operator==(const Disk &other) const
Returns whether two disks describe the same closed region.
Definition disk.hpp:1391
constexpr bool boundaryContains(const OtherOrientedSegment &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:514
constexpr bool boundaryContains(const OtherConvex &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:607
constexpr bool interiorsIntersect(const OtherTriangle &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:1569
constexpr bool contains(const OtherConvex &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1083
constexpr bool interiorsIntersect(const OtherOrientedLine &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:1491
constexpr Disk(PointType center, NumberType radius)
Creates a disk from its center and radius.
Definition disk.hpp:111
constexpr bool boundaryContains(const Shape< PointType > &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:638
constexpr Point< ResultNumber, PointLabelType > pointInside() const
Returns the midpoint of the first two boundary points.
Definition disk.hpp:630
constexpr bool interiorsIntersect(const OtherPoint &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:1402
constexpr bool intersects(const Shape< OtherPoint > &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1317
constexpr bool boundaryContains(const OtherTriangle &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:574
constexpr bool intersects(const OtherOrientedSegment &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1188
constexpr bool crosses(const OtherLine &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:750
constexpr bool crosses(const OtherRay &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:762
constexpr bool boundaryContains(const OtherRectangle &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:588
constexpr Disk()=default
Creates a disk with all three boundary points at the origin.
constexpr Rectangle< PointType > bbox() const
Returns an axis-aligned bounding box in the coordinate type.
Definition disk.hpp:457
constexpr bool interiorsIntersect(const OtherShape &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition disk.hpp:1348
constexpr auto minkowskiSum(const OtherShape &other) const
Returns the Minkowski sum of this shape and another (A ⊕ B).
Definition minkowski.hpp:802
constexpr bool contains(const OtherChain &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:2086
constexpr Disk(PointType first, PointType second, PointType third, A &&label)
Creates a disk from three boundary points and stores a label.
Definition disk.hpp:97
detail::floating_result_t< ResultNumber > distanceL1(const OtherPoint &point) const
Returns the Manhattan (L1) distance from this disk to a point.
Definition distancel1.hpp:203
detail::floating_result_t< ResultNumber > distanceLInf(const Shape< OtherPoint > &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition disk.hpp:811
constexpr void rotate90(int k=1)
Rotates the disk by 90k degrees around the origin in place.
Definition transformations.hpp:2188
constexpr Disk(PointType center, NumberType radius, A &&label)
Same as above, and stores a disk label.
Definition disk.hpp:128
constexpr EmptyShape< EmptyPoint > intersection(const EmptyShape< EmptyPoint > &) const
Returns the intersection of the two shapes (A ∩ B), empty when they are disjoint.
Definition disk.hpp:843
static constexpr std::size_t size()
Returns the number of stored boundary points (always 3).
Definition disk.hpp:199
constexpr bool separates(const OtherSegment &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:1718
constexpr bool intersects(const OtherRectangle &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1281
constexpr bool interiorsIntersect(const OtherHalfplane &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:1537
detail::floating_result_t< ResultNumber > squaredDistance(const OtherTriangle &other) const
Returns the squared Euclidean distance from this disk to a shape.
Definition distance.hpp:1289
constexpr bool interiorContains(const OtherDisk &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1179
detail::floating_result_t< ResultNumber > squaredDistance(const OtherOrientedLine &other) const
Returns the squared Euclidean distance from this disk to a shape.
Definition distance.hpp:1245
constexpr bool interiorContains(const OtherRay &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1137
constexpr bool separates(const OtherRay &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:1792
constexpr bool interiorContains(const OtherRegion &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
constexpr ResultNumber area() const
Returns the area pi * R^2 of the closed disk.
Definition disk.hpp:444
constexpr bool separates(const OtherOrientedSegment &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:1727
constexpr bool contains(const OtherDisk &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1094
constexpr bool separates(const OtherRegion &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:4658
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:2421
constexpr const PointType & a() const
Definition disk.hpp:228
constexpr bool separates(const OtherDisk &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:1843
constexpr auto begin() const
Returns an iterator to the first boundary point.
Definition disk.hpp:251
constexpr bool interiorContains(const OtherConvex &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1168
constexpr bool interiorsIntersect(const OtherRectangle &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:1547
detail::floating_result_t< ResultNumber > squaredDistance(const OtherLine &other) const
Returns the squared Euclidean distance from this disk to a shape.
Definition distance.hpp:1234
constexpr bool interiorContains(const OtherRegion &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:2131
constexpr std::ptrdiff_t index(const PointType &point) const
Definition disk.hpp:216
constexpr bool contains(const OtherRay &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1053
constexpr Disk & operator+=(const OtherPoint &translation)
Translates the disk by translation in place.
Definition disk.hpp:1620
constexpr bool interiorContains(const OtherPolyline &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1755
constexpr bool contains(const OtherOrientedSegment &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1035
constexpr std::partial_ordering operator<=>(const Disk &other) const
Orders disks by increasing squared radius, then by center.
Definition disk.hpp:1432
constexpr bool separates(const OtherRectangle &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:1804
constexpr bool boundaryContains(const OtherRay &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:550
constexpr bool contains(const OtherRegion &other) const
Tests whether this shape contains the other shape (A ⊇ B).
constexpr bool contains(const OtherPolygon &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1804
detail::floating_result_t< ResultNumber > distanceL1(const Shape< OtherPoint > &other) const
Returns the Manhattan (L1) distance to the given shape.
Definition disk.hpp:803
constexpr bool interiorsIntersect(const OtherDisk &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:1587
constexpr bool interiorContains(const OtherRectangle &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1155
constexpr bool isUndefined() const
Returns whether the disk is degenerate without collapsing to a point.
Definition disk.hpp:391
constexpr bool contains(const OtherSegment &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1029
constexpr Disk(NumberType x, NumberType y, NumberType radius)
Creates a disk from center coordinates and a radius.
Definition disk.hpp:136
bool separates(const OtherRegion &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:5759
constexpr bool boundaryContains(const OtherChain &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1213
constexpr bool intersects(const OtherDisk &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:954
constexpr bool contains(const Shape< PointType > &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1121
constexpr auto cbegin() const
Returns a const iterator to the first boundary point.
Definition disk.hpp:258
constexpr bool intersects(const OtherRay &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1234
EmptyShape< Point< ResultNumber, PointLabelType > > minkowskiErosion(const OtherHalfplane &other) const
Returns the Minkowski erosion of this disk by a half-plane (A ⊖ B), which is empty.
constexpr Segment< Point< ResultNumber, PointLabelType > > diameter() const
Returns a segment defining a diameter of the disk.
Definition disk.hpp:649
constexpr bool crosses(const OtherDisk &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:790
constexpr bool interiorContains(const OtherHalfplane &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1143
constexpr bool crosses(const OtherShape &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition disk.hpp:1360
detail::floating_result_t< ResultNumber > squaredDistance(const OtherRay &other) const
Returns the squared Euclidean distance from this disk to a shape.
Definition distance.hpp:1256
constexpr bool boundaryContains(const OtherSet &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition disk.hpp:1150
constexpr bool contains(const OtherSet &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition disk.hpp:1139
constexpr Disk(NumberType x, NumberType y, NumberType radius, A &&label)
Same as above, and stores a disk label.
Definition disk.hpp:142
constexpr bool separates(const OtherOrientedLine &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:1742
constexpr bool boundaryContains(const OtherPolyline &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:1322
constexpr bool separates(const OtherPolygon &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:2294
constexpr bool interiorContains(const OtherSet &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition disk.hpp:1161
constexpr Disk(const Disk< OtherPointType, OtherLabelType > &other)
Converts a disk with a different point and/or label type.
Definition disk.hpp:154
constexpr bool crosses(const OtherOrientedSegment &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:744
constexpr bool isPoint() const
Returns whether the disk collapses to a single point.
Definition disk.hpp:360
constexpr bool contains(const OtherTriangle &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1065
constexpr bool crosses(const OtherOrientedLine &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:756
detail::floating_result_t< ResultNumber > squaredDistance(const OtherDisk &other) const
Returns the squared Euclidean distance between two disks.
Definition distance.hpp:1300
constexpr bool interiorsIntersect(const EmptyShape< EmptyPoint > &) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition disk.hpp:1354
constexpr const PointType & b() const
Definition disk.hpp:235
constexpr bool separates(const OtherHalfplane &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:1798
constexpr bool separates(const OtherLine &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:1733
constexpr bool interiorsIntersect(const OtherOrientedSegment &other) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition interiorsintersect.hpp:1458
constexpr bool crosses(const Shape< OtherPoint > &other) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition crosses.hpp:796
constexpr bool separates(const OtherChain &other) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition separates.hpp:3201
constexpr bool interiorContains(const OtherSegment &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1113
Point< typename min_disk_input_point_t< Container >::NumberType > PointType
Definition disk.hpp:67
std::optional< Disk< Point< ResultNumber, PointLabelType > > > minkowskiErosion(const OtherDisk &other) const
Returns the Minkowski erosion of this disk by another (A ⊖ B), a disk when there is one.
constexpr bool intersects(const OtherHalfplane &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1275
constexpr bool crosses(const EmptyShape< EmptyPoint > &) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition disk.hpp:1366
constexpr bool interiorContains(const OtherPolygon &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1334
constexpr bool boundaryContains(const OtherHalfplane &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition boundarycontains.hpp:562
constexpr auto minkowskiErosion(const OtherShape &other) const
Returns the Minkowski erosion of this shape by another (A ⊖ B).
Definition minkowskierosion.hpp:635
constexpr const 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 disk.hpp:207
constexpr Rectangle< Point< ResultNumber > > fbox() const
Returns a floating-point bounding box of the disk.
Definition disk.hpp:610
The empty set of points in the plane.
Definition emptyshape.hpp:33
Closed half-plane defined by an oriented boundary line.
Definition halfplane.hpp:51
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
TLabel LabelType
Definition point.hpp:133
TNumber NumberType
Definition point.hpp:131
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
Public declaration of pgl::Triangle.