Pangolin
Header-only C++20 plane computational geometry library
Loading...
Searching...
No Matches
emptyshape.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "shape/point.hpp"
4
15
16#include <compare>
17#include <cstddef>
18#include <ostream>
19#include <stdexcept>
20#include <type_traits>
21#include <utility>
22
23
24namespace pgl {
25
32template <class PointType_ = Point<>>
33struct EmptyShape {
34 using PointType = PointType_;
37
41 constexpr EmptyShape() = default;
42
46 [[nodiscard]] constexpr bool operator==(const EmptyShape&) const = default;
48 [[nodiscard]] constexpr auto operator<=>(const EmptyShape&) const = default;
49
51 template<AnyShapeConcept OtherShape>
52 [[nodiscard]] constexpr bool samePointSet(const OtherShape& other) const;
53
57 [[nodiscard]] static constexpr std::size_t size() {
58 return 0;
59 }
60
64 [[nodiscard]] constexpr bool isDegenerate() const {
65 return false;
66 }
67
76 [[nodiscard]] constexpr bool isUndefined() const {
77 return false;
78 }
79
83 [[nodiscard]] PointType get(std::ptrdiff_t) const {
84 throw std::logic_error("EmptyShape::get: the empty shape has no vertices");
85 }
86
90 [[nodiscard]] PointType operator[](std::size_t) const {
91 throw std::logic_error("EmptyShape::operator[]: the empty shape has no vertices");
92 }
93
97 template <class T>
98 [[nodiscard]] std::ptrdiff_t index(const T&) const {
99 throw std::logic_error("EmptyShape::index: the empty shape has no vertices");
100 }
101
102 // The empty set is a subset of every shape, so it contains only the empty
103 // set itself: containment of any non-empty shape is false, while containment
104 // of another empty shape is true.
105 //
106 // "Another empty shape" is not only an EmptyShape. A default-constructed
107 // Rectangle, Convex, Polygon, PolygonWithHoles, PolygonSet,
108 // HalfplaneIntersection, MonotoneChain or Polyline is the empty set too, and
109 // each answers so through `empty()` -- so the generic overloads ask, rather
110 // than assuming that anything of another type covers a point. The shapes
111 // that can never be empty (a Point, Segment, Line, Ray, Halfplane, Triangle
112 // or Disk always cover at least one point) have no `empty()` and take the
113 // constant-false branch.
114
116 template <class T>
117 [[nodiscard]] constexpr bool contains(const T& other) const {
118 if constexpr (requires { other.empty(); }) {
119 return other.empty();
120 } else {
121 return false;
122 }
123 }
124
125 template <PointConcept OtherPoint>
126 [[nodiscard]] constexpr bool contains(const EmptyShape<OtherPoint>&) const {
127 return true;
128 }
129
131 template <class T>
132 [[nodiscard]] constexpr bool boundaryContains(const T& other) const {
133 // The boundary of the empty set is the empty set.
134 if constexpr (requires { other.empty(); }) {
135 return other.empty();
136 } else {
137 return false;
138 }
139 }
140
141 template <PointConcept OtherPoint>
142 [[nodiscard]] constexpr bool boundaryContains(const EmptyShape<OtherPoint>&) const {
143 return true;
144 }
145
147 template <class T>
148 [[nodiscard]] constexpr bool interiorContains(const T& other) const {
149 // The interior of the empty set is the empty set.
150 if constexpr (requires { other.empty(); }) {
151 return other.empty();
152 } else {
153 return false;
154 }
155 }
156
157 template <PointConcept OtherPoint>
158 [[nodiscard]] constexpr bool interiorContains(const EmptyShape<OtherPoint>&) const {
159 return true;
160 }
161
163 template <class T>
164 [[nodiscard]] constexpr bool intersects(const T&) const {
165 return false;
166 }
167
169 template <class T>
170 [[nodiscard]] constexpr bool interiorsIntersect(const T&) const {
171 return false;
172 }
173
175 template <class T>
176 [[nodiscard]] constexpr bool separates(const T&) const {
177 return false;
178 }
179
181 template <class T>
182 [[nodiscard]] constexpr bool crosses(const T&) const {
183 return false;
184 }
185
187 template <class ResultNumber = NumberType, class T>
188 [[nodiscard]] constexpr EmptyShape intersection(const T&) const {
189 return EmptyShape{};
190 }
191
205 template <class OtherShape>
207 [[nodiscard]] constexpr auto minkowskiSum(const OtherShape& other) const;
208
232 template <class OtherShape>
234 [[nodiscard]] constexpr auto minkowskiErosion(const OtherShape& other) const;
235
243 template <PointConcept OtherPoint>
244 constexpr EmptyShape& operator+=(const OtherPoint&) {
245 return *this;
246 }
247
255 template <PointConcept OtherPoint>
256 constexpr EmptyShape& operator-=(const OtherPoint&) {
257 return *this;
258 }
259
267 template <class Scalar>
268 requires(!detail::is_point_v<Scalar> && !TransformationConcept<Scalar>)
269 constexpr EmptyShape& operator*=(const Scalar&) {
270 return *this;
271 }
272
280 template <class Scalar>
281 requires(!detail::is_point_v<Scalar> && !TransformationConcept<Scalar>)
282 constexpr EmptyShape& operator/=(const Scalar&) {
283 return *this;
284 }
285
287 [[nodiscard]] constexpr EmptyShape rotated90(int = 1) const {
288 return *this;
289 }
290
292 constexpr void rotate90(int = 1) {}
293
295 template <class OtherNumber>
296 [[nodiscard]] constexpr EmptyShape scaledUpX(const OtherNumber) const {
297 return *this;
298 }
299
301 template <class OtherNumber>
302 constexpr void scaleUpX(const OtherNumber) {}
303
305 template <class OtherNumber>
306 [[nodiscard]] constexpr EmptyShape scaledUpY(const OtherNumber) const {
307 return *this;
308 }
309
311 template <class OtherNumber>
312 constexpr void scaleUpY(const OtherNumber) {}
313
315 template <class OtherNumber>
316 [[nodiscard]] constexpr EmptyShape scaledDownX(const OtherNumber) const {
317 return *this;
318 }
319
321 template <class OtherNumber>
322 constexpr void scaleDownX(const OtherNumber) {}
323
325 template <class OtherNumber>
326 [[nodiscard]] constexpr EmptyShape scaledDownY(const OtherNumber) const {
327 return *this;
328 }
329
331 template <class OtherNumber>
332 constexpr void scaleDownY(const OtherNumber) {}
333};
334
344template <class PointType, class TranslationNumber, class TranslationLabel>
345constexpr auto operator-(const EmptyShape<PointType>&,
347 using ResultPoint = std::decay_t<decltype(std::declval<const PointType&>() -
348 std::declval<const Point<TranslationNumber, TranslationLabel>&>())>;
350}
351
361template <class PointType, class Scalar>
362 requires(!detail::is_point_v<Scalar> && !TransformationConcept<Scalar>)
363constexpr auto operator*(const EmptyShape<PointType>&, const Scalar&) {
364 using ResultPoint = std::decay_t<decltype(std::declval<const PointType&>() *
365 std::declval<const Scalar&>())>;
367}
368
370template <class Scalar, class PointType>
371 requires(!detail::is_point_v<Scalar> && !TransformationConcept<Scalar>)
372constexpr auto operator*(const Scalar& scalar, const EmptyShape<PointType>& empty) {
373 return empty * scalar;
374}
375
385template <class PointType, class Scalar>
386 requires(!detail::is_point_v<Scalar> && !TransformationConcept<Scalar>)
387constexpr auto operator/(const EmptyShape<PointType>&, const Scalar&) {
388 using ResultPoint = std::decay_t<decltype(std::declval<const PointType&>() /
389 std::declval<const Scalar&>())>;
391}
392
399template <class PointType>
400std::ostream& operator<<(std::ostream& stream, const EmptyShape<PointType>&) {
401 return stream << "EmptyShape()";
402}
403
404} // namespace pgl
Shape pairs whose Minkowski sum Pangolin can represent.
Definition forward.hpp:476
Definition forward.hpp:324
Definition arrangement.hpp:67
constexpr auto operator-(const Point< LeftNumber, LeftLabel > &left, const Point< RightNumber, RightLabel > &right)
Translates a point by the opposite of another point.
Definition transformations.hpp:130
std::ostream & operator<<(std::ostream &stream, const Point< Number, Label > &point)
Streams a point as (x,y) or label:(x,y).
Definition io.hpp:27
Public declaration of pgl::Point and point-label helpers.
The empty set of points in the plane.
Definition emptyshape.hpp:33
constexpr EmptyShape intersection(const T &) const
Returns the intersection of the two shapes (A ∩ B), empty when they are disjoint.
Definition emptyshape.hpp:188
constexpr bool contains(const T &other) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition emptyshape.hpp:117
constexpr EmptyShape rotated90(int=1) const
Returns the empty shape rotated by 90k degrees; a no-op.
Definition emptyshape.hpp:287
constexpr bool separates(const T &) const
Tests whether removing this shape disconnects the other shape (B∖A is disconnected).
Definition emptyshape.hpp:176
typename PointType::LabelType LabelType
Definition emptyshape.hpp:36
constexpr EmptyShape & operator-=(const OtherPoint &)
Translates the empty shape in place by a negated point; a no-op.
Definition emptyshape.hpp:256
constexpr auto minkowskiSum(const OtherShape &other) const
Returns the Minkowski sum of this shape and another (A ⊕ B).
Definition minkowski.hpp:881
constexpr auto operator<=>(const EmptyShape &) const =default
Three-way comparison: all empty shapes are equivalent.
constexpr bool interiorContains(const EmptyShape< OtherPoint > &) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition emptyshape.hpp:158
constexpr bool operator==(const EmptyShape &) const =default
All empty shapes are equal and unordered among themselves.
EPoint PointType
Definition emptyshape.hpp:34
constexpr bool contains(const EmptyShape< OtherPoint > &) const
Tests whether this shape contains the other shape (A ⊇ B).
Definition emptyshape.hpp:126
typename PointType::NumberType NumberType
Definition emptyshape.hpp:35
constexpr bool intersects(const T &) const
Tests whether this shape and the other shape intersect (A ∩ B ≠ ∅).
Definition emptyshape.hpp:164
static constexpr std::size_t size()
Returns the number of vertices, always 0.
Definition emptyshape.hpp:57
constexpr EmptyShape scaledDownX(const OtherNumber) const
Returns the empty shape with its x-coordinates scaled down; a no-op.
Definition emptyshape.hpp:316
constexpr EmptyShape & operator+=(const OtherPoint &)
Translates the empty shape in place; a no-op.
Definition emptyshape.hpp:244
PointType get(std::ptrdiff_t) const
Always throws: the empty shape has no vertices.
Definition emptyshape.hpp:83
constexpr void scaleDownX(const OtherNumber)
Scales the empty shape's x-coordinates down in place; a no-op.
Definition emptyshape.hpp:322
constexpr bool boundaryContains(const T &other) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition emptyshape.hpp:132
std::ptrdiff_t index(const T &) const
Always throws: the empty shape has no vertices.
Definition emptyshape.hpp:98
constexpr bool isDegenerate() const
The empty shape is never degenerate.
Definition emptyshape.hpp:64
constexpr void scaleUpY(const OtherNumber)
Scales the empty shape's y-coordinates up in place; a no-op.
Definition emptyshape.hpp:312
constexpr EmptyShape scaledDownY(const OtherNumber) const
Returns the empty shape with its y-coordinates scaled down; a no-op.
Definition emptyshape.hpp:326
constexpr bool isUndefined() const
The empty shape is never undefined.
Definition emptyshape.hpp:76
PointType operator[](std::size_t) const
Always throws: the empty shape has no vertices.
Definition emptyshape.hpp:90
constexpr auto minkowskiErosion(const OtherShape &other) const
Returns the Minkowski erosion of this shape by another (A ⊖ B).
Definition minkowskierosion.hpp:655
constexpr bool boundaryContains(const EmptyShape< OtherPoint > &) const
Tests whether this shape's boundary contains the other shape (∂A ⊇ B).
Definition emptyshape.hpp:142
constexpr EmptyShape scaledUpX(const OtherNumber) const
Returns the empty shape with its x-coordinates scaled up; a no-op.
Definition emptyshape.hpp:296
constexpr bool interiorContains(const T &other) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition emptyshape.hpp:148
constexpr EmptyShape scaledUpY(const OtherNumber) const
Returns the empty shape with its y-coordinates scaled up; a no-op.
Definition emptyshape.hpp:306
constexpr EmptyShape()=default
Creates the (unique) empty shape.
constexpr void scaleDownY(const OtherNumber)
Scales the empty shape's y-coordinates down in place; a no-op.
Definition emptyshape.hpp:332
constexpr bool samePointSet(const OtherShape &other) const
Tests whether another shape defines the empty point set.
Definition samepointset.hpp:1941
constexpr void rotate90(int=1)
Rotates the empty shape by 90k degrees in place; a no-op.
Definition emptyshape.hpp:292
constexpr bool interiorsIntersect(const T &) const
Tests whether the interiors of the two shapes intersect ((A∖∂A) ∩ (B∖∂B) ≠ ∅).
Definition emptyshape.hpp:170
constexpr bool crosses(const T &) const
Tests whether the two shapes mutually separate each other (each disconnects the other).
Definition emptyshape.hpp:182
constexpr void scaleUpX(const OtherNumber)
Scales the empty shape's x-coordinates up in place; a no-op.
Definition emptyshape.hpp:302
Two-dimensional point with optional label payload.
Definition point.hpp:129
TLabel LabelType
Definition point.hpp:133
ERational NumberType
Definition point.hpp:131