Pangolin
Header-only C++20 plane computational geometry library
Loading...
Searching...
No Matches
distancelinf.hpp
Go to the documentation of this file.
1#pragma once
2
4
16
17namespace pgl {
18
19namespace detail {
20
37template <class ResultNumber>
38constexpr ResultNumber segmentLikeDistanceLInf(const Point<ResultNumber>& a, const Point<ResultNumber>& b,
39 const Point<ResultNumber>& q, bool boundedLow, bool boundedHigh) {
40 const ResultNumber dx = b.x() - a.x();
41 const ResultNumber dy = b.y() - a.y();
42 const ResultNumber px = q.x() - a.x();
43 const ResultNumber py = q.y() - a.y();
44
45 if (dx == 0 && dy == 0) {
46 const ResultNumber ax = pgl::detail::abs(px);
47 const ResultNumber ay = pgl::detail::abs(py);
48 return ax > ay ? ax : ay;
49 }
50
51 bool haveBest = false;
52 ResultNumber best{};
53 const auto consider = [&](const ResultNumber& value) {
54 if (!haveBest || value < best) {
55 best = value;
56 haveBest = true;
57 }
58 };
59
60 if (boundedLow) {
61 const ResultNumber ax = pgl::detail::abs(px);
62 const ResultNumber ay = pgl::detail::abs(py);
63 consider(ax > ay ? ax : ay);
64 }
65 if (boundedHigh) {
66 const ResultNumber ax = pgl::detail::abs(px - dx);
67 const ResultNumber ay = pgl::detail::abs(py - dy);
68 consider(ax > ay ? ax : ay);
69 }
70
71 const ResultNumber cross = dx * py - dy * px;
72 const auto considerCrossing = [&](const ResultNumber& n, const ResultNumber& d) {
73 if (d == 0) {
74 return;
75 }
76 // The low bound rejects t = n/d < 0, i.e. n and d of opposite signs.
77 // Read off the two signs rather than forming n*d: for an exact rational
78 // the product is a multiplication plus a normalization, while comparing
79 // against the literal 0 is the sign of a numerator. d is nonzero here,
80 // so d > 0 splits the cases exhaustively, and n == 0 correctly fails
81 // both branches.
82 if (boundedLow && (d > 0 ? n < 0 : n > 0)) {
83 return;
84 }
85 if (boundedHigh && n * d > d * d) {
86 return;
87 }
88 consider(pgl::detail::abs(cross) / pgl::detail::abs(d));
89 };
90 considerCrossing(px, dx);
91 considerCrossing(py, dy);
92 considerCrossing(px - py, dx - dy);
93 considerCrossing(px + py, dx + dy);
94
95 return best;
96}
97
107template <class ResultNumber, class Self, class OtherShape>
108constexpr ResultNumber maxVertexDistanceLInf(const Self& self, const OtherShape& other) {
109 const auto self_vertices = self.vertices();
110 const auto distanceToVertex = [&other](const auto& vertex) -> ResultNumber {
111 return other.template distanceLInf<ResultNumber>(vertex);
112 };
113 ResultNumber worst = distanceToVertex(self_vertices[0]);
114 for (std::size_t index = 1; index < self_vertices.size(); ++index) {
115 const ResultNumber current = distanceToVertex(self_vertices[index]);
116 if (worst < current) {
117 worst = current;
118 }
119 }
120 return worst;
121}
122
130template <class Float = double>
131Float diskPointDistanceLInf(Float a, Float b, Float r) {
132 const auto h = [&](Float theta) {
133 return std::max(std::abs(a + r * std::cos(theta)), std::abs(b + r * std::sin(theta)));
134 };
135
136 constexpr int coarseSteps = 720;
137 Float bestTheta{0};
138 Float bestValue = h(Float{0});
139 for (int i = 1; i < coarseSteps; ++i) {
140 const Float theta = Float{2} * std::numbers::pi_v<Float> * i / coarseSteps;
141 const Float value = h(theta);
142 if (value < bestValue) {
143 bestValue = value;
144 bestTheta = theta;
145 }
146 }
147
148 const Float step = Float{2} * std::numbers::pi_v<Float> / coarseSteps;
149 Float lo = bestTheta - step;
150 Float hi = bestTheta + step;
151 constexpr Float invPhi = 0.6180339887498949;
152 Float c1 = hi - invPhi * (hi - lo);
153 Float c2 = lo + invPhi * (hi - lo);
154 Float hc1 = h(c1);
155 Float hc2 = h(c2);
156 for (int i = 0; i < 100; ++i) {
157 if (hc1 < hc2) {
158 hi = c2;
159 c2 = c1;
160 hc2 = hc1;
161 c1 = hi - invPhi * (hi - lo);
162 hc1 = h(c1);
163 } else {
164 lo = c1;
165 c1 = c2;
166 hc1 = hc2;
167 c2 = lo + invPhi * (hi - lo);
168 hc2 = h(c2);
169 }
170 }
171
172 return std::min({bestValue, hc1, hc2});
173}
174
175} // namespace detail
176
177// -----------------------------------------------------------------------------
178// Point
179
180template <class Number, class Label>
181template <class ResultNumber, PointConcept OtherPoint>
182constexpr auto Point<Number, Label>::hausdorffDistanceLInf(const OtherPoint& other) const {
183 return this->template distanceLInf<ResultNumber>(other);
184}
185
186// -----------------------------------------------------------------------------
187// Disk
188
189template <class PointType_, class TLabel>
190template <class ResultNumber, PointConcept OtherPoint>
191detail::floating_result_t<ResultNumber> Disk<PointType_, TLabel>::distanceLInf(
192 const OtherPoint& point) const {
193 using Float = detail::floating_result_t<ResultNumber>;
194 if (contains(point)) {
195 return Float{0};
196 }
197 const Float a = center<Float>().x() - static_cast<Float>(point.x());
198 const Float b = center<Float>().y() - static_cast<Float>(point.y());
199 return detail::diskPointDistanceLInf(a, b, radius<Float>());
200}
201
202// -----------------------------------------------------------------------------
203// Segment
204
205template <class PointType, class LabelType>
206template <class ResultNumber, PointConcept OtherPoint>
207constexpr auto Segment<PointType, LabelType>::distanceLInf(const OtherPoint& point) const {
208 return detail::segmentLikeDistanceLInf<ResultNumber>(
210}
211
212template <class PointType, class LabelType>
213template <class ResultNumber, SegmentConcept OtherSegment>
214constexpr auto Segment<PointType, LabelType>::distanceLInf(const OtherSegment& other) const {
215 if (intersects(other)) {
216 return ResultNumber{};
217 }
218
219 const auto this_min_to_other = other.template distanceLInf<ResultNumber>(min());
220 const auto this_max_to_other = other.template distanceLInf<ResultNumber>(max());
221 const auto other_min_to_this = this->template distanceLInf<ResultNumber>(other.min());
222 const auto other_max_to_this = this->template distanceLInf<ResultNumber>(other.max());
223
224 const auto best_from_this = this_min_to_other < this_max_to_other ? this_min_to_other : this_max_to_other;
225 const auto best_from_other = other_min_to_this < other_max_to_this ? other_min_to_this : other_max_to_this;
226
227 return best_from_this < best_from_other ? best_from_this : best_from_other;
228}
229
230// -----------------------------------------------------------------------------
231// OrientedSegment
232
233template <class PointType, class LabelType>
234template <class ResultNumber, PointConcept OtherPoint>
235constexpr auto OrientedSegment<PointType, LabelType>::distanceLInf(const OtherPoint& point) const {
236 return static_cast<Segment<PointType>>(*this).template distanceLInf<ResultNumber>(point);
237}
238
239template <class PointType, class LabelType>
240template <class ResultNumber, SegmentConcept OtherSegment>
241constexpr auto OrientedSegment<PointType, LabelType>::distanceLInf(const OtherSegment& other) const {
242 return static_cast<Segment<PointType>>(*this).template distanceLInf<ResultNumber>(other);
243}
244
245template <class PointType, class LabelType>
246template <class ResultNumber, OrientedSegmentConcept OtherOrientedSegment>
247constexpr auto OrientedSegment<PointType, LabelType>::distanceLInf(const OtherOrientedSegment& other) const {
248 return static_cast<Segment<PointType>>(*this).template distanceLInf<ResultNumber>(
250}
251
252// -----------------------------------------------------------------------------
253// Line
254
255template <class PointType, class LabelType>
256template <class ResultNumber, PointConcept OtherPoint>
257constexpr auto Line<PointType, LabelType>::distanceLInf(const OtherPoint& point) const {
258 return detail::segmentLikeDistanceLInf<ResultNumber>(
260}
261
262template <class PointType, class LabelType>
263template <class ResultNumber, LineConcept OtherLine>
264constexpr auto Line<PointType, LabelType>::distanceLInf(const OtherLine& other) const {
265 if (intersects(other)) {
266 return ResultNumber{};
267 }
268 return other.template distanceLInf<ResultNumber>(min());
269}
270
271template <class PointType, class LabelType>
272template <class ResultNumber, SegmentConcept OtherSegment>
273constexpr auto Line<PointType, LabelType>::distanceLInf(const OtherSegment& other) const {
274 if (intersects(other)) {
275 return ResultNumber{};
276 }
277
278 const auto source_distance = this->template distanceLInf<ResultNumber>(other.min());
279 const auto target_distance = this->template distanceLInf<ResultNumber>(other.max());
280 return source_distance < target_distance ? source_distance : target_distance;
281}
282
283template <class PointType, class LabelType>
284template <class ResultNumber, OrientedSegmentConcept OtherOrientedSegment>
285constexpr auto Line<PointType, LabelType>::distanceLInf(const OtherOrientedSegment& other) const {
286 return this->template distanceLInf<ResultNumber>(static_cast<Segment<typename OtherOrientedSegment::PointType>>(other));
287}
288
289// -----------------------------------------------------------------------------
290// OrientedLine
291
292template <class PointType, class LabelType>
293template <class ResultNumber, PointConcept OtherPoint>
294constexpr auto OrientedLine<PointType, LabelType>::distanceLInf(const OtherPoint& point) const {
295 return this->asLine().template distanceLInf<ResultNumber>(point);
296}
297
298template <class PointType, class LabelType>
299template <class ResultNumber, LineConcept OtherLine>
300constexpr auto OrientedLine<PointType, LabelType>::distanceLInf(const OtherLine& other) const {
301 return this->asLine().template distanceLInf<ResultNumber>(other);
302}
303
304template <class PointType, class LabelType>
305template <class ResultNumber, OrientedLineConcept OtherOrientedLine>
306constexpr auto OrientedLine<PointType, LabelType>::distanceLInf(const OtherOrientedLine& other) const {
307 return this->asLine().template distanceLInf<ResultNumber>(other.asLine());
308}
309
310template <class PointType, class LabelType>
311template <class ResultNumber, SegmentConcept OtherSegment>
312constexpr auto OrientedLine<PointType, LabelType>::distanceLInf(const OtherSegment& other) const {
313 return this->asLine().template distanceLInf<ResultNumber>(other);
314}
315
316template <class PointType, class LabelType>
317template <class ResultNumber, OrientedSegmentConcept OtherOrientedSegment>
318constexpr auto OrientedLine<PointType, LabelType>::distanceLInf(const OtherOrientedSegment& other) const {
319 return this->asLine().template distanceLInf<ResultNumber>(other);
320}
321
322// -----------------------------------------------------------------------------
323// Ray
324
325template <class PointType, class LabelType>
326template <class ResultNumber, PointConcept OtherPoint>
327constexpr auto Ray<PointType, LabelType>::distanceLInf(const OtherPoint& point) const {
328 return detail::segmentLikeDistanceLInf<ResultNumber>(
330}
331
332template <class PointType, class LabelType>
333template <class ResultNumber, LineConcept OtherLine>
334constexpr auto Ray<PointType, LabelType>::distanceLInf(const OtherLine& other) const {
335 if (intersects(other)) {
336 return ResultNumber{};
337 }
338 return other.template distanceLInf<ResultNumber>(source());
339}
340
341template <class PointType, class LabelType>
342template <class ResultNumber, OrientedLineConcept OtherOrientedLine>
343constexpr auto Ray<PointType, LabelType>::distanceLInf(const OtherOrientedLine& other) const {
344 if (intersects(other)) {
345 return ResultNumber{};
346 }
347 return other.template distanceLInf<ResultNumber>(source());
348}
349
350template <class PointType, class LabelType>
351template <class ResultNumber, SegmentConcept OtherSegment>
352constexpr auto Ray<PointType, LabelType>::distanceLInf(const OtherSegment& other) const {
353 if (intersects(other)) {
354 return ResultNumber{};
355 }
356
357 const auto source_to_other = other.template distanceLInf<ResultNumber>(source());
358 const auto other_min_to_this = this->template distanceLInf<ResultNumber>(other.min());
359 const auto other_max_to_this = this->template distanceLInf<ResultNumber>(other.max());
360 const auto best_from_segment = other_min_to_this < other_max_to_this ? other_min_to_this : other_max_to_this;
361 return source_to_other < best_from_segment ? source_to_other : best_from_segment;
362}
363
364template <class PointType, class LabelType>
365template <class ResultNumber, OrientedSegmentConcept OtherOrientedSegment>
366constexpr auto Ray<PointType, LabelType>::distanceLInf(const OtherOrientedSegment& other) const {
367 if (intersects(other)) {
368 return ResultNumber{};
369 }
370
371 const auto source_to_other = other.template distanceLInf<ResultNumber>(source());
372 const auto other_source_to_this = this->template distanceLInf<ResultNumber>(other.source());
373 const auto other_target_to_this = this->template distanceLInf<ResultNumber>(other.target());
374 const auto best_from_segment = other_source_to_this < other_target_to_this ? other_source_to_this : other_target_to_this;
375 return source_to_other < best_from_segment ? source_to_other : best_from_segment;
376}
377
378template <class PointType, class LabelType>
379template <class ResultNumber, RayConcept OtherRay>
380constexpr auto Ray<PointType, LabelType>::distanceLInf(const OtherRay& other) const {
381 if (intersects(other)) {
382 return ResultNumber{};
383 }
384
385 const auto this_source_to_other = other.template distanceLInf<ResultNumber>(source());
386 const auto other_source_to_this = this->template distanceLInf<ResultNumber>(other.source());
387 return this_source_to_other < other_source_to_this ? this_source_to_other : other_source_to_this;
388}
389
390// -----------------------------------------------------------------------------
391// Halfplane
392
393template <class PointType, class LabelType>
394template <class ResultNumber, PointConcept OtherPoint>
395constexpr auto Halfplane<PointType, LabelType>::distanceLInf(const OtherPoint& point) const {
396 if (intersects(point)) {
397 return ResultNumber{};
398 }
399 return asLine().template distanceLInf<ResultNumber>(point);
400}
401
402template <class PointType, class LabelType>
403template <class ResultNumber, SegmentConcept OtherSegment>
404constexpr auto Halfplane<PointType, LabelType>::distanceLInf(const OtherSegment& other) const {
405 if (intersects(other)) {
406 return ResultNumber{};
407 }
408 return asLine().template distanceLInf<ResultNumber>(other);
409}
410
411template <class PointType, class LabelType>
412template <class ResultNumber, OrientedSegmentConcept OtherOrientedSegment>
413constexpr auto Halfplane<PointType, LabelType>::distanceLInf(const OtherOrientedSegment& other) const {
414 if (intersects(other)) {
415 return ResultNumber{};
416 }
417 return asLine().template distanceLInf<ResultNumber>(other);
418}
419
420template <class PointType, class LabelType>
421template <class ResultNumber, LineConcept OtherLine>
422constexpr auto Halfplane<PointType, LabelType>::distanceLInf(const OtherLine& other) const {
423 if (intersects(other)) {
424 return ResultNumber{};
425 }
426 return asLine().template distanceLInf<ResultNumber>(other);
427}
428
429template <class PointType, class LabelType>
430template <class ResultNumber, OrientedLineConcept OtherOrientedLine>
431constexpr auto Halfplane<PointType, LabelType>::distanceLInf(const OtherOrientedLine& other) const {
432 if (intersects(other)) {
433 return ResultNumber{};
434 }
435 return asLine().template distanceLInf<ResultNumber>(other);
436}
437
438template <class PointType, class LabelType>
439template <class ResultNumber, RayConcept OtherRay>
440constexpr auto Halfplane<PointType, LabelType>::distanceLInf(const OtherRay& other) const {
441 if (intersects(other)) {
442 return ResultNumber{};
443 }
444 return asLine().template distanceLInf<ResultNumber>(other);
445}
446
447template <class PointType, class LabelType>
448template <class ResultNumber, HalfplaneConcept OtherHalfplane>
449constexpr auto Halfplane<PointType, LabelType>::distanceLInf(const OtherHalfplane& other) const {
450 if (intersects(other)) {
451 return ResultNumber{};
452 }
453 return asLine().template distanceLInf<ResultNumber>(other.asLine());
454}
455
456// -----------------------------------------------------------------------------
457// Rectangle
458
459template <class PointType, class LabelType>
460template <class ResultNumber, PointConcept OtherPoint>
461constexpr auto Rectangle<PointType, LabelType>::distanceLInf(const OtherPoint& point) const {
462 // There is no nearest point of the empty set, so it has no distance to
463 // anything; asking for one is a precondition violation.
464 assert(!empty());
465 const ResultNumber dx = static_cast<ResultNumber>(axisDistance(min().x(), max().x(), point.x(), point.x()));
466 const ResultNumber dy = static_cast<ResultNumber>(axisDistance(min().y(), max().y(), point.y(), point.y()));
467 return dx > dy ? dx : dy;
468}
469
470template <class PointType, class LabelType>
471template <class ResultNumber, LineConcept OtherLine>
472constexpr auto Rectangle<PointType, LabelType>::distanceLInf(const OtherLine& other) const {
473 // There is no nearest point of the empty set, so it has no distance to
474 // anything; asking for one is a precondition violation.
475 assert(!empty());
476 if (intersects(other)) {
477 return ResultNumber{};
478 }
479
480 const auto rectangle_vertices = vertices();
481 auto best_distance = other.template distanceLInf<ResultNumber>(rectangle_vertices[0]);
482 for (std::size_t index = 1; index < rectangle_vertices.size(); ++index) {
483 const auto current_distance = other.template distanceLInf<ResultNumber>(rectangle_vertices[index]);
484 if (current_distance < best_distance) {
485 best_distance = current_distance;
486 }
487 }
488
489 return best_distance;
490}
491
492template <class PointType, class LabelType>
493template <class ResultNumber, OrientedLineConcept OtherOrientedLine>
494constexpr auto Rectangle<PointType, LabelType>::distanceLInf(const OtherOrientedLine& other) const {
495 // There is no nearest point of the empty set, so it has no distance to
496 // anything; asking for one is a precondition violation.
497 assert(!empty());
498 return this->template distanceLInf<ResultNumber>(other.asLine());
499}
500
501template <class PointType, class LabelType>
502template <class ResultNumber, SegmentConcept OtherSegment>
503constexpr auto Rectangle<PointType, LabelType>::distanceLInf(const OtherSegment& other) const {
504 // There is no nearest point of the empty set, so it has no distance to
505 // anything; asking for one is a precondition violation.
506 assert(!empty());
507 if (intersects(other)) {
508 return ResultNumber{};
509 }
510
511 auto best_distance = this->template distanceLInf<ResultNumber>(other.min());
512 const auto other_max_distance = this->template distanceLInf<ResultNumber>(other.max());
513 if (other_max_distance < best_distance) {
514 best_distance = other_max_distance;
515 }
516
517 const auto rectangle_edges = edges();
518 for (const auto& edge : rectangle_edges) {
519 const auto current_distance = edge.template distanceLInf<ResultNumber>(other);
520 if (current_distance < best_distance) {
521 best_distance = current_distance;
522 }
523 }
524
525 return best_distance;
526}
527
528template <class PointType, class LabelType>
529template <class ResultNumber, OrientedSegmentConcept OtherOrientedSegment>
530constexpr auto Rectangle<PointType, LabelType>::distanceLInf(const OtherOrientedSegment& other) const {
531 // There is no nearest point of the empty set, so it has no distance to
532 // anything; asking for one is a precondition violation.
533 assert(!empty());
534 return this->template distanceLInf<ResultNumber>(static_cast<Segment<typename OtherOrientedSegment::PointType>>(other));
535}
536
537template <class PointType, class LabelType>
538template <class ResultNumber, RayConcept OtherRay>
539constexpr auto Rectangle<PointType, LabelType>::distanceLInf(const OtherRay& other) const {
540 // There is no nearest point of the empty set, so it has no distance to
541 // anything; asking for one is a precondition violation.
542 assert(!empty());
543 if (intersects(other)) {
544 return ResultNumber{};
545 }
546
547 auto best_distance = this->template distanceLInf<ResultNumber>(other.source());
548 const auto rectangle_edges = edges();
549 for (const auto& edge : rectangle_edges) {
550 const auto current_distance = other.template distanceLInf<ResultNumber>(edge);
551 if (current_distance < best_distance) {
552 best_distance = current_distance;
553 }
554 }
555
556 return best_distance;
557}
558
559template <class PointType, class LabelType>
560template <class ResultNumber, HalfplaneConcept OtherHalfplane>
561constexpr auto Rectangle<PointType, LabelType>::distanceLInf(const OtherHalfplane& other) const {
562 // There is no nearest point of the empty set, so it has no distance to
563 // anything; asking for one is a precondition violation.
564 assert(!empty());
565 if (intersects(other)) {
566 return ResultNumber{};
567 }
568 return this->template distanceLInf<ResultNumber>(other.asLine());
569}
570
571template <class PointType, class LabelType>
572template <class ResultNumber, RectangleConcept OtherRectangle>
573constexpr auto Rectangle<PointType, LabelType>::distanceLInf(const OtherRectangle& other) const {
574 // There is no nearest point of the empty set, so it has no distance to
575 // anything; asking for one is a precondition violation.
576 assert(!empty());
577 const ResultNumber dx = static_cast<ResultNumber>(axisDistance(min().x(), max().x(), other.min().x(), other.max().x()));
578 const ResultNumber dy = static_cast<ResultNumber>(axisDistance(min().y(), max().y(), other.min().y(), other.max().y()));
579 return dx > dy ? dx : dy;
580}
581
582// -----------------------------------------------------------------------------
583// Triangle
584
585template <class PointType, class LabelType>
586template <class ResultNumber, class OtherShape>
587constexpr ResultNumber Triangle<PointType, LabelType>::edgeMinDistanceLInf(const OtherShape& other) const {
588 const auto triangle_edges = edges();
589 auto best = triangle_edges[0].template distanceLInf<ResultNumber>(other);
590 for (std::size_t index = 1; index < triangle_edges.size(); ++index) {
591 const auto current = triangle_edges[index].template distanceLInf<ResultNumber>(other);
592 if (current < best) {
593 best = current;
594 }
595 }
596 return best;
597}
598
599template <class PointType, class LabelType>
600template <class ResultNumber, class OtherShape>
601constexpr ResultNumber Triangle<PointType, LabelType>::vertexMinDistanceLInf(const OtherShape& other) const {
602 const auto triangle_vertices = vertices();
603 auto best = other.template distanceLInf<ResultNumber>(triangle_vertices[0]);
604 for (std::size_t index = 1; index < triangle_vertices.size(); ++index) {
605 const auto current = other.template distanceLInf<ResultNumber>(triangle_vertices[index]);
606 if (current < best) {
607 best = current;
608 }
609 }
610 return best;
611}
612
613template <class PointType, class LabelType>
614template <class ResultNumber, PointConcept OtherPoint>
615constexpr auto Triangle<PointType, LabelType>::distanceLInf(const OtherPoint& point) const {
616 if (intersects(point)) {
617 return ResultNumber{};
618 }
619 return this->template edgeMinDistanceLInf<ResultNumber>(point);
620}
621
622template <class PointType, class LabelType>
623template <class ResultNumber, SegmentConcept OtherSegment>
624constexpr auto Triangle<PointType, LabelType>::distanceLInf(const OtherSegment& other) const {
625 if (intersects(other)) {
626 return ResultNumber{};
627 }
628 return this->template edgeMinDistanceLInf<ResultNumber>(other);
629}
630
631template <class PointType, class LabelType>
632template <class ResultNumber, OrientedSegmentConcept OtherOrientedSegment>
633constexpr auto Triangle<PointType, LabelType>::distanceLInf(const OtherOrientedSegment& other) const {
634 if (intersects(other)) {
635 return ResultNumber{};
636 }
637 return this->template edgeMinDistanceLInf<ResultNumber>(other);
638}
639
640template <class PointType, class LabelType>
641template <class ResultNumber, LineConcept OtherLine>
642constexpr auto Triangle<PointType, LabelType>::distanceLInf(const OtherLine& other) const {
643 if (intersects(other)) {
644 return ResultNumber{};
645 }
646 return this->template vertexMinDistanceLInf<ResultNumber>(other);
647}
648
649template <class PointType, class LabelType>
650template <class ResultNumber, OrientedLineConcept OtherOrientedLine>
651constexpr auto Triangle<PointType, LabelType>::distanceLInf(const OtherOrientedLine& other) const {
652 if (intersects(other)) {
653 return ResultNumber{};
654 }
655 return this->template vertexMinDistanceLInf<ResultNumber>(other);
656}
657
658template <class PointType, class LabelType>
659template <class ResultNumber, RayConcept OtherRay>
660constexpr auto Triangle<PointType, LabelType>::distanceLInf(const OtherRay& other) const {
661 if (intersects(other)) {
662 return ResultNumber{};
663 }
664 return this->template edgeMinDistanceLInf<ResultNumber>(other);
665}
666
667template <class PointType, class LabelType>
668template <class ResultNumber, HalfplaneConcept OtherHalfplane>
669constexpr auto Triangle<PointType, LabelType>::distanceLInf(const OtherHalfplane& other) const {
670 if (intersects(other)) {
671 return ResultNumber{};
672 }
673 return this->template distanceLInf<ResultNumber>(other.asLine());
674}
675
676template <class PointType, class LabelType>
677template <class ResultNumber, RectangleConcept OtherRectangle>
678constexpr auto Triangle<PointType, LabelType>::distanceLInf(const OtherRectangle& other) const {
679 if (intersects(other)) {
680 return ResultNumber{};
681 }
682 return this->template edgeMinDistanceLInf<ResultNumber>(other);
683}
684
685template <class PointType, class LabelType>
686template <class ResultNumber, TriangleConcept OtherTriangle>
687constexpr auto Triangle<PointType, LabelType>::distanceLInf(const OtherTriangle& other) const {
688 if (intersects(other)) {
689 return ResultNumber{};
690 }
691 return this->template edgeMinDistanceLInf<ResultNumber>(other);
692}
693
694// -----------------------------------------------------------------------------
695// Convex
696//
697// Always uses the O(n) edge scan below (no cyclic support-function fast path):
698// see the distanceLInf declarations in convex.hpp for why the Euclidean fast
699// path's search functional does not carry over to the LInf gauge.
700
701template <class PointType_, class LabelType>
702template <class ResultNumber, PointConcept OtherPoint>
703constexpr auto Convex<PointType_, LabelType>::distanceLInf(const OtherPoint& point) const {
704 if (contains(point)) {
705 return ResultNumber{};
706 }
707 auto edgeVector = edges();
708 ResultNumber best = edgeVector[0].template distanceLInf<ResultNumber>(point);
709 for (auto& e : edgeVector) {
710 const ResultNumber current = e.template distanceLInf<ResultNumber>(point);
711 if (current < best) {
712 best = current;
713 }
714 }
715 return best;
716}
717
718template <class PointType_, class LabelType>
719template <class ResultNumber, SegmentConcept OtherSegment>
720constexpr auto Convex<PointType_, LabelType>::distanceLInf(const OtherSegment& other) const {
721 if (intersects(other)) {
722 return ResultNumber{};
723 }
724 auto edgeVector = edges();
725 ResultNumber best = edgeVector[0].template distanceLInf<ResultNumber>(other);
726 for (auto& e : edgeVector) {
727 const ResultNumber current = e.template distanceLInf<ResultNumber>(other);
728 if (current < best) {
729 best = current;
730 }
731 }
732 return best;
733}
734
735template <class PointType_, class LabelType>
736template <class ResultNumber, OrientedSegmentConcept OtherOrientedSegment>
737constexpr auto Convex<PointType_, LabelType>::distanceLInf(const OtherOrientedSegment& other) const {
738 return this->template distanceLInf<ResultNumber>(
740}
741
742template <class PointType_, class LabelType>
743template <class ResultNumber, ConvexConcept OtherConvex>
744constexpr auto Convex<PointType_, LabelType>::distanceLInf(const OtherConvex& other) const {
745 if (intersects(other)) {
746 return ResultNumber{};
747 }
748
749 const auto minOverEdges = [](const auto& source, const auto& target) {
750 const auto edgeVector = source.edges();
751 ResultNumber best = target.template distanceLInf<ResultNumber>(edgeVector[0]);
752 for (const auto& edge : edgeVector) {
753 const ResultNumber current = target.template distanceLInf<ResultNumber>(edge);
754 if (current < best) {
755 best = current;
756 }
757 }
758 return best;
759 };
760
761 if (size() <= other.size()) {
762 return minOverEdges(*this, other);
763 }
764 return minOverEdges(other, *this);
765}
766
767template <class PointType_, class LabelType>
768template <class ResultNumber, TriangleConcept OtherTriangle>
769constexpr auto Convex<PointType_, LabelType>::distanceLInf(const OtherTriangle& other) const {
770 return this->template distanceLInf<ResultNumber>(other.asConvex());
771}
772
773template <class PointType_, class LabelType>
774template <class ResultNumber, RectangleConcept OtherRectangle>
775constexpr auto Convex<PointType_, LabelType>::distanceLInf(const OtherRectangle& other) const {
776 return this->template distanceLInf<ResultNumber>(other.asConvex());
777}
778
779template <class PointType_, class LabelType>
780template <class ResultNumber, LineConcept OtherLine>
781constexpr auto Convex<PointType_, LabelType>::distanceLInf(const OtherLine& other) const {
782 if (intersects(other)) {
783 return ResultNumber{};
784 }
785 ResultNumber best = other.template distanceLInf<ResultNumber>(get(0));
786 for (std::ptrdiff_t i = 1; i < static_cast<std::ptrdiff_t>(size()); ++i) {
787 const ResultNumber current = other.template distanceLInf<ResultNumber>(get(i));
788 if (current < best) {
789 best = current;
790 }
791 }
792 return best;
793}
794
795template <class PointType_, class LabelType>
796template <class ResultNumber, OrientedLineConcept OtherOrientedLine>
797constexpr auto Convex<PointType_, LabelType>::distanceLInf(const OtherOrientedLine& other) const {
798 return this->template distanceLInf<ResultNumber>(other.asLine());
799}
800
801template <class PointType_, class LabelType>
802template <class ResultNumber, RayConcept OtherRay>
803constexpr auto Convex<PointType_, LabelType>::distanceLInf(const OtherRay& other) const {
804 if (intersects(other)) {
805 return ResultNumber{};
806 }
807 auto edgeVector = edges();
808 ResultNumber best = other.template distanceLInf<ResultNumber>(edgeVector[0]);
809 for (const auto& e : edgeVector) {
810 const ResultNumber current = other.template distanceLInf<ResultNumber>(e);
811 if (current < best) {
812 best = current;
813 }
814 }
815 return best;
816}
817
818template <class PointType_, class LabelType>
819template <class ResultNumber, HalfplaneConcept OtherHalfplane>
820constexpr auto Convex<PointType_, LabelType>::distanceLInf(const OtherHalfplane& other) const {
821 if (intersects(other)) {
822 return ResultNumber{};
823 }
824 return this->template distanceLInf<ResultNumber>(other.asLine());
825}
826
827// -----------------------------------------------------------------------------
828// Polygon
829
830template <class PointType_, class TLabel>
831template <class ResultNumber, class OtherShape>
832constexpr ResultNumber Polygon<PointType_, TLabel>::edgeMinDistanceLInf(const OtherShape& other) const {
833 const auto boundaryEdges = edges();
834 ResultNumber best = boundaryEdges[0].template distanceLInf<ResultNumber>(other);
835 for (std::size_t index = 1; index < boundaryEdges.size(); ++index) {
836 const ResultNumber current = boundaryEdges[index].template distanceLInf<ResultNumber>(other);
837 if (current < best) {
838 best = current;
839 }
840 }
841 return best;
842}
843
844template <class PointType_, class TLabel>
845template <class ResultNumber, PointConcept OtherPoint>
846constexpr auto Polygon<PointType_, TLabel>::distanceLInf(const OtherPoint& point) const {
847 if (intersects(point)) {
848 return ResultNumber{};
849 }
850 return this->template edgeMinDistanceLInf<ResultNumber>(point);
851}
852
853template <class PointType_, class TLabel>
854template <class ResultNumber, SegmentConcept OtherSegment>
855constexpr auto Polygon<PointType_, TLabel>::distanceLInf(const OtherSegment& other) const {
856 if (intersects(other)) {
857 return ResultNumber{};
858 }
859 return this->template edgeMinDistanceLInf<ResultNumber>(other);
860}
861
862template <class PointType_, class TLabel>
863template <class ResultNumber, OrientedSegmentConcept OtherOrientedSegment>
864constexpr auto Polygon<PointType_, TLabel>::distanceLInf(const OtherOrientedSegment& other) const {
865 if (intersects(other)) {
866 return ResultNumber{};
867 }
868 return this->template edgeMinDistanceLInf<ResultNumber>(other);
869}
870
871template <class PointType_, class TLabel>
872template <class ResultNumber, LineConcept OtherLine>
873constexpr auto Polygon<PointType_, TLabel>::distanceLInf(const OtherLine& other) const {
874 if (intersects(other)) {
875 return ResultNumber{};
876 }
877 return this->template edgeMinDistanceLInf<ResultNumber>(other);
878}
879
880template <class PointType_, class TLabel>
881template <class ResultNumber, OrientedLineConcept OtherOrientedLine>
882constexpr auto Polygon<PointType_, TLabel>::distanceLInf(const OtherOrientedLine& other) const {
883 if (intersects(other)) {
884 return ResultNumber{};
885 }
886 return this->template edgeMinDistanceLInf<ResultNumber>(other);
887}
888
889template <class PointType_, class TLabel>
890template <class ResultNumber, RayConcept OtherRay>
891constexpr auto Polygon<PointType_, TLabel>::distanceLInf(const OtherRay& other) const {
892 if (intersects(other)) {
893 return ResultNumber{};
894 }
895 return this->template edgeMinDistanceLInf<ResultNumber>(other);
896}
897
898template <class PointType_, class TLabel>
899template <class ResultNumber, HalfplaneConcept OtherHalfplane>
900constexpr auto Polygon<PointType_, TLabel>::distanceLInf(const OtherHalfplane& other) const {
901 if (intersects(other)) {
902 return ResultNumber{};
903 }
904 return this->template edgeMinDistanceLInf<ResultNumber>(other);
905}
906
907template <class PointType_, class TLabel>
908template <class ResultNumber, RectangleConcept OtherRectangle>
909constexpr auto Polygon<PointType_, TLabel>::distanceLInf(const OtherRectangle& other) const {
910 if (intersects(other)) {
911 return ResultNumber{};
912 }
913 return this->template edgeMinDistanceLInf<ResultNumber>(other);
914}
915
916template <class PointType_, class TLabel>
917template <class ResultNumber, TriangleConcept OtherTriangle>
918constexpr auto Polygon<PointType_, TLabel>::distanceLInf(const OtherTriangle& other) const {
919 if (intersects(other)) {
920 return ResultNumber{};
921 }
922 return this->template edgeMinDistanceLInf<ResultNumber>(other);
923}
924
925template <class PointType_, class TLabel>
926template <class ResultNumber, ConvexConcept OtherConvex>
927constexpr auto Polygon<PointType_, TLabel>::distanceLInf(const OtherConvex& other) const {
928 if (intersects(other)) {
929 return ResultNumber{};
930 }
931 return this->template edgeMinDistanceLInf<ResultNumber>(other);
932}
933
934template <class PointType_, class TLabel>
935template <class ResultNumber, PolygonConcept OtherPolygon>
936constexpr auto Polygon<PointType_, TLabel>::distanceLInf(const OtherPolygon& other) const {
937 if (intersects(other)) {
938 return ResultNumber{};
939 }
940 return this->template edgeMinDistanceLInf<ResultNumber>(other);
941}
942
943// -----------------------------------------------------------------------------
944// Hausdorff distance (added only where a Euclidean squaredHausdorffDistance
945// overload already exists; Polygon has none today, so it gets none here).
946
947template <class PointType, class LabelType>
948template <class ResultNumber, SegmentConcept OtherSegment>
949constexpr auto Segment<PointType, LabelType>::hausdorffDistanceLInf(const OtherSegment& other) const {
950 const auto worst_from_this = detail::maxVertexDistanceLInf<ResultNumber>(*this, other);
951 const auto worst_from_other = detail::maxVertexDistanceLInf<ResultNumber>(other, *this);
952 return worst_from_this > worst_from_other ? worst_from_this : worst_from_other;
953}
954
955template <class PointType, class LabelType>
956template <class ResultNumber, PointConcept OtherPoint>
957constexpr auto Segment<PointType, LabelType>::hausdorffDistanceLInf(const OtherPoint& point) const {
958 return detail::maxVertexDistanceLInf<ResultNumber>(*this, point);
959}
960
961template <class PointType, class LabelType>
962template <class ResultNumber, SegmentConcept OtherSegment>
963constexpr auto OrientedSegment<PointType, LabelType>::hausdorffDistanceLInf(const OtherSegment& other) const {
964 return static_cast<Segment<PointType>>(*this).template hausdorffDistanceLInf<ResultNumber>(other);
965}
966
967template <class PointType, class LabelType>
968template <class ResultNumber, OrientedSegmentConcept OtherOrientedSegment>
969constexpr auto OrientedSegment<PointType, LabelType>::hausdorffDistanceLInf(const OtherOrientedSegment& other) const {
970 return static_cast<Segment<PointType>>(*this).template hausdorffDistanceLInf<ResultNumber>(
972}
973
974template <class PointType, class LabelType>
975template <class ResultNumber, PointConcept OtherPoint>
976constexpr auto OrientedSegment<PointType, LabelType>::hausdorffDistanceLInf(const OtherPoint& point) const {
977 return static_cast<Segment<PointType>>(*this).template hausdorffDistanceLInf<ResultNumber>(point);
978}
979
980template <class PointType, class LabelType>
981template <class ResultNumber, RectangleConcept OtherRectangle>
982constexpr auto Rectangle<PointType, LabelType>::hausdorffDistanceLInf(const OtherRectangle& other) const {
983 // There is no nearest point of the empty set, so it has no distance to
984 // anything; asking for one is a precondition violation.
985 assert(!empty());
986 const auto worst_from_this = detail::maxVertexDistanceLInf<ResultNumber>(*this, other);
987 const auto worst_from_other = detail::maxVertexDistanceLInf<ResultNumber>(other, *this);
988 return worst_from_this > worst_from_other ? worst_from_this : worst_from_other;
989}
990
991template <class PointType, class LabelType>
992template <class ResultNumber, PointConcept OtherPoint>
993constexpr auto Rectangle<PointType, LabelType>::hausdorffDistanceLInf(const OtherPoint& point) const {
994 // There is no nearest point of the empty set, so it has no distance to
995 // anything; asking for one is a precondition violation.
996 assert(!empty());
997 return detail::maxVertexDistanceLInf<ResultNumber>(*this, point);
998}
999
1000template <class PointType, class LabelType>
1001template <class ResultNumber, SegmentConcept OtherSegment>
1002constexpr auto Rectangle<PointType, LabelType>::hausdorffDistanceLInf(const OtherSegment& other) const {
1003 // There is no nearest point of the empty set, so it has no distance to
1004 // anything; asking for one is a precondition violation.
1005 assert(!empty());
1006 const auto worst_from_this = detail::maxVertexDistanceLInf<ResultNumber>(*this, other);
1007 const auto worst_from_other = detail::maxVertexDistanceLInf<ResultNumber>(other, *this);
1008 return worst_from_this > worst_from_other ? worst_from_this : worst_from_other;
1009}
1010
1011template <class PointType, class LabelType>
1012template <class ResultNumber, OrientedSegmentConcept OtherOrientedSegment>
1013constexpr auto Rectangle<PointType, LabelType>::hausdorffDistanceLInf(const OtherOrientedSegment& other) const {
1014 // There is no nearest point of the empty set, so it has no distance to
1015 // anything; asking for one is a precondition violation.
1016 assert(!empty());
1017 const auto worst_from_this = detail::maxVertexDistanceLInf<ResultNumber>(*this, other);
1018 const auto worst_from_other = detail::maxVertexDistanceLInf<ResultNumber>(other, *this);
1019 return worst_from_this > worst_from_other ? worst_from_this : worst_from_other;
1020}
1021
1022template <class PointType, class LabelType>
1023template <class ResultNumber, PointConcept OtherPoint>
1024constexpr auto Triangle<PointType, LabelType>::hausdorffDistanceLInf(const OtherPoint& point) const {
1025 return detail::maxVertexDistanceLInf<ResultNumber>(*this, point);
1026}
1027
1028template <class PointType, class LabelType>
1029template <class ResultNumber, SegmentConcept OtherSegment>
1030constexpr auto Triangle<PointType, LabelType>::hausdorffDistanceLInf(const OtherSegment& other) const {
1031 const auto worst_from_this = detail::maxVertexDistanceLInf<ResultNumber>(*this, other);
1032 const auto worst_from_other = detail::maxVertexDistanceLInf<ResultNumber>(other, *this);
1033 return worst_from_this > worst_from_other ? worst_from_this : worst_from_other;
1034}
1035
1036template <class PointType, class LabelType>
1037template <class ResultNumber, OrientedSegmentConcept OtherOrientedSegment>
1038constexpr auto Triangle<PointType, LabelType>::hausdorffDistanceLInf(const OtherOrientedSegment& other) const {
1039 const auto worst_from_this = detail::maxVertexDistanceLInf<ResultNumber>(*this, other);
1040 const auto worst_from_other = detail::maxVertexDistanceLInf<ResultNumber>(other, *this);
1041 return worst_from_this > worst_from_other ? worst_from_this : worst_from_other;
1042}
1043
1044template <class PointType, class LabelType>
1045template <class ResultNumber, RectangleConcept OtherRectangle>
1046constexpr auto Triangle<PointType, LabelType>::hausdorffDistanceLInf(const OtherRectangle& other) const {
1047 const auto worst_from_this = detail::maxVertexDistanceLInf<ResultNumber>(*this, other);
1048 const auto worst_from_other = detail::maxVertexDistanceLInf<ResultNumber>(other, *this);
1049 return worst_from_this > worst_from_other ? worst_from_this : worst_from_other;
1050}
1051
1052template <class PointType, class LabelType>
1053template <class ResultNumber, TriangleConcept OtherTriangle>
1054constexpr auto Triangle<PointType, LabelType>::hausdorffDistanceLInf(const OtherTriangle& other) const {
1055 const auto worst_from_this = detail::maxVertexDistanceLInf<ResultNumber>(*this, other);
1056 const auto worst_from_other = detail::maxVertexDistanceLInf<ResultNumber>(other, *this);
1057 return worst_from_this > worst_from_other ? worst_from_this : worst_from_other;
1058}
1059
1060template <class PointType_, class LabelType>
1061template <class ResultNumber, PointConcept OtherPoint>
1062constexpr auto Convex<PointType_, LabelType>::hausdorffDistanceLInf(const OtherPoint& point) const {
1063 return detail::maxVertexDistanceLInf<ResultNumber>(*this, point);
1064}
1065
1066template <class PointType_, class LabelType>
1067template <class ResultNumber, SegmentConcept OtherSegment>
1068constexpr auto Convex<PointType_, LabelType>::hausdorffDistanceLInf(const OtherSegment& other) const {
1069 const auto worst_from_this = detail::maxVertexDistanceLInf<ResultNumber>(*this, other);
1070 const auto worst_from_other = detail::maxVertexDistanceLInf<ResultNumber>(other, *this);
1071 return worst_from_this > worst_from_other ? worst_from_this : worst_from_other;
1072}
1073
1074template <class PointType_, class LabelType>
1075template <class ResultNumber, OrientedSegmentConcept OtherOrientedSegment>
1076constexpr auto Convex<PointType_, LabelType>::hausdorffDistanceLInf(const OtherOrientedSegment& other) const {
1077 const auto worst_from_this = detail::maxVertexDistanceLInf<ResultNumber>(*this, other);
1078 const auto worst_from_other = detail::maxVertexDistanceLInf<ResultNumber>(other, *this);
1079 return worst_from_this > worst_from_other ? worst_from_this : worst_from_other;
1080}
1081
1082template <class PointType_, class LabelType>
1083template <class ResultNumber, RectangleConcept OtherRectangle>
1084constexpr auto Convex<PointType_, LabelType>::hausdorffDistanceLInf(const OtherRectangle& other) const {
1085 const auto worst_from_this = detail::maxVertexDistanceLInf<ResultNumber>(*this, other);
1086 const auto worst_from_other = detail::maxVertexDistanceLInf<ResultNumber>(other, *this);
1087 return worst_from_this > worst_from_other ? worst_from_this : worst_from_other;
1088}
1089
1090template <class PointType_, class LabelType>
1091template <class ResultNumber, TriangleConcept OtherTriangle>
1092constexpr auto Convex<PointType_, LabelType>::hausdorffDistanceLInf(const OtherTriangle& other) const {
1093 const auto worst_from_this = detail::maxVertexDistanceLInf<ResultNumber>(*this, other);
1094 const auto worst_from_other = detail::maxVertexDistanceLInf<ResultNumber>(other, *this);
1095 return worst_from_this > worst_from_other ? worst_from_this : worst_from_other;
1096}
1097
1098template <class PointType_, class LabelType>
1099template <class ResultNumber, ConvexConcept OtherConvex>
1100constexpr auto Convex<PointType_, LabelType>::hausdorffDistanceLInf(const OtherConvex& other) const {
1101 const auto worst_from_this = detail::maxVertexDistanceLInf<ResultNumber>(*this, other);
1102 const auto worst_from_other = detail::maxVertexDistanceLInf<ResultNumber>(other, *this);
1103 return worst_from_this > worst_from_other ? worst_from_this : worst_from_other;
1104}
1105
1106
1107template <class PointType_, class TLabel>
1108template <class ResultNumber, MonotoneChainConcept OtherChain>
1109constexpr auto Polygon<PointType_, TLabel>::distanceLInf(const OtherChain& other) const {
1110 if (intersects(other)) {
1111 return ResultNumber{};
1112 }
1113 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1114}
1115
1116// -----------------------------------------------------------------------------
1117// MonotoneChain
1118
1119template <class PointType, class LabelType, class Storage>
1120template <class ResultNumber, class OtherShape>
1121constexpr ResultNumber MonotoneChain<PointType, LabelType, Storage>::edgeMinDistanceLInf(const OtherShape& other) const {
1122 assert(size() >= 1);
1123 if (size() == 1) {
1124 // A chain collapsed to a single vertex has no edge to measure from;
1125 // its distance is the distance from that vertex.
1126 return (*this)[0].template distanceLInf<ResultNumber>(other);
1127 }
1128 ResultNumber best = this->template boundaryAt<false>(0).template distanceLInf<ResultNumber>(other);
1129 for (std::size_t index = 1; index + 1 < size(); ++index) {
1130 const ResultNumber current =
1131 this->template boundaryAt<false>(index).template distanceLInf<ResultNumber>(other);
1132 if (current < best) {
1133 best = current;
1134 }
1135 }
1136 return best;
1137}
1138
1139template <class PointType, class LabelType, class Storage>
1140template <class ResultNumber, PointConcept OtherPoint>
1141constexpr auto MonotoneChain<PointType, LabelType, Storage>::distanceLInf(const OtherPoint& point) const {
1142 if (intersects(point)) {
1143 return ResultNumber{};
1144 }
1145 return this->template edgeMinDistanceLInf<ResultNumber>(point);
1146}
1147
1148template <class PointType, class LabelType, class Storage>
1149template <class ResultNumber, SegmentConcept OtherSegment>
1150constexpr auto MonotoneChain<PointType, LabelType, Storage>::distanceLInf(const OtherSegment& other) const {
1151 if (intersects(other)) {
1152 return ResultNumber{};
1153 }
1154 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1155}
1156
1157template <class PointType, class LabelType, class Storage>
1158template <class ResultNumber, OrientedSegmentConcept OtherOrientedSegment>
1159constexpr auto MonotoneChain<PointType, LabelType, Storage>::distanceLInf(const OtherOrientedSegment& other) const {
1160 if (intersects(other)) {
1161 return ResultNumber{};
1162 }
1163 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1164}
1165
1166template <class PointType, class LabelType, class Storage>
1167template <class ResultNumber, LineConcept OtherLine>
1168constexpr auto MonotoneChain<PointType, LabelType, Storage>::distanceLInf(const OtherLine& other) const {
1169 if (intersects(other)) {
1170 return ResultNumber{};
1171 }
1172 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1173}
1174
1175template <class PointType, class LabelType, class Storage>
1176template <class ResultNumber, OrientedLineConcept OtherOrientedLine>
1177constexpr auto MonotoneChain<PointType, LabelType, Storage>::distanceLInf(const OtherOrientedLine& other) const {
1178 if (intersects(other)) {
1179 return ResultNumber{};
1180 }
1181 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1182}
1183
1184template <class PointType, class LabelType, class Storage>
1185template <class ResultNumber, RayConcept OtherRay>
1186constexpr auto MonotoneChain<PointType, LabelType, Storage>::distanceLInf(const OtherRay& other) const {
1187 if (intersects(other)) {
1188 return ResultNumber{};
1189 }
1190 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1191}
1192
1193template <class PointType, class LabelType, class Storage>
1194template <class ResultNumber, HalfplaneConcept OtherHalfplane>
1195constexpr auto MonotoneChain<PointType, LabelType, Storage>::distanceLInf(const OtherHalfplane& other) const {
1196 if (intersects(other)) {
1197 return ResultNumber{};
1198 }
1199 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1200}
1201
1202template <class PointType, class LabelType, class Storage>
1203template <class ResultNumber, RectangleConcept OtherRectangle>
1204constexpr auto MonotoneChain<PointType, LabelType, Storage>::distanceLInf(const OtherRectangle& other) const {
1205 if (intersects(other)) {
1206 return ResultNumber{};
1207 }
1208 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1209}
1210
1211template <class PointType, class LabelType, class Storage>
1212template <class ResultNumber, TriangleConcept OtherTriangle>
1213constexpr auto MonotoneChain<PointType, LabelType, Storage>::distanceLInf(const OtherTriangle& other) const {
1214 if (intersects(other)) {
1215 return ResultNumber{};
1216 }
1217 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1218}
1219
1220template <class PointType, class LabelType, class Storage>
1221template <class ResultNumber, ConvexConcept OtherConvex>
1222constexpr auto MonotoneChain<PointType, LabelType, Storage>::distanceLInf(const OtherConvex& other) const {
1223 if (intersects(other)) {
1224 return ResultNumber{};
1225 }
1226 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1227}
1228
1229template <class PointType, class LabelType, class Storage>
1230template <class ResultNumber, MonotoneChainConcept OtherChain>
1231constexpr auto MonotoneChain<PointType, LabelType, Storage>::distanceLInf(const OtherChain& other) const {
1232 if (intersects(other)) {
1233 return ResultNumber{};
1234 }
1235 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1236}
1237
1238// -----------------------------------------------------------------------------
1239// Polyline
1240
1241template <class PointType, class LabelType>
1242template <class ResultNumber, class OtherShape>
1243constexpr ResultNumber Polyline<PointType, LabelType>::edgeMinDistanceLInf(const OtherShape& other) const {
1244 assert(size() >= 1);
1245 if (size() == 1) {
1246 // A polyline collapsed to a single vertex has no edge to measure from;
1247 // its distance is the distance from that vertex.
1248 return (*this)[0].template distanceLInf<ResultNumber>(other);
1249 }
1250 ResultNumber best = this->template boundaryAt<false>(0).template distanceLInf<ResultNumber>(other);
1251 for (std::size_t index = 1; index + 1 < size(); ++index) {
1252 const ResultNumber current =
1253 this->template boundaryAt<false>(index).template distanceLInf<ResultNumber>(other);
1254 if (current < best) {
1255 best = current;
1256 }
1257 }
1258 return best;
1259}
1260
1261template <class PointType, class LabelType>
1262template <class ResultNumber, PointConcept OtherPoint>
1263constexpr auto Polyline<PointType, LabelType>::distanceLInf(const OtherPoint& point) const {
1264 if (intersects(point)) {
1265 return ResultNumber{};
1266 }
1267 return this->template edgeMinDistanceLInf<ResultNumber>(point);
1268}
1269
1270template <class PointType, class LabelType>
1271template <class ResultNumber, SegmentConcept OtherSegment>
1272constexpr auto Polyline<PointType, LabelType>::distanceLInf(const OtherSegment& other) const {
1273 if (intersects(other)) {
1274 return ResultNumber{};
1275 }
1276 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1277}
1278
1279template <class PointType, class LabelType>
1280template <class ResultNumber, PolylineConcept OtherPolyline>
1281constexpr auto Polyline<PointType, LabelType>::distanceLInf(const OtherPolyline& other) const {
1282 if (intersects(other)) {
1283 return ResultNumber{};
1284 }
1285 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1286}
1287
1288
1289template <class PointType, class LabelType>
1290template <class ResultNumber, OrientedSegmentConcept OtherOrientedSegment>
1291constexpr auto Polyline<PointType, LabelType>::distanceLInf(const OtherOrientedSegment& other) const {
1292 if (intersects(other)) {
1293 return ResultNumber{};
1294 }
1295 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1296}
1297
1298template <class PointType, class LabelType>
1299template <class ResultNumber, LineConcept OtherLine>
1300constexpr auto Polyline<PointType, LabelType>::distanceLInf(const OtherLine& other) const {
1301 if (intersects(other)) {
1302 return ResultNumber{};
1303 }
1304 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1305}
1306
1307template <class PointType, class LabelType>
1308template <class ResultNumber, OrientedLineConcept OtherOrientedLine>
1309constexpr auto Polyline<PointType, LabelType>::distanceLInf(const OtherOrientedLine& other) const {
1310 if (intersects(other)) {
1311 return ResultNumber{};
1312 }
1313 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1314}
1315
1316template <class PointType, class LabelType>
1317template <class ResultNumber, RayConcept OtherRay>
1318constexpr auto Polyline<PointType, LabelType>::distanceLInf(const OtherRay& other) const {
1319 if (intersects(other)) {
1320 return ResultNumber{};
1321 }
1322 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1323}
1324
1325template <class PointType, class LabelType>
1326template <class ResultNumber, HalfplaneConcept OtherHalfplane>
1327constexpr auto Polyline<PointType, LabelType>::distanceLInf(const OtherHalfplane& other) const {
1328 if (intersects(other)) {
1329 return ResultNumber{};
1330 }
1331 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1332}
1333
1334template <class PointType, class LabelType>
1335template <class ResultNumber, RectangleConcept OtherRectangle>
1336constexpr auto Polyline<PointType, LabelType>::distanceLInf(const OtherRectangle& other) const {
1337 if (intersects(other)) {
1338 return ResultNumber{};
1339 }
1340 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1341}
1342
1343template <class PointType, class LabelType>
1344template <class ResultNumber, TriangleConcept OtherTriangle>
1345constexpr auto Polyline<PointType, LabelType>::distanceLInf(const OtherTriangle& other) const {
1346 if (intersects(other)) {
1347 return ResultNumber{};
1348 }
1349 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1350}
1351
1352template <class PointType, class LabelType>
1353template <class ResultNumber, ConvexConcept OtherConvex>
1354constexpr auto Polyline<PointType, LabelType>::distanceLInf(const OtherConvex& other) const {
1355 if (intersects(other)) {
1356 return ResultNumber{};
1357 }
1358 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1359}
1360
1361template <class PointType, class LabelType>
1362template <class ResultNumber, MonotoneChainConcept OtherChain>
1363constexpr auto Polyline<PointType, LabelType>::distanceLInf(const OtherChain& other) const {
1364 if (intersects(other)) {
1365 return ResultNumber{};
1366 }
1367 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1368}
1369
1370template <class PointType_, class TLabel>
1371template <class ResultNumber, PolylineConcept OtherPolyline>
1372constexpr auto Polygon<PointType_, TLabel>::distanceLInf(const OtherPolyline& other) const {
1373 if (intersects(other)) {
1374 return ResultNumber{};
1375 }
1376 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1377}
1378
1379
1380// -----------------------------------------------------------------------------
1381// HalfplaneIntersection
1382//
1383// Minimum over the region's boundary edges of the edge-to-shape Chebyshev
1384// distance, mirroring squaredDistance. Disk is excluded (the library defines
1385// L1/LInf to a disk only from a point). Querying the empty region is undefined
1386// behavior.
1387
1388namespace detail {
1389
1390template <class ResultNumber, class Region, class Other>
1391constexpr ResultNumber regionEdgesDistanceLInf(const Region& region, const Other& other) {
1392 ResultNumber best{};
1393 bool has = false;
1394 for (std::size_t i = 0; i < region.size(); ++i) {
1395 const ResultNumber current = std::visit(
1396 [&other](const auto& piece) {
1397 return static_cast<ResultNumber>(piece.template distanceLInf<ResultNumber>(other));
1398 },
1399 region.template edge<ResultNumber>(i));
1400 if (!has || current < best) {
1401 best = current;
1402 has = true;
1403 }
1404 }
1405 return best;
1406}
1407
1408} // namespace detail
1409
1410#define PGL_HPI_DISTANCE_LINF(ConceptName, ArgType) \
1411 template <class PointType, class LabelType> \
1412 template <class ResultNumber, ConceptName ArgType> \
1413 constexpr auto HalfplaneIntersection<PointType, LabelType>::distanceLInf( \
1414 const ArgType& other) const { \
1415 if (intersects(other)) { \
1416 return ResultNumber{}; \
1417 } \
1418 return detail::regionEdgesDistanceLInf<ResultNumber>(*this, other); \
1419 }
1420
1434
1435#undef PGL_HPI_DISTANCE_LINF
1436
1437template <class PointType, class LabelType>
1438template <class ResultNumber, HalfplaneIntersectionConcept OtherRegion>
1439constexpr auto HalfplaneIntersection<PointType, LabelType>::distanceLInf(const OtherRegion& other) const {
1440 // Disjoint convex regions realize their distance on this region's
1441 // boundary; each edge re-dispatches into the other region's own edge scan.
1442 if (intersects(other)) {
1443 return ResultNumber{};
1444 }
1445 return detail::regionEdgesDistanceLInf<ResultNumber>(*this, other);
1446}
1447
1448
1449// -----------------------------------------------------------------------------
1450// PolygonWithHoles
1451//
1452// See distance.hpp: a shape the closed region misses is nearest to a point of
1453// ∂A, so one scan over the edges of every ring answers all three metrics.
1454
1455template <class PointType, class LabelType>
1456template <class ResultNumber, class OtherShape>
1457constexpr ResultNumber PolygonWithHoles<PointType, LabelType>::edgeMinDistanceLInf(const OtherShape& other) const {
1458 ResultNumber best{};
1459 bool seeded = false;
1460 anyBoundaryEdge([&](const auto& edge) {
1461 const ResultNumber current = edge.template distanceLInf<ResultNumber>(other);
1462 if (!seeded || current < best) {
1463 best = current;
1464 seeded = true;
1465 }
1466 return false;
1467 });
1468 return best;
1469}
1470
1471template <class PointType, class LabelType>
1472template <class ResultNumber, PointConcept OtherPoint>
1473constexpr auto PolygonWithHoles<PointType, LabelType>::distanceLInf(const OtherPoint& point) const {
1474 if (intersects(point)) {
1475 return ResultNumber{};
1476 }
1477 return this->template edgeMinDistanceLInf<ResultNumber>(point);
1478}
1479
1480template <class PointType, class LabelType>
1481template <class ResultNumber, SegmentConcept OtherSegment>
1482constexpr auto PolygonWithHoles<PointType, LabelType>::distanceLInf(const OtherSegment& other) const {
1483 if (intersects(other)) {
1484 return ResultNumber{};
1485 }
1486 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1487}
1488
1489template <class PointType, class LabelType>
1490template <class ResultNumber, OrientedSegmentConcept OtherOrientedSegment>
1491constexpr auto PolygonWithHoles<PointType, LabelType>::distanceLInf(const OtherOrientedSegment& other) const {
1492 if (intersects(other)) {
1493 return ResultNumber{};
1494 }
1495 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1496}
1497
1498template <class PointType, class LabelType>
1499template <class ResultNumber, LineConcept OtherLine>
1500constexpr auto PolygonWithHoles<PointType, LabelType>::distanceLInf(const OtherLine& other) const {
1501 if (intersects(other)) {
1502 return ResultNumber{};
1503 }
1504 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1505}
1506
1507template <class PointType, class LabelType>
1508template <class ResultNumber, OrientedLineConcept OtherOrientedLine>
1509constexpr auto PolygonWithHoles<PointType, LabelType>::distanceLInf(const OtherOrientedLine& other) const {
1510 if (intersects(other)) {
1511 return ResultNumber{};
1512 }
1513 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1514}
1515
1516template <class PointType, class LabelType>
1517template <class ResultNumber, RayConcept OtherRay>
1518constexpr auto PolygonWithHoles<PointType, LabelType>::distanceLInf(const OtherRay& other) const {
1519 if (intersects(other)) {
1520 return ResultNumber{};
1521 }
1522 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1523}
1524
1525template <class PointType, class LabelType>
1526template <class ResultNumber, HalfplaneConcept OtherHalfplane>
1527constexpr auto PolygonWithHoles<PointType, LabelType>::distanceLInf(const OtherHalfplane& other) const {
1528 if (intersects(other)) {
1529 return ResultNumber{};
1530 }
1531 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1532}
1533
1534template <class PointType, class LabelType>
1535template <class ResultNumber, RectangleConcept OtherRectangle>
1536constexpr auto PolygonWithHoles<PointType, LabelType>::distanceLInf(const OtherRectangle& other) const {
1537 if (intersects(other)) {
1538 return ResultNumber{};
1539 }
1540 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1541}
1542
1543template <class PointType, class LabelType>
1544template <class ResultNumber, TriangleConcept OtherTriangle>
1545constexpr auto PolygonWithHoles<PointType, LabelType>::distanceLInf(const OtherTriangle& other) const {
1546 if (intersects(other)) {
1547 return ResultNumber{};
1548 }
1549 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1550}
1551
1552template <class PointType, class LabelType>
1553template <class ResultNumber, ConvexConcept OtherConvex>
1554constexpr auto PolygonWithHoles<PointType, LabelType>::distanceLInf(const OtherConvex& other) const {
1555 if (intersects(other)) {
1556 return ResultNumber{};
1557 }
1558 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1559}
1560
1561template <class PointType, class LabelType>
1562template <class ResultNumber, PolygonConcept OtherPolygon>
1563constexpr auto PolygonWithHoles<PointType, LabelType>::distanceLInf(const OtherPolygon& other) const {
1564 if (intersects(other)) {
1565 return ResultNumber{};
1566 }
1567 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1568}
1569
1570template <class PointType, class LabelType>
1571template <class ResultNumber, PolygonWithHolesConcept OtherRegion>
1572constexpr auto PolygonWithHoles<PointType, LabelType>::distanceLInf(const OtherRegion& other) const {
1573 if (intersects(other)) {
1574 return ResultNumber{};
1575 }
1576 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1577}
1578
1579template <class PointType, class LabelType>
1580template <class ResultNumber, MonotoneChainConcept OtherChain>
1581constexpr auto PolygonWithHoles<PointType, LabelType>::distanceLInf(const OtherChain& other) const {
1582 if (intersects(other)) {
1583 return ResultNumber{};
1584 }
1585 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1586}
1587
1588template <class PointType, class LabelType>
1589template <class ResultNumber, PolylineConcept OtherPolyline>
1590constexpr auto PolygonWithHoles<PointType, LabelType>::distanceLInf(const OtherPolyline& other) const {
1591 if (intersects(other)) {
1592 return ResultNumber{};
1593 }
1594 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1595}
1596
1597template <class PointType, class LabelType>
1598template <class ResultNumber, HalfplaneIntersectionConcept OtherIntersection>
1599constexpr auto PolygonWithHoles<PointType, LabelType>::distanceLInf(const OtherIntersection& other) const {
1600 if (intersects(other)) {
1601 return ResultNumber{};
1602 }
1603 return this->template edgeMinDistanceLInf<ResultNumber>(other);
1604}
1605
1606// No Disk overload: the library defines the L1 and LInf distances to a disk
1607// only from a point.
1608
1609
1610// ---------------------------------------------------------------------------
1611// PolygonSet
1612//
1613// The distance to a union is the minimum of the distances, with no caveat and
1614// no operand it fails for. An empty set has no component to measure from and
1615// reports zero.
1616
1617template <class PointType, class LabelType>
1618template <class ResultNumber, detail::SetOperandConcept OtherShape>
1619 requires detail::ComponentDistanceLInfConcept<ResultNumber, PolygonWithHoles<PointType>, OtherShape>
1620auto PolygonSet<PointType, LabelType>::distanceLInf(const OtherShape& other) const {
1621 return minOverComponents([&other](const ComponentType& component) {
1622 return component.template distanceLInf<ResultNumber>(other);
1623 });
1624}
1625
1626template <class PointType, class LabelType>
1627template <class ResultNumber, PolygonSetConcept OtherSet>
1628auto PolygonSet<PointType, LabelType>::distanceLInf(const OtherSet& other) const {
1629 ResultNumber best{};
1630 bool seeded = false;
1631 for (const auto& component : other) {
1632 const ResultNumber current = this->template distanceLInf<ResultNumber>(component);
1633 if (!seeded || current < best) {
1634 best = current;
1635 seeded = true;
1636 }
1637 }
1638 return best;
1639}
1640
1641} // namespace pgl
Definition forward.hpp:315
Definition forward.hpp:312
Definition forward.hpp:309
Definition forward.hpp:320
Definition forward.hpp:310
Definition forward.hpp:308
Definition forward.hpp:306
Definition forward.hpp:316
Definition forward.hpp:321
Definition forward.hpp:311
Definition forward.hpp:313
Definition forward.hpp:307
Definition forward.hpp:314
Manhattan (L1) distance between shapes.
#define PGL_HPI_DISTANCE_LINF(ConceptName, ArgType)
Definition distancelinf.hpp:1410
Definition arrangement.hpp:67
@ y
Definition intervaltree.hpp:24
@ x
Definition intervaltree.hpp:24
@ edge
Definition bitmatrix.hpp:37
@ vertex
Definition bitmatrix.hpp:37
Point() -> Point< int >
constexpr bool intersects(const OtherSegment &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:716
constexpr PointType get(std::ptrdiff_t index) const
Cyclic access: same as operator[] but index is taken modulo size(); negative indices wrap from the en...
Definition convex.hpp:289
constexpr auto hausdorffDistanceLInf(const OtherPoint &point) const
Returns the Chebyshev (LInf) Hausdorff distance to the given shape.
Definition distancelinf.hpp:1062
constexpr auto distanceLInf(const OtherPoint &point) const
Returns the Chebyshev (LInf) distance to the given shape.
Definition distancelinf.hpp:703
constexpr std::vector< Segment< PointType > > edges() const
Returns the edges of the convex polygon.
Definition convex.hpp:529
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1135
size_t size() const
Returns the number of vertices in the convex polygon.
Definition convex.hpp:840
constexpr Point< ResultNumber, PointLabelType > center() const
Returns the center (circumcenter of the three boundary points) in an explicitly chosen coordinate typ...
Definition disk.hpp:284
constexpr bool contains(const OtherPoint &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1015
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
constexpr ResultNumber radius() const
Returns the radius.
Definition disk.hpp:333
constexpr const PointType & a() const
Returns the first boundary point (lexicographically smallest).
Definition disk.hpp:228
constexpr const PointType & b() const
Returns the second boundary point in canonical order.
Definition disk.hpp:235
constexpr auto distanceLInf(const OtherPoint &other) const
Returns the Chebyshev (L∞) distance to the given shape.
Definition distancelinf.hpp:1421
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1808
constexpr auto distanceLInf(const OtherPoint &point) const
Returns the Chebyshev (LInf) distance to the given shape.
Definition distancelinf.hpp:395
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:622
constexpr Line< PointType > asLine() const
Returns the boundary line without orientation.
Definition halfplane.hpp:318
constexpr const PointType & max() const
Returns the largest stored defining point.
Definition line.hpp:189
constexpr const PointType & min() const
Returns the smallest stored defining point.
Definition line.hpp:180
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:312
constexpr auto distanceLInf(const OtherPoint &point) const
Returns the Chebyshev (LInf) distance to the given shape.
Definition distancelinf.hpp:257
constexpr auto distanceLInf(const OtherPoint &point) const
Returns the Chebyshev (LInf) distance to the given shape.
Definition distancelinf.hpp:1141
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1353
constexpr Line< PointType > asLine() const
Returns the line without orientation.
Definition orientedline.hpp:321
constexpr auto distanceLInf(const OtherPoint &point) const
Returns the Chebyshev (LInf) distance to the given shape.
Definition distancelinf.hpp:294
constexpr auto distanceLInf(const OtherPoint &point) const
Returns the Chebyshev (LInf) distance to the given shape.
Definition distancelinf.hpp:235
constexpr auto hausdorffDistanceLInf(const OtherSegment &other) const
Returns the Chebyshev (LInf) Hausdorff distance to the given shape.
Definition distancelinf.hpp:963
Two-dimensional point with optional label payload.
Definition point.hpp:129
constexpr auto distanceLInf(const OtherPoint &other) const
Returns the Chebyshev distance to another point.
Definition distance.hpp:83
static constexpr std::size_t size()
Definition point.hpp:246
constexpr std::ptrdiff_t index(const NumberType &value) const
Definition point.hpp:267
constexpr auto hausdorffDistanceLInf(const OtherPoint &other) const
Returns the Chebyshev (LInf) Hausdorff distance to another point.
Definition distancelinf.hpp:182
auto distanceLInf(const OtherShape &other) const
Computes the squared Euclidean distance to the other shape.
Definition distancelinf.hpp:1620
constexpr const ComponentType & component(std::size_t index) const
Accesses a component by index.
Definition polygonset.hpp:271
PolygonWithHoles< PointType > ComponentType
Definition polygonset.hpp:169
constexpr auto distanceLInf(const OtherPoint &point) const
Computes the squared Euclidean distance to the other shape.
Definition distancelinf.hpp:1473
constexpr bool intersects(const OtherPoint &point) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition polygonwithholes.hpp:1649
constexpr bool intersects(const OtherChain &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1596
constexpr auto distanceLInf(const OtherChain &other) const
Returns the Chebyshev (LInf) distance to the given shape.
Definition distancelinf.hpp:1109
constexpr auto distanceLInf(const OtherPoint &point) const
Returns the Chebyshev (LInf) distance to the given shape.
Definition distancelinf.hpp:1263
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:1620
constexpr const PointType & target() const
Returns the second stored point defining the direction.
Definition ray.hpp:193
constexpr auto distanceLInf(const OtherPoint &point) const
Returns the Chebyshev (LInf) distance to the given shape.
Definition distancelinf.hpp:327
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:409
constexpr const PointType & source() const
Returns the source point of the ray.
Definition ray.hpp:181
constexpr auto hausdorffDistanceLInf(const OtherRectangle &other) const
Returns the Chebyshev (LInf) Hausdorff distance to the given shape.
Definition distancelinf.hpp:982
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:502
constexpr const PointType & min() const
Returns the minimum corner (min x, min y).
Definition rectangle.hpp:347
constexpr bool empty() const
Returns whether the rectangle is the empty set of points.
Definition rectangle.hpp:290
constexpr std::array< Segment< PointType >, 4 > edges() const
Returns the four edges as unordered segments.
Definition bounding.hpp:199
constexpr auto distanceLInf(const OtherPoint &point) const
Returns the Chebyshev (LInf) distance to the given shape.
Definition distancelinf.hpp:461
constexpr std::array< PointType, 4 > vertices() const
Returns the four vertices in counterclockwise order.
Definition bounding.hpp:188
constexpr std::ptrdiff_t index(const PointType &point) const
Returns the smallest index i with (*this)[i] == point, or -1 if no corner equals point.
Definition rectangle.hpp:330
constexpr const PointType & max() const
Returns the maximum corner (max x, max y).
Definition rectangle.hpp:359
Unoriented closed segment between two endpoints plus optional segment label.
Definition segment.hpp:58
constexpr auto distanceLInf(const OtherPoint &point) const
Returns the Chebyshev (LInf) distance to the given shape.
Definition distancelinf.hpp:207
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:48
constexpr const PointType & max() const
Returns the largest stored endpoint.
Definition segment.hpp:199
constexpr const PointType & min() const
Returns the smallest stored endpoint.
Definition segment.hpp:190
constexpr auto hausdorffDistanceLInf(const OtherSegment &other) const
Returns the Chebyshev (LInf) Hausdorff distance to the given shape.
Definition distancelinf.hpp:949
constexpr bool intersects(const OtherPoint &other) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition intersects.hpp:134
constexpr auto hausdorffDistanceLInf(const OtherPoint &point) const
Returns the Chebyshev (LInf) Hausdorff distance to the given shape.
Definition distancelinf.hpp:1024
constexpr auto distanceLInf(const OtherPoint &point) const
Returns the Chebyshev (LInf) distance to the given shape.
Definition distancelinf.hpp:615