2#ifndef TATOOINE_DELAUNATOR_H
3#define TATOOINE_DELAUNATOR_H
21inline size_t fast_mod(
size_t const i,
size_t const c) {
22 return i >= c ? i % c : i;
26template <
floating_po
int Real>
27Real
sum(std::vector<Real>
const& x) {
31 for (
size_t i = 1; i < x.size(); i++) {
33 Real
const m =
sum + k;
34 err += std::fabs(
sum) >= std::fabs(k) ?
sum - m + k : k - m +
sum;
40template <
floating_po
int Real>
41Real
dist(Real
const ax, Real
const ay, Real
const bx, Real
const by) {
42 Real
const dx = ax - bx;
43 Real
const dy = ay - by;
44 return dx * dx + dy * dy;
47template <
floating_po
int Real>
48Real
circumradius(Real
const ax, Real
const ay, Real
const bx, Real
const by,
49 Real
const cx, Real
const cy) {
50 Real
const dx = bx - ax;
51 Real
const dy = by - ay;
52 Real
const ex = cx - ax;
53 Real
const ey = cy - ay;
55 Real
const bl = dx * dx + dy * dy;
56 Real
const cl = ex * ex + ey * ey;
57 Real
const d = dx * ey - dy * ex;
59 Real
const x = (ey * bl - dy * cl) * 0.5 / d;
60 Real
const y = (dx * cl - ex * bl) * 0.5 / d;
62 if ((bl > 0.0 || bl < 0.0) && (cl > 0.0 || cl < 0.0) &&
63 (d > 0.0 || d < 0.0)) {
66 return std::numeric_limits<Real>::max();
70template <
floating_po
int Real>
71bool orient(Real
const px, Real
const py, Real
const qx, Real
const qy,
72 Real
const rx, Real
const ry) {
73 return (qy - py) * (rx - qx) - (qx - px) * (ry - qy) < 0.0;
76template <
floating_po
int Real>
77std::pair<Real, Real>
circumcenter(Real
const ax, Real
const ay, Real
const bx,
78 Real
const by, Real
const cx,
80 Real
const dx = bx - ax;
81 Real
const dy = by - ay;
82 Real
const ex = cx - ax;
83 Real
const ey = cy - ay;
85 Real
const bl = dx * dx + dy * dy;
86 Real
const cl = ex * ex + ey * ey;
87 Real
const d = dx * ey - dy * ex;
89 Real
const x = ax + (ey * bl - dy * cl) * 0.5 / d;
90 Real
const y = ay + (dx * cl - ex * bl) * 0.5 / d;
92 return std::make_pair(x, y);
95template <range Coords>
97 using real_type =
typename Coords::value_type::value_type;
109 if (diff1 > 0.0 || diff1 < 0.0) {
111 }
else if (diff2 > 0.0 || diff2 < 0.0) {
119template <
floating_po
int Real>
120bool in_circle(Real
const ax, Real
const ay, Real
const bx,
121 Real
const by, Real
const cx, Real
const cy,
122 Real
const px, Real
const py) {
123 Real
const dx = ax - px;
124 Real
const dy = ay - py;
125 Real
const ex = bx - px;
126 Real
const ey = by - py;
127 Real
const fx = cx - px;
128 Real
const fy = cy - py;
130 Real
const ap = dx * dx + dy * dy;
131 Real
const bp = ex * ex + ey * ey;
132 Real
const cp = fx * fx + fy * fy;
134 return (dx * (ey * cp - bp * fy) - dy * (ex * cp - bp * fx) +
135 ap * (ex * fy - ey * fx)) < 0.0;
138template <
floating_po
int Real>
140 return std::fabs(x1 - x2) <= std::numeric_limits<Real>::epsilon() &&
141 std::fabs(y1 - y2) <= std::numeric_limits<Real>::epsilon();
146template <
floating_po
int Real>
148 Real
const p = dx / (std::abs(dx) + std::abs(dy));
149 return (dy > 0.0 ? 3.0 - p : 1.0 + p) / 4.0;
152template <range Coords>
154 static_assert(std::is_same_v<typename Coords::value_type, Vec2<float>> ||
155 std::is_same_v<typename Coords::value_type, Vec2<double>>);
156 using real_type =
typename Coords::value_type::value_type;
178 std::size_t
legalize(std::size_t a);
180 std::size_t
add_triangle(std::size_t i0, std::size_t i1, std::size_t i2,
181 std::size_t a, std::size_t b, std::size_t c);
182 void link(std::size_t a, std::size_t b);
185template <range Coords>
187 std::size_t n = (
coords.size() * 2) >> 1;
189 real_type max_x = std::numeric_limits<real_type>::min();
190 real_type max_y = std::numeric_limits<real_type>::min();
191 real_type min_x = std::numeric_limits<real_type>::max();
192 real_type min_y = std::numeric_limits<real_type>::max();
193 std::vector<std::size_t> ids;
196 for (std::size_t i = 0; i < n; i++) {
200 if (x < min_x) { min_x = x; }
201 if (y < min_y) { min_y = y; }
202 if (x > max_x) { max_x = x; }
203 if (y > max_y) { max_y = y; }
207 real_type const cx = (min_x + max_x) / 2;
208 real_type const cy = (min_y + max_y) / 2;
209 real_type min_dist = std::numeric_limits<real_type>::max();
211 std::size_t i0 = std::numeric_limits<std::size_t>::max();
212 std::size_t i1 = std::numeric_limits<std::size_t>::max();
213 std::size_t i2 = std::numeric_limits<std::size_t>::max();
216 for (std::size_t i = 0; i < n; i++) {
227 min_dist = std::numeric_limits<real_type>::max();
230 for (std::size_t i = 0; i < n; i++) {
231 if (i == i0)
continue;
233 if (d < min_dist && d > 0.0) {
242 real_type min_radius = std::numeric_limits<real_type>::max();
246 for (std::size_t i = 0; i < n; i++) {
247 if (i == i0 || i == i1)
continue;
252 if (r < min_radius) {
258 if (!(min_radius < std::numeric_limits<real_type>::max())) {
259 throw std::runtime_error(
"not triangulation");
265 if (
orient(i0x, i0y, i1x, i1y, i2x, i2y)) {
277 m_hash_size =
static_cast<std::size_t
>(std::llround(std::ceil(std::sqrt(n))));
280 std::numeric_limits<std::size_t>::max());
289 size_t hull_size = 3;
303 std::size_t max_triangles = n < 3 ? 1 : 2 * n - 5;
306 add_triangle(i0, i1, i2, std::numeric_limits<std::size_t>::max(),
307 std::numeric_limits<std::size_t>::max(),
308 std::numeric_limits<std::size_t>::max());
309 real_type xp = std::numeric_limits<real_type>::quiet_NaN();
310 real_type yp = std::numeric_limits<real_type>::quiet_NaN();
311 for (std::size_t k = 0; k < n; k++) {
312 std::size_t
const i = ids[k];
327 std::size_t start = 0;
332 if (start != std::numeric_limits<std::size_t>::max() &&
347 e = std::numeric_limits<std::size_t>::max();
352 if (e == std::numeric_limits<std::size_t>::max()) {
358 e, i,
hull_next[e], std::numeric_limits<std::size_t>::max(),
359 std::numeric_limits<std::size_t>::max(),
hull_tri[e]);
372 std::numeric_limits<std::size_t>::max(),
hull_tri[
next]);
383 t =
add_triangle(q, i, e, std::numeric_limits<std::size_t>::max(),
405template <range Coords>
407 std::vector<real_type> hull_area;
408 size_t e = hull_start;
410 hull_area.push_back((coords[e](0) - coords[hull_prev[e]](0)) *
411 (coords[e](1) + coords[hull_prev[e]](1)));
413 }
while (e != hull_start);
414 return sum(hull_area);
417template <range Coords>
421 m_edge_stack.clear();
425 const size_t b = halfedges[a];
442 const size_t a0 = 3 * (a / 3);
443 ar = a0 + (a + 2) % 3;
445 if (b == std::numeric_limits<std::size_t>::max()) {
456 const size_t b0 = 3 * (b / 3);
457 const size_t al = a0 + (a + 1) % 3;
458 const size_t bl = b0 + (b + 2) % 3;
460 std::size_t
const p0 = triangles[ar];
461 std::size_t
const pr = triangles[a];
462 std::size_t
const pl = triangles[al];
463 std::size_t
const p1 = triangles[bl];
466 in_circle(coords[p0](0), coords[p0](1), coords[pr](0), coords[pr](1),
467 coords[pl](0), coords[pl](1), coords[p1](0), coords[p1](1));
473 auto hbl = halfedges[bl];
477 if (hbl == std::numeric_limits<std::size_t>::max()) {
478 std::size_t e = hull_start;
480 if (hull_tri[e] == bl) {
485 }
while (e != hull_start);
488 link(b, halfedges[ar]);
490 std::size_t br = b0 + (b + 1) % 3;
492 if (i < m_edge_stack.size()) {
493 m_edge_stack[i] = br;
495 m_edge_stack.push_back(br);
512template <range Coords>
517 return fast_mod(
static_cast<std::size_t
>(std::llround(std::floor(
522template <range Coords>
524 std::size_t i2, std::size_t a,
525 std::size_t b, std::size_t c) {
526 std::size_t t = triangles.size();
527 triangles.push_back(i0);
528 triangles.push_back(i1);
529 triangles.push_back(i2);
536template <range Coords>
538 std::size_t s = halfedges.size();
540 halfedges.push_back(b);
544 throw std::runtime_error(
"Cannot link edge");
546 if (b != std::numeric_limits<std::size_t>::max()) {
547 std::size_t s2 = halfedges.size();
549 halfedges.push_back(a);
553 throw std::runtime_error(
"Cannot link edge");
Definition: delaunator.h:153
std::size_t add_triangle(std::size_t i0, std::size_t i1, std::size_t i2, std::size_t a, std::size_t b, std::size_t c)
Definition: delaunator.h:523
std::vector< std::size_t > hull_tri
Definition: delaunator.h:164
std::size_t m_hash_size
Definition: delaunator.h:175
std::size_t legalize(std::size_t a)
Definition: delaunator.h:418
std::vector< std::size_t > hull_prev
Definition: delaunator.h:162
std::size_t hull_start
Definition: delaunator.h:165
std::size_t hash_key(real_type x, real_type y) const
Definition: delaunator.h:513
std::vector< std::size_t > m_edge_stack
Definition: delaunator.h:176
real_type m_center_y
Definition: delaunator.h:174
real_type get_hull_area()
Definition: delaunator.h:406
std::vector< std::size_t > m_hash
Definition: delaunator.h:172
real_type m_center_x
Definition: delaunator.h:173
typename Coords::value_type::value_type real_type
Definition: delaunator.h:156
std::vector< std::size_t > hull_next
Definition: delaunator.h:163
std::vector< std::size_t > triangles
Definition: delaunator.h:160
Coords const & coords
Definition: delaunator.h:159
void link(std::size_t a, std::size_t b)
Definition: delaunator.h:537
std::vector< std::size_t > halfedges
Definition: delaunator.h:161
Definition: delaunator.h:17
bool in_circle(Real const ax, Real const ay, Real const bx, Real const by, Real const cx, Real const cy, Real const px, Real const py)
Definition: delaunator.h:120
bool orient(Real const px, Real const py, Real const qx, Real const qy, Real const rx, Real const ry)
Definition: delaunator.h:71
Real sum(std::vector< Real > const &x)
Kahan and Babuska summation, Neumaier variant; accumulates less FP error.
Definition: delaunator.h:27
Real dist(Real const ax, Real const ay, Real const bx, Real const by)
Definition: delaunator.h:41
size_t fast_mod(size_t const i, size_t const c)
Definition: delaunator.h:21
std::pair< Real, Real > circumcenter(Real const ax, Real const ay, Real const bx, Real const by, Real const cx, Real const cy)
Definition: delaunator.h:77
Real pseudo_angle(Real const dx, Real const dy)
Definition: delaunator.h:147
bool check_pts_equal(Real x1, Real y1, Real x2, Real y2)
Definition: delaunator.h:139
Real circumradius(Real const ax, Real const ay, Real const bx, Real const by, Real const cx, Real const cy)
Definition: delaunator.h:48
auto begin(Range &&range)
Definition: iterator_facade.h:318
auto end(Range &&range)
Definition: iterator_facade.h:322
auto next(Iter iter)
Definition: iterator_facade.h:325
Definition: delaunator.h:96
Coords const & coords
Definition: delaunator.h:98
real_type cx
Definition: delaunator.h:99
typename Coords::value_type::value_type real_type
Definition: delaunator.h:97
bool operator()(std::size_t i, std::size_t j)
Definition: delaunator.h:102
real_type cy
Definition: delaunator.h:100