47template <
class Number,
class Label,
class CenterNumber,
class CenterLabel>
50 if (points.size() < 2)
55 const auto first = points.begin();
56 const auto last = std::partition(first, points.end(),
57 [&p](
const auto& q) { return q != p; });
62 const auto reference = *std::min_element(first, last);
69 using Compare = std::common_type_t<Number, CenterNumber>;
70 const auto firstHalf = [&p](
const auto& q) {
71 const auto vertical = detail::strongOrder(detail::asNumber<Compare>(q.y()),
72 detail::asNumber<Compare>(p.
y()));
75 return detail::strongOrder(detail::asNumber<Compare>(q.x()),
76 detail::asNumber<Compare>(p.
x())) > 0;
78 const auto middle = std::partition(first, last, firstHalf);
84 using SignCoordinate = detail::orientation_coordinate_t<CenterNumber, Number, Number>;
85 const auto center = detail::filtered<SignCoordinate>(p);
89 const auto less = [&p, ¢er](
const auto& a,
const auto& b) {
90 const auto turn = detail::orientationSignOf(
91 center, detail::filtered<SignCoordinate>(a), detail::filtered<SignCoordinate>(b))
101 return p.template squaredDistance<Compare>(a) >
102 p.template squaredDistance<Compare>(b);
104 std::sort(first, middle, less);
105 std::sort(middle, last, less);
112 const auto above = firstHalf(reference);
113 const auto start = std::lower_bound(
114 above ? first : middle, above ? middle : last, reference,
115 [¢er](
const auto& a,
const auto& b) {
116 return detail::orientationSignOf(center,
117 detail::filtered<SignCoordinate>(a),
118 detail::filtered<SignCoordinate>(b))
121 std::rotate(first, start, last);
132template <
class RandomIt,
class LessX,
class LessY>
133void hilbertSortMedian(RandomIt begin, RandomIt end,
bool xAxis,
bool upX,
bool upY,
134 const LessX& lessX,
const LessY& lessY) {
135 if (end - begin <= 1) {
139 const RandomIt m0 = begin, m4 = end;
140 const RandomIt m2 = m0 + (m4 - m0) / 2;
141 const RandomIt m1 = m0 + (m2 - m0) / 2;
142 const RandomIt m3 = m2 + (m4 - m2) / 2;
146 const auto split = [](RandomIt first, RandomIt mid, RandomIt last,
const auto& less,
149 std::nth_element(first, mid, last, less);
151 std::nth_element(first, mid, last,
152 [&less](
const auto& a,
const auto& b) {
return less(b, a); });
157 split(m0, m2, m4, lessX, upX);
158 split(m0, m1, m2, lessY, upY);
159 split(m2, m3, m4, lessY, !upY);
161 split(m0, m2, m4, lessY, upY);
162 split(m0, m1, m2, lessX, upX);
163 split(m2, m3, m4, lessX, !upX);
166 hilbertSortMedian(m0, m1, !xAxis, upY, upX, lessX, lessY);
167 hilbertSortMedian(m1, m2, xAxis, upX, upY, lessX, lessY);
168 hilbertSortMedian(m2, m3, xAxis, upX, upY, lessX, lessY);
169 hilbertSortMedian(m3, m4, !xAxis, !upY, !upX, lessX, lessY);
191template <
class Number,
class Label>
194 return a.
x() < b.x();
197 return a.
y() < b.y();
199 detail::hilbertSortMedian(points.begin(), points.end(),
true,
false,
false, lessX, lessY);
Definition arrangement.hpp:67
void hilbertSort(std::vector< Point< Number, Label > > &points)
Sorts points along a Hilbert space-filling curve.
Definition sortpoints.hpp:192
void sortAround(std::vector< Point< Number, Label > > &points, const Point< CenterNumber, CenterLabel > &p)
Sorts points counterclockwise around a center point.
Definition sortpoints.hpp:48
Two-dimensional point with optional label payload.
Definition point.hpp:129
constexpr const NumberType & x() const
Returns the x coordinate.
Definition point.hpp:193
constexpr const NumberType & y() const
Returns the y coordinate.
Definition point.hpp:205
Bounding-box sweep over pairs of segments.