Pangolin
Header-only C++20 plane computational geometry library
Loading...
Searching...
No Matches
bounding.hpp
Go to the documentation of this file.
1#pragma once
2
4
9
10#include "shape/rectangle.hpp"
11
12namespace pgl {
13
14// -----------------------------------------------------------------------------
15// Point
16
17template <class Number, class Label>
19 return Rectangle<Point<Number, Label>>(*this, *this, true);
20}
21
22template <class Number, class Label>
23template <std::floating_point ResultNumber>
26 detail::lowerFloatingBound<ResultNumber>(x()),
27 detail::lowerFloatingBound<ResultNumber>(y()),
28 detail::upperFloatingBound<ResultNumber>(x()),
29 detail::upperFloatingBound<ResultNumber>(y()),
30 true);
31}
32
33template <class Number, class Label>
34constexpr std::array<Point<Number, Label>, 1> Point<Number, Label>::vertices() const {
35 return {*this};
36}
37
38template <class Number, class Label>
39constexpr std::array<Segment<Point<Number, Label>>, 0> Point<Number, Label>::edges() const {
40 return {};
41}
42
43template <class Number, class Label>
44constexpr std::array<OrientedSegment<Point<Number, Label>>, 0> Point<Number, Label>::orientedEdges() const {
45 return {};
46}
47
48// -----------------------------------------------------------------------------
49// Segment
50
51template <class PointType, class LabelType>
52template <std::floating_point ResultNumber, class Value>
53constexpr ResultNumber Segment<PointType, LabelType>::lowerCoordinateBound(const Value& value) {
54 if constexpr (requires { value.template lowerBound<ResultNumber>(); }) {
55 return value.template lowerBound<ResultNumber>();
56 } else {
57 return static_cast<ResultNumber>(value);
58 }
59}
60
61template <class PointType, class LabelType>
62template <std::floating_point ResultNumber, class Value>
63constexpr ResultNumber Segment<PointType, LabelType>::upperCoordinateBound(const Value& value) {
64 if constexpr (requires { value.template upperBound<ResultNumber>(); }) {
65 return value.template upperBound<ResultNumber>();
66 } else {
67 return static_cast<ResultNumber>(value);
68 }
69}
70
71template <class PointType, class LabelType>
73 if (min().y() < max().y()) {
74 return Rectangle<PointType>(min().x(), min().y(), max().x(), max().y(), true);
75 }
76 return Rectangle<PointType>(min().x(), max().y(), max().x(), min().y(), true);
77}
78
79template <class PointType, class LabelType>
80template <std::floating_point ResultNumber>
82 ResultNumber xmin = lowerCoordinateBound<ResultNumber>(min().x());
83 ResultNumber ymin = lowerCoordinateBound<ResultNumber>(min().y());
84 ResultNumber xmax = upperCoordinateBound<ResultNumber>(max().x());
85 ResultNumber ymax = upperCoordinateBound<ResultNumber>(max().y());
86 if (ymin > ymax) {
87 std::swap(ymin, ymax);
88 }
89 return Rectangle<Point<ResultNumber>>(xmin, ymin, xmax, ymax, true);
90}
91
92template <class PointType, class LabelType>
93constexpr std::array<PointType, 2> Segment<PointType, LabelType>::vertices() const {
94 return {min(), max()};
95}
96
97template <class PointType, class LabelType>
98constexpr std::array<Segment<PointType, LabelType>, 1> Segment<PointType, LabelType>::edges() const {
99 return {*this};
100}
101
102template <class PointType, class LabelType>
103constexpr std::array<OrientedSegment<PointType>, 1> Segment<PointType, LabelType>::orientedEdges() const {
104 return {OrientedSegment<PointType>(min(), max())};
105}
106
107// -----------------------------------------------------------------------------
108// OrientedSegment
109
110template <class PointType, class LabelType>
112 return static_cast<Segment<PointType>>(*this).bbox();
113}
114
115template <class PointType, class LabelType>
116template <std::floating_point ResultNumber>
120
121template <class PointType, class LabelType>
122constexpr std::array<PointType, 2> OrientedSegment<PointType, LabelType>::vertices() const {
123 return {source(), target()};
124}
125
126template <class PointType, class LabelType>
127constexpr std::array<Segment<PointType>, 1> OrientedSegment<PointType, LabelType>::edges() const {
128 return {static_cast<Segment<PointType>>(*this)};
129}
130
131template <class PointType, class LabelType>
132constexpr std::array<OrientedSegment<PointType, LabelType>, 1> OrientedSegment<PointType, LabelType>::orientedEdges() const {
133 return {*this};
134}
135
136// -----------------------------------------------------------------------------
137// Rectangle
138
139template <class PointType, class LabelType>
143
144template <class PointType, class LabelType>
145template <std::floating_point ResultNumber>
148 detail::lowerFloatingBound<ResultNumber>(min().x()),
149 detail::lowerFloatingBound<ResultNumber>(min().y()),
150 detail::upperFloatingBound<ResultNumber>(max().x()),
151 detail::upperFloatingBound<ResultNumber>(max().y()),
152 true);
153}
154
155template <class PointType, class LabelType>
156constexpr typename Rectangle<PointType, LabelType>::PointType Rectangle<PointType, LabelType>::bottomRight() const {
157 return makeCorner(max().x(), min().y());
158}
159
160template <class PointType, class LabelType>
161constexpr typename Rectangle<PointType, LabelType>::PointType Rectangle<PointType, LabelType>::topLeft() const {
162 return makeCorner(min().x(), max().y());
163}
164
165template <class PointType, class LabelType>
166template <bool Oriented>
167constexpr typename Rectangle<PointType, LabelType>::template BoundaryType<Oriented> Rectangle<PointType, LabelType>::boundaryAt(std::size_t index) const {
168 assert(index < size());
169
170 const auto bottom_left = min();
171 const auto bottom_right = bottomRight();
172 const auto top_right = max();
173 const auto top_left = topLeft();
174
175 switch (index) {
176 case 0:
177 return BoundaryType<Oriented>(bottom_left, bottom_right);
178 case 1:
179 return BoundaryType<Oriented>(bottom_right, top_right);
180 case 2:
181 return BoundaryType<Oriented>(top_right, top_left);
182 default:
183 return BoundaryType<Oriented>(top_left, bottom_left);
184 }
185}
186
187template <class PointType, class LabelType>
188constexpr std::array<typename Rectangle<PointType, LabelType>::PointType, 4> Rectangle<PointType, LabelType>::vertices() const {
189 assert(!empty());
190 return {
191 min(),
192 bottomRight(),
193 max(),
194 topLeft(),
195 };
196}
197
198template <class PointType, class LabelType>
199constexpr std::array<Segment<PointType>, 4> Rectangle<PointType, LabelType>::edges() const {
200 assert(!empty());
201 return {
202 boundaryAt<false>(0),
203 boundaryAt<false>(1),
204 boundaryAt<false>(2),
205 boundaryAt<false>(3),
206 };
207}
208
209template <class PointType, class LabelType>
210constexpr std::array<OrientedSegment<PointType>, 4> Rectangle<PointType, LabelType>::orientedEdges() const {
211 assert(!empty());
212 return {
213 boundaryAt<true>(0),
214 boundaryAt<true>(1),
215 boundaryAt<true>(2),
216 boundaryAt<true>(3),
217 };
218}
219
220// -----------------------------------------------------------------------------
221// Triangle
222
223template <class PointType, class LabelType>
227
228template <class PointType, class LabelType>
229template <std::floating_point ResultNumber>
233
234template <class PointType, class LabelType>
235constexpr std::array<PointType, 3> Triangle<PointType, LabelType>::vertices() const {
236 return points_;
237}
238
239template <class PointType, class LabelType>
240constexpr std::array<Segment<PointType>, 3> Triangle<PointType, LabelType>::edges() const {
241 return {
242 Segment<PointType>(a(), b()),
243 Segment<PointType>(b(), c()),
244 Segment<PointType>(c(), a()),
245 };
246}
247
248template <class PointType, class LabelType>
249constexpr std::array<OrientedSegment<PointType>, 3> Triangle<PointType, LabelType>::orientedEdges() const {
250 return {
254 };
255}
256
257// template <class PointType>
258// template <std::ranges::input_range Range>
259// requires std::constructible_from<PointType, std::ranges::range_reference_t<Range>>
260// constexpr void Rectangle<PointType, LabelType>::assignBoundingBox(Range&& points) {
261// auto iterator = std::ranges::begin(points);
262// const auto sentinel = std::ranges::end(points);
263//
264// if (iterator == sentinel) {
265// throw std::invalid_argument("Rectangle bounding box requires at least one point");
266// }
267//
268// PointType min_corner(*iterator);
269// PointType max_corner(*iterator);
270// std::optional<PointType> exact_min_corner(min_corner);
271// std::optional<PointType> exact_max_corner(max_corner);
272// ++iterator;
273//
274// for (; iterator != sentinel; ++iterator) {
275// const PointType point(*iterator);
276// const PointType previous_min = min_corner;
277// const PointType previous_max = max_corner;
278//
279// if (point.x() < min_corner.x()) {
280// min_corner = makeCorner(point.x(), min_corner.y());
281// }
282// if (point.y() < min_corner.y()) {
283// min_corner = makeCorner(min_corner.x(), point.y());
284// }
285// if (max_corner.x() < point.x()) {
286// max_corner = makeCorner(point.x(), max_corner.y());
287// }
288// if (max_corner.y() < point.y()) {
289// max_corner = makeCorner(max_corner.x(), point.y());
290// }
291//
292// if (point.x() == min_corner.x() && point.y() == min_corner.y()) {
293// exact_min_corner = point;
294// } else if (previous_min != min_corner) {
295// exact_min_corner.reset();
296// }
297//
298// if (point.x() == max_corner.x() && point.y() == max_corner.y()) {
299// exact_max_corner = point;
300// } else if (previous_max != max_corner) {
301// exact_max_corner.reset();
302// }
303// }
304//
305// points_[0] = exact_min_corner.has_value() ? std::move(*exact_min_corner) : std::move(min_corner);
306// points_[1] = exact_max_corner.has_value() ? std::move(*exact_max_corner) : std::move(max_corner);
307// }
308
309template <class PointType, class LabelType>
310template <PointConcept OtherPoint>
311constexpr void Rectangle<PointType, LabelType>::insert(const OtherPoint& point) {
312 const NumberType x = static_cast<NumberType>(point.x());
313 const NumberType y = static_cast<NumberType>(point.y());
314
315 if (empty()) {
316 // The empty rectangle bounds nothing, so it cannot be grown: it becomes
317 // the inserted point outright.
318 points_[0] = points_[1] = makeCorner(x, y);
319 return;
320 }
321
322 const PointType old_min = min();
323 const PointType old_max = max();
324
325 NumberType min_x = old_min.x();
326 NumberType min_y = old_min.y();
327 NumberType max_x = old_max.x();
328 NumberType max_y = old_max.y();
329
330 if (x < min_x) {
331 min_x = x;
332 }
333 if (y < min_y) {
334 min_y = y;
335 }
336 if (max_x < x) {
337 max_x = x;
338 }
339 if (max_y < y) {
340 max_y = y;
341 }
342
343 points_[0] = (min_x == old_min.x() && min_y == old_min.y())
344 ? old_min
345 : makeCorner(min_x, min_y);
346 points_[1] = (max_x == old_max.x() && max_y == old_max.y())
347 ? old_max
348 : makeCorner(max_x, max_y);
349}
350
351template <class PointType, class LabelType>
352template <RectangleConcept OtherRectangle>
353constexpr void Rectangle<PointType, LabelType>::insert(const OtherRectangle& other) {
354 if (other.empty()) {
355 // Its corners are inverted placeholders, not points to enclose.
356 return;
357 }
358 insert(other.min());
359 insert(other.max());
360}
362template <class PointType, class LabelType>
363template <class TShape>
364 requires(!detail::is_point_v<TShape> && !RectangleConcept<TShape> && requires(const TShape& shape) { shape.bbox(); })
365constexpr void Rectangle<PointType, LabelType>::insert(const TShape& shape) {
366 insert(shape.bbox());
367}
369
370// ---------------------------------------------------------------------------
371// Convex
372
373template <class PointType, class LabelType>
375 if (!bbox_.empty()) {
376 return bbox_;
377 }
378 if (points_.empty()) {
379 return bbox_ = {};
380 }
381 if (points_.size() <= 6) {
382 return bbox_ = Rectangle<PointType>(points_) + translation_;
383 }
385 // Find the peak of a plain unimodal range [first, last): the keys ascend
386 // weakly to a single maximum, then descend weakly. O(log n) binary search.
387 const auto unimodalMax = [](auto first, auto last, auto key) {
388 auto lo = first;
389 auto hi = last - 1;
390 while (lo < hi) {
391 const auto mid = lo + (hi - lo) / 2;
392 if (key(*mid) < key(*(mid + 1)))
393 lo = mid + 1;
394 else
395 hi = mid;
396 }
397 return lo;
398 };
399
400 // The boundary splits at its leftmost (points_[0]) and rightmost (maxIndex())
401 // vertices into two x-monotone chains. On each chain y is plain unimodal (the
402 // split removes the rotation cyclicMax would otherwise have to handle). The
403 // lower chain [0, mi] is contiguous; the upper chain [mi, n) wraps back to
404 // points_[0], so that vertex is folded into the max_y candidate explicitly.
405 const NumberType min_x = points_[0].x();
406 const auto mi = maxIndex();
407 const NumberType max_x = points_[mi].x();
408 const NumberType min_y = unimodalMax(points_.begin(), points_.begin() + mi + 1,
409 [](const PointType& p) { return -p.y(); })->y();
410 const NumberType max_y = std::max(
411 unimodalMax(points_.begin() + mi, points_.end(),
412 [](const PointType& p) { return p.y(); })->y(),
413 points_[0].y());
414
415 return bbox_ = Rectangle<PointType>(min_x, min_y, max_x, max_y, true) + translation_;
416}
417
418template <class PointType, class LabelType>
419template <std::floating_point ResultNumber>
423
424template <class PointType, class LabelType>
425template <PointConcept OtherPoint>
426constexpr void Convex<PointType, LabelType>::insert(const OtherPoint& point) {
427 const PointType vertex = static_cast<PointType>(point);
428 if (contains(vertex)) {
429 return;
430 }
431 std::vector<PointType> points = vertices();
432 points.push_back(vertex);
433 rebuildHull(points);
434}
435
436template <class PointType, class LabelType>
437template <class TShape>
438 requires(!detail::is_point_v<TShape> && requires(const TShape& shape) { shape.vertices(); })
439constexpr void Convex<PointType, LabelType>::insert(const TShape& shape) {
440 // The hull of a shape is the hull of its vertices, so the point-range
441 // overload does the work.
442 insert(shape.vertices());
443}
444
445// ---------------------------------------------------------------------------
446// Polygon
447
448template <class PointType, class LabelType>
450 if (!bbox_.empty()) {
451 return bbox_;
452 }
453 if (points_.empty()) {
454 return bbox_ = {};
455 }
456 return bbox_ = Rectangle<PointType>(points_) + translation_;
457}
458
459template <class PointType, class LabelType>
460template <std::floating_point ResultNumber>
464
465// ---------------------------------------------------------------------------
466// PolygonSet
467
468template <class PointType, class LabelType>
470 if (!bbox_.empty()) {
471 return bbox_;
472 }
473 if (components_.empty()) {
474 return bbox_ = {};
475 }
476 // Every hole lies inside its own component's outer ring, so the components'
477 // own boxes — each of them its outer ring's — already cover every vertex.
478 Rectangle<PointType> box = components_.front().bbox();
479 for (std::size_t i = 1; i < components_.size(); ++i) {
480 box.insert(components_[i].bbox());
481 }
482 return bbox_ = box;
483}
484
485template <class PointType, class LabelType>
486template <std::floating_point ResultNumber>
490
491// ---------------------------------------------------------------------------
492// MonotoneChain
493
494template <class PointType, class LabelType, class Storage>
496 if (!bbox_.empty()) {
497 return bbox_;
498 }
499 if (points_.empty()) {
500 return bbox_ = {};
501 }
502 return bbox_ = Rectangle<PointType>(points_) + translation_;
503}
504
505template <class PointType, class LabelType, class Storage>
506template <std::floating_point ResultNumber>
510
511// ---------------------------------------------------------------------------
512// Polyline
513
514template <class PointType, class LabelType>
516 if (!bbox_.empty()) {
517 return bbox_;
518 }
519 if (points_.empty()) {
520 return bbox_ = {};
521 }
522 return bbox_ = Rectangle<PointType>(points_) + translation_;
523}
524
525template <class PointType, class LabelType>
526template <std::floating_point ResultNumber>
530
531
532// ---------------------------------------------------------------------------
533// HalfplaneIntersection
534
535template <class PointType, class LabelType>
536template <class ResultNumber>
540 if (empty() || !isBounded()) {
541 throw std::logic_error("HalfplaneIntersection::bbox is only defined for a nonempty bounded region");
542 }
543 using C = detail::promoted_number_t<detail::promoted_number_t<NumberType>>;
544 struct Fraction {
545 C num;
546 C den; // positive
547 };
548 // The extreme point in an outward normal direction a = (dy, -dx) sits
549 // where the stored boundary directions bracket the query direction
550 // (dx, dy) — the same bracketing as supStatus, but producing the extreme
551 // coordinate as an exact fraction. O(log n) per direction.
552 const auto extreme = [&](NumberType dx, NumberType dy, bool wantX) -> Fraction {
553 const HalfplaneType query(PointType(NumberType(0), NumberType(0)), PointType(dx, dy));
554 const std::size_t n = halfplanes_.size();
555 const std::size_t pos = linearUpperBound(query);
556 const std::size_t predIdx = (pos == 0 ? n : pos) - 1;
557 const auto& pred = halfplanes_[predIdx];
558 if (detail::directionEqual(pred, query)) {
559 // Attained along an axis-parallel edge, where the wanted
560 // coordinate is constant.
561 return {static_cast<C>(wantX ? pred.source().x() : pred.source().y()), C(1)};
562 }
563 const auto& succ = halfplanes_[pos == n ? 0 : pos];
564 // Vertex of the two boundary lines a_i · v = b_i.
565 const auto row = [](const HalfplaneType& h) {
566 const C sx = static_cast<C>(h.source().x());
567 const C sy = static_cast<C>(h.source().y());
568 const C tx = static_cast<C>(h.target().x());
569 const C ty = static_cast<C>(h.target().y());
570 struct Row { C ax, ay, b; };
571 return Row{ty - sy, sx - tx, sx * ty - sy * tx};
572 };
573 const auto r1 = row(pred);
574 const auto r2 = row(succ);
575 const C den = r1.ax * r2.ay - r1.ay * r2.ax; // positive: bounded gaps are below pi
576 assert(den > C(0));
577 if (wantX) {
578 return {r1.b * r2.ay - r2.b * r1.ay, den};
579 }
580 return {r1.ax * r2.b - r2.ax * r1.b, den};
581 };
582 // Outward normals +x, -x, +y, -y correspond to boundary directions
583 // (0, 1), (0, -1), (-1, 0), (1, 0).
584 const Fraction xMax = extreme(NumberType(0), NumberType(1), true);
585 const Fraction xMin = extreme(NumberType(0), NumberType(-1), true);
586 const Fraction yMax = extreme(NumberType(-1), NumberType(0), false);
587 const Fraction yMin = extreme(NumberType(1), NumberType(0), false);
588 const auto convert = [](const Fraction& f, bool roundUp) -> ResultNumber {
589 if constexpr (std::is_floating_point_v<ResultNumber>) {
590 (void)roundUp;
591 return detail::asNumber<ResultNumber>(f.num) / detail::asNumber<ResultNumber>(f.den);
592 } else if constexpr (is_Rational_v<ResultNumber>) {
593 // Exact when the fraction fits the rational's storage type.
594 (void)roundUp;
595 return detail::asNumber<ResultNumber>(f.num) / detail::asNumber<ResultNumber>(f.den);
596 } else if constexpr (is_Rational_v<C> || std::is_floating_point_v<C>) {
597 // Exact (Rational) or approximate (floating) coordinates: divide
598 // in the working type and convert; no outward rounding applies.
599 (void)roundUp;
600 return static_cast<ResultNumber>(f.num / f.den);
601 } else {
602 // Integer coordinates and result: round outward so the box
603 // encloses the region.
604 C quotient = f.num / f.den;
605 const C remainder = f.num % f.den;
606 if (remainder != C(0)) {
607 if (roundUp && f.num > C(0)) {
608 ++quotient;
609 }
610 if (!roundUp && f.num < C(0)) {
611 --quotient;
612 }
613 }
614 return static_cast<ResultNumber>(quotient);
615 }
616 };
617 return Rectangle<ResultPoint>(ResultPoint(convert(xMin, false), convert(yMin, false)),
618 ResultPoint(convert(xMax, true), convert(yMax, true)));
619}
620
621template <class PointType, class LabelType>
622template <std::floating_point ResultNumber>
624 const auto box = bbox<ResultNumber>();
625 return Rectangle<Point<ResultNumber>>(Point<ResultNumber>(box.min().x(), box.min().y()),
626 Point<ResultNumber>(box.max().x(), box.max().y()));
627}
628
629} // namespace pgl
Definition forward.hpp:313
Geometric measurements and canonical representative-point helpers.
Definition arrangement.hpp:67
@ y
Definition intervaltree.hpp:24
@ x
Definition intervaltree.hpp:24
Rectangle() -> Rectangle< Point<>, NoLabel >
Definition rectangle.hpp:2384
constexpr bool is_Rational_v
Definition rational.hpp:37
@ vertex
Definition bitmatrix.hpp:37
Point() -> Point< int >
OrientedSegment() -> OrientedSegment< Point<>, NoLabel >
Public declaration of pgl::Rectangle.
constexpr const Rectangle< PointType > & bbox() const
Computes the bounding box of the convex polygon.
Definition bounding.hpp:374
constexpr Rectangle< Point< ResultNumber > > fbox() const
Computes the floating-point bounding box of the convex polygon.
Definition bounding.hpp:420
constexpr void insert(const OtherPoint &point)
Enlarges the convex polygon so that it contains the given point.
Definition bounding.hpp:426
constexpr bool contains(const OtherPoint &point) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition contains.hpp:1135
constexpr const std::vector< PointType > vertices() const
Returns the vertices of the convex polygon.
Definition convex.hpp:508
PointType_ PointType
Definition convex.hpp:171
constexpr Rectangle< Point< ResultNumber, typename PointType::LabelType > > bbox() const
Computes the bounding box of the region.
Definition bounding.hpp:538
Halfplane< PointType > HalfplaneType
Definition halfplaneintersection.hpp:248
constexpr bool empty() const
Returns whether the region is the empty set.
Definition halfplaneintersection.hpp:649
constexpr bool isBounded() const
Returns whether the region is bounded.
Definition halfplaneintersection.hpp:811
PointType_ PointType
Definition halfplaneintersection.hpp:245
PointType::NumberType NumberType
Definition halfplaneintersection.hpp:246
constexpr Rectangle< Point< ResultNumber > > fbox() const
Computes the floating-point bounding box of the region.
Definition bounding.hpp:623
constexpr Rectangle< Point< ResultNumber > > fbox() const
Computes the floating-point bounding box of the chain.
Definition bounding.hpp:507
constexpr const Rectangle< PointType > & bbox() const
Computes the bounding box of the chain.
Definition bounding.hpp:495
constexpr std::array< OrientedSegment, 1 > orientedEdges() const
Returns the unique oriented edge of the oriented segment.
Definition bounding.hpp:132
constexpr Rectangle< PointType > bbox() const
Returns the bounding box of the oriented segment.
Definition bounding.hpp:111
constexpr const PointType & source() const
Returns the source endpoint.
Definition orientedsegment.hpp:178
constexpr Rectangle< Point< ResultNumber > > fbox() const
Returns a bounding box of the oriented segment with floating point coordinates.
Definition bounding.hpp:117
constexpr const PointType & target() const
Returns the target endpoint.
Definition orientedsegment.hpp:190
constexpr std::array< Segment< PointType >, 1 > edges() const
Returns the unique geometric edge of the oriented segment.
Definition bounding.hpp:127
constexpr std::array< PointType, 2 > vertices() const
Returns the two endpoints in source-to-target order.
Definition bounding.hpp:122
Two-dimensional point with optional label payload.
Definition point.hpp:129
constexpr std::array< Point, 1 > vertices() const
Returns the unique vertex of the point-shaped object.
Definition bounding.hpp:34
constexpr Rectangle< Point< ResultNumber > > fbox() const
Returns a floating-point bounding box containing the point.
Definition bounding.hpp:24
constexpr std::array< OrientedSegment< Point >, 0 > orientedEdges() const
Returns the oriented boundary edges.
Definition bounding.hpp:44
constexpr Rectangle< Point > bbox() const
Returns the bounding box of the point.
Definition bounding.hpp:18
constexpr std::array< Segment< Point >, 0 > edges() const
Returns the point boundary edges.
Definition bounding.hpp:39
constexpr Rectangle< Point< ResultNumber > > fbox() const
Computes the floating-point bounding box of the set.
Definition bounding.hpp:487
constexpr const Rectangle< PointType > & bbox() const
Computes the bounding box of the set.
Definition bounding.hpp:469
constexpr const Rectangle< PointType > & bbox() const
Computes the bounding box of the polygon.
Definition bounding.hpp:449
constexpr Rectangle< Point< ResultNumber > > fbox() const
Computes the floating-point bounding box of the polygon.
Definition bounding.hpp:461
constexpr const Rectangle< PointType > & bbox() const
Computes the bounding box of the polyline.
Definition bounding.hpp:515
constexpr Rectangle< Point< ResultNumber > > fbox() const
Computes the floating-point bounding box of the polyline.
Definition bounding.hpp:527
Axis-aligned rectangle stored by minimum and maximum corners.
Definition rectangle.hpp:75
std::conditional_t< Oriented, OrientedSegment< PointType >, Segment< PointType > > BoundaryType
Definition rectangle.hpp:88
constexpr Rectangle< Point< ResultNumber > > fbox() const
Returns a bounding box of the rectangle with floating point coordinates.
Definition bounding.hpp:146
PointType::NumberType NumberType
Definition rectangle.hpp:77
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< OrientedSegment< PointType >, 4 > orientedEdges() const
Returns the four boundary edges in counterclockwise order.
Definition bounding.hpp:210
constexpr std::array< Segment< PointType >, 4 > edges() const
Returns the four edges as unordered segments.
Definition bounding.hpp:199
constexpr std::array< PointType, 4 > vertices() const
Returns the four vertices in counterclockwise order.
Definition bounding.hpp:188
constexpr std::ptrdiff_t index(const PointType &point) const
Definition rectangle.hpp:330
PointType_ PointType
Definition rectangle.hpp:76
constexpr const PointType & max() const
Returns the maximum corner (max x, max y).
Definition rectangle.hpp:359
constexpr std::size_t size() const
Definition rectangle.hpp:307
constexpr Rectangle()
Creates the empty rectangle [(0,0),(-1,-1)].
Definition rectangle.hpp:120
constexpr void insert(const OtherPoint &point)
Enlarges the rectangle so that it contains the given point.
Definition bounding.hpp:311
constexpr Rectangle bbox() const
Returns the bounding box of the rectangle.
Definition bounding.hpp:140
Unoriented closed segment between two endpoints plus optional segment label.
Definition segment.hpp:58
constexpr Rectangle< Point< ResultNumber > > fbox() const
Returns a bounding box of the segment with floating point coordinates.
Definition bounding.hpp:81
constexpr std::array< PointType, 2 > vertices() const
Returns the two endpoints in canonical order.
Definition bounding.hpp:93
constexpr Rectangle< PointType > bbox() const
Returns the bounding box of the segment.
Definition bounding.hpp:72
constexpr std::array< Segment, 1 > edges() const
Returns the unique boundary edge of the segment.
Definition bounding.hpp:98
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 std::array< OrientedSegment< PointType >, 1 > orientedEdges() const
Returns the unique oriented boundary edge in canonical order.
Definition bounding.hpp:103
constexpr const PointType & b() const
Returns the second vertex.
Definition triangle.hpp:217
constexpr std::array< PointType, 3 > vertices() const
Returns the vertices in canonical order.
Definition bounding.hpp:235
constexpr const PointType & a() const
Returns the first vertex.
Definition triangle.hpp:208
constexpr Rectangle< PointType > bbox() const
Returns the axis-aligned bounding box of the vertices.
Definition bounding.hpp:224
constexpr Rectangle< Point< ResultNumber > > fbox() const
Returns a floating-point bounding box containing the triangle.
Definition bounding.hpp:230
constexpr std::array< Segment< PointType >, 3 > edges() const
Returns the three unoriented boundary edges.
Definition bounding.hpp:240
constexpr const PointType & c() const
Returns the third vertex.
Definition triangle.hpp:226
constexpr std::array< OrientedSegment< PointType >, 3 > orientedEdges() const
Returns the three oriented boundary edges.
Definition bounding.hpp:249