Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
convex-hull.h
Go to the documentation of this file.
1/*
4 * Copyright 2006 Nathan Hurst <njh@mail.csse.monash.edu.au>
5 * Copyright 2006 Michael G. Sloan <mgsloan@gmail.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it either under the terms of the GNU Lesser General Public
9 * License version 2.1 as published by the Free Software Foundation
10 * (the "LGPL") or, at your option, under the terms of the Mozilla
11 * Public License Version 1.1 (the "MPL"). If you do not alter this
12 * notice, a recipient may use your version of this file under either
13 * the MPL or the LGPL.
14 *
15 * You should have received a copy of the LGPL along with this library
16 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * You should have received a copy of the MPL along with this library
19 * in the file COPYING-MPL-1.1
20 *
21 * The contents of this file are subject to the Mozilla Public License
22 * Version 1.1 (the "License"); you may not use this file except in
23 * compliance with the License. You may obtain a copy of the License at
24 * http://www.mozilla.org/MPL/
25 *
26 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28 * the specific language governing rights and limitations.
29 *
30 */
31
32#ifndef LIB2GEOM_SEEN_CONVEX_HULL_H
33#define LIB2GEOM_SEEN_CONVEX_HULL_H
34
35#include <algorithm>
36#include <optional>
37#include <vector>
38#include <boost/operators.hpp>
39#include <boost/range/iterator_range.hpp>
40#include <2geom/point.h>
41#include <2geom/rect.h>
42#include <2geom/transforms.h>
43
44namespace Geom {
45
46namespace {
47
51class ConvexHullLowerIterator
52 : public boost::random_access_iterator_helper
53 < ConvexHullLowerIterator
54 , Point
55 , std::ptrdiff_t
56 , Point const *
57 , Point const &
58 >
59{
60public:
61 using Self = ConvexHullLowerIterator;
62 ConvexHullLowerIterator() = default;
63 ConvexHullLowerIterator(std::vector<Point> const &pts, std::size_t x)
64 : _data(&pts[0])
65 , _size(pts.size())
66 , _x(x)
67 {}
68
69 Self &operator++() {
70 *this += 1;
71 return *this;
72 }
73 Self &operator--() {
74 *this -= 1;
75 return *this;
76 }
77 Self &operator+=(std::ptrdiff_t d) {
78 _x += d;
79 return *this;
80 }
81 Self &operator-=(std::ptrdiff_t d) {
82 _x -= d;
83 return *this;
84 }
85 std::ptrdiff_t operator-(Self const &other) const {
86 return _x - other._x;
87 }
88 Point const &operator*() const {
89 if (_x < _size) {
90 return _data[_x];
91 } else {
92 return *_data;
93 }
94 }
95 bool operator==(Self const &other) const {
96 return _data == other._data && _x == other._x;
97 }
98 bool operator<(Self const &other) const {
99 return _data == other._data && _x < other._x;
100 }
101
102private:
103 Point const *_data = nullptr;
104 std::size_t _size = 0;
105 std::size_t _x = 0;
106};
107
108} // namespace
109
115{
116public:
117 using iterator = std::vector<Point>::const_iterator;
118 using const_iterator = std::vector<Point>::const_iterator;
119 using UpperIterator = std::vector<Point>::const_iterator;
120 using LowerIterator = ConvexHullLowerIterator;
121
124
126 ConvexHull() = default;
128 explicit ConvexHull(Point const &a)
129 : _boundary(1, a)
130 , _lower(1)
131 {}
133 ConvexHull(Point const &a, Point const &b);
135 ConvexHull(Point const &a, Point const &b, Point const &c);
137 ConvexHull(Point const &a, Point const &b, Point const &c, Point const &d);
139 ConvexHull(std::vector<Point> const &pts);
140
142 template <typename Iter>
143 ConvexHull(Iter first, Iter last)
144 : _lower(0)
145 {
146 _prune(first, last, _boundary);
147 _construct();
148 }
150
153
155 bool empty() const { return _boundary.empty(); }
157 size_t size() const { return _boundary.size(); }
159 bool isSingular() const { return _boundary.size() == 1; }
161 bool isLinear() const { return _boundary.size() == 2; }
163 bool isDegenerate() const { return _boundary.size() < 3; }
165 double area() const;
166 //Point centroid() const;
167 //double areaAndCentroid(Point &c);
169
172
174 OptRect bounds() const;
177 std::pair<Rotate, OptRect> minAreaRotation() const;
178
180 Coord left() const { return _boundary[0][X]; }
182 Coord right() const { return _boundary[_lower-1][X]; }
184 Coord top() const { return topPoint()[Y]; }
186 Coord bottom() const { return bottomPoint()[Y]; }
187
190 Point leftPoint() const { return _boundary[0]; }
193 Point rightPoint() const { return _boundary[_lower-1]; }
196 Point topPoint() const;
199 Point bottomPoint() const;
201
204
209 iterator begin() const { return _boundary.begin(); }
211 iterator end() const { return _boundary.end(); }
213 Point const &front() const { return _boundary.front(); }
215 Point const &back() const { return _boundary.back(); }
216 Point const &operator[](std::size_t i) const { return _boundary[i]; }
217
221 boost::iterator_range<UpperIterator> upperHull() const {
222 return boost::iterator_range<UpperIterator>(_boundary.begin(), _boundary.begin() + _lower);
223 }
224
228 boost::iterator_range<LowerIterator> lowerHull() const {
229 if (_boundary.empty()) {
230 boost::iterator_range<LowerIterator> r(LowerIterator(_boundary, 0),
232 return r;
233 }
234 if (_boundary.size() == 1) {
235 boost::iterator_range<LowerIterator> r(LowerIterator(_boundary, 0),
237 return r;
238 }
239 boost::iterator_range<LowerIterator> r(LowerIterator(_boundary, _lower - 1),
240 LowerIterator(_boundary, _boundary.size() + 1));
241 return r;
242 }
244
247
249 bool contains(Point const &p) const;
252 bool contains(Rect const &r) const;
254 bool contains(ConvexHull const &other) const;
255 //bool interiorContains(Point const &p) const;
256 //bool interiorContains(Rect const &r) const;
257 //bool interiorContains(ConvexHull const &other) const;
258 //bool intersects(Rect const &r) const;
259 //bool intersects(ConvexHull const &other) const;
260
261 //ConvexHull &operator|=(ConvexHull const &other);
262 //ConvexHull &operator&=(ConvexHull const &other);
263 //ConvexHull &operator*=(Affine const &m);
264
265 //ConvexHull &expand(Point const &p);
266 //void unifyWith(ConvexHull const &other);
267 //void intersectWith(ConvexHull const &other);
269
270 void swap(ConvexHull &other);
271 void swap(std::vector<Point> &pts);
272
273private:
274 void _construct();
275
277 template <typename Iter>
278 static void _prune(Iter first, Iter last, std::vector<Point> &out) {
279 std::optional<Point> ymin, ymax, xmin, xmax;
280 for (Iter i = first; i != last; ++i) {
281 Point p = *i;
282 if (!ymin || Point::LexLess<Y>()(p, *ymin)) {
283 ymin = p;
284 }
285 if (!xmin || Point::LexLess<X>()(p, *xmin)) {
286 xmin = p;
287 }
288 if (!ymax || Point::LexGreater<Y>()(p, *ymax)) {
289 ymax = p;
290 }
291 if (!xmax || Point::LexGreater<X>()(p, *xmax)) {
292 xmax = p;
293 }
294 }
295 if (!ymin) return;
296
297 ConvexHull qhull(*xmin, *xmax, *ymin, *ymax);
298 for (Iter i = first; i != last; ++i) {
299 if (qhull.contains(*i)) continue;
300 out.push_back(*i);
301 }
302
303 out.push_back(*xmin);
304 out.push_back(*xmax);
305 out.push_back(*ymin);
306 out.push_back(*ymax);
307 std::sort(out.begin(), out.end(), Point::LexLess<X>());
308 out.erase(std::unique(out.begin(), out.end()), out.end());
309 }
310
312 std::vector<Point> _boundary;
314 std::size_t _lower;
315};
316
319inline std::ostream &operator<<(std::ostream &out, Geom::ConvexHull const &hull) {
320 out << "ConvexHull(";
321 for (auto i : hull) {
322 out << i << ", ";
323 }
324 return out << ")";
325}
326
327} // namespace Geom
328
329#endif // LIB2GEOM_SEEN_CONVEX_HULL_H
330
331/*
332 Local Variables:
333 mode:c++
334 c-file-style:"stroustrup"
335 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
336 indent-tabs-mode:nil
337 fill-column:99
338 End:
339*/
340// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Cartesian point / 2D vector and related operations.
pair< double, double > Point
Definition parser.cpp:7
static bool operator<(const Baseline &a, const Baseline &b)
Geom::IntRect bounds
Definition canvas.cpp:182
Convex hull based on the Andrew's monotone chain algorithm.
std::vector< Point > _boundary
Sequence of points forming the convex hull polygon.
bool empty() const
Check for emptiness.
std::vector< Point >::const_iterator iterator
Point bottomPoint() const
Get the bottommost (maximum Y) point of the hull.
iterator end() const
Get the end iterator to the points that form the hull.
Point const & back() const
Get the penultimate point of the lower hull.
boost::iterator_range< UpperIterator > upperHull() const
Get an iterator range to the upper part of the hull.
Point rightPoint() const
Get the rightmost (maximum X) point of the hull.
ConvexHull()=default
Create an empty convex hull.
static void _prune(Iter first, Iter last, std::vector< Point > &out)
Take a vector of points and produce a pruned sorted vector.
boost::iterator_range< LowerIterator > lowerHull() const
Get an iterator range to the lower part of the hull.
size_t size() const
Get the number of points in the hull.
ConvexHullLowerIterator LowerIterator
ConvexHull(Point const &a)
Construct a singular convex hull.
Coord bottom() const
Get the bottommost (maximum Y) coordinate of the hull.
Coord left() const
Get the leftmost (minimum X) coordinate of the hull.
bool contains(Point const &p) const
Check whether the given point is inside the hull.
bool isSingular() const
Check whether the hull contains only one point.
std::vector< Point >::const_iterator UpperIterator
std::pair< Rotate, OptRect > minAreaRotation() const
Return a rotation that puts the convex hull into a position such that bounds() has minimal area,...
iterator begin() const
Get the begin iterator to the points that form the hull.
Point leftPoint() const
Get the leftmost (minimum X) point of the hull.
double area() const
Calculate the area of the convex hull.
std::vector< Point >::const_iterator const_iterator
Point const & front() const
Get the first, leftmost point in the hull.
ConvexHull(Iter first, Iter last)
Create a convex hull of a range of points.
bool isLinear() const
Check whether the hull is a line.
Coord right() const
Get the rightmost (maximum X) coordinate of the hull.
Point topPoint() const
Get the topmost (minimum Y) point of the hull.
Coord top() const
Get the topmost (minimum Y) coordinate of the hull.
Point const & operator[](std::size_t i) const
bool isDegenerate() const
Check whether the hull has zero area.
std::size_t _lower
Index one past the rightmost point, where the lower part of the boundary starts.
Axis-aligned rectangle that can be empty.
Definition rect.h:203
Two-dimensional point that doubles as a vector.
Definition point.h:66
Axis aligned, non-empty rectangle.
Definition rect.h:92
std::size_t _size
Point const * _data
std::size_t _x
Geom::IntPoint size
double c[8][4]
double Coord
Floating point type used to store coordinates.
Definition coord.h:76
@ Y
Definition coord.h:48
@ X
Definition coord.h:48
Various utility functions.
Definition affine.h:22
std::ostream & operator<<(std::ostream &os, const Bezier &b)
Definition bezier.h:372
D2< T > operator+=(D2< T > &a, D2< T > const &b)
Definition d2.h:219
D2< T > operator-(D2< T > const &a, D2< T > const &b)
Definition d2.h:209
Bezier operator*(Bezier const &f, Bezier const &g)
Definition bezier.cpp:221
D2< T > operator-=(D2< T > &a, D2< T > const &b)
Definition d2.h:228
bool operator==(D2< T > const &a, D2< T > const &b)
Definition d2.h:177
Axis-aligned rectangle.
Affine transformation classes.