move back to class
diff --git a/include/delaunator.hpp b/include/delaunator.hpp
index 6eae623..f4078c3 100644
--- a/include/delaunator.hpp
+++ b/include/delaunator.hpp
@@ -11,21 +11,25 @@
namespace delaunator {
-inline double dist(const double ax,
- const double ay,
- const double bx,
- const double by) {
+inline double dist(
+ const double ax,
+ const double ay,
+ const double bx,
+ const double by
+) {
const double dx = ax - bx;
const double dy = ay - by;
return dx * dx + dy * dy;
}
-inline double circumradius(const double ax,
- const double ay,
- const double bx,
- const double by,
- const double cx,
- const double cy) {
+inline double circumradius(
+ const double ax,
+ const double ay,
+ const double bx,
+ const double by,
+ const double cx,
+ const double cy
+) {
const double dx = bx - ax;
const double dy = by - ay;
const double ex = cx - ax;
@@ -45,21 +49,25 @@
}
}
-inline double area(const double px,
- const double py,
- const double qx,
- const double qy,
- const double rx,
- const double ry) {
+inline double area(
+ const double px,
+ const double py,
+ const double qx,
+ const double qy,
+ const double rx,
+ const double ry
+) {
return (qy - py) * (rx - qx) - (qx - px) * (ry - qy);
}
-inline std::pair<double, double> circumcenter(const double ax,
- const double ay,
- const double bx,
- const double by,
- const double cx,
- const double cy) {
+inline std::pair<double, double> circumcenter(
+ const double ax,
+ const double ay,
+ const double bx,
+ const double by,
+ const double cx,
+ const double cy
+) {
const double dx = bx - ax;
const double dy = by - ay;
const double ex = cx - ax;
@@ -75,11 +83,13 @@
return std::make_pair(x, y);
}
-inline double compare(std::vector<double> const& coords,
- std::size_t i,
- std::size_t j,
- double cx,
- double cy) {
+inline double compare(
+ std::vector<double> const& coords,
+ std::size_t i,
+ std::size_t j,
+ double cx,
+ double cy
+) {
const double d1 = dist(coords[2 * i], coords[2 * i + 1], cx, cy);
const double d2 = dist(coords[2 * j], coords[2 * j + 1], cx, cy);
const double diff1 = d1 - d2;
@@ -106,14 +116,16 @@
}
};
-inline bool in_circle(double ax,
- double ay,
- double bx,
- double by,
- double cx,
- double cy,
- double px,
- double py) {
+inline bool in_circle(
+ double ax,
+ double ay,
+ double bx,
+ double by,
+ double cx,
+ double cy,
+ double px,
+ double py
+) {
const double dx = ax - px;
const double dy = ay - py;
const double ex = bx - px;
@@ -147,373 +159,395 @@
bool removed;
};
-struct Delaunator {
+class Delaunator {
- std::vector<double> const& coords;
- std::vector<std::size_t> triangles;
- std::vector<std::size_t> halfedges;
- std::vector<std::size_t> m_hash;
- std::vector<DelaunatorPoint> m_hull;
- double m_center_x;
- double m_center_y;
- std::size_t m_hash_size;
+ public:
+ std::vector<double> const& coords;
+ std::vector<std::size_t> triangles;
+ std::vector<std::size_t> halfedges;
- Delaunator (std::vector<double> const& in_coords) :
- coords(in_coords),
- triangles(),
- halfedges(),
- m_hash(),
- m_hull(),
- m_center_x(),
- m_center_y(),
- m_hash_size()
- {
- std::size_t n = coords.size() >> 1;
+ Delaunator (std::vector<double> const& in_coords);
- double max_x = std::numeric_limits<double>::min();
- double max_y = std::numeric_limits<double>::min();
- double min_x = std::numeric_limits<double>::max();
- double min_y = std::numeric_limits<double>::max();
- std::vector<std::size_t> ids;
- ids.reserve(n);
+ private:
+ std::vector<std::size_t> m_hash;
+ std::vector<DelaunatorPoint> m_hull;
+ double m_center_x;
+ double m_center_y;
+ std::size_t m_hash_size;
- for (std::size_t i = 0; i < n; i++) {
- const double x = coords[2 * i];
- const double y = coords[2 * i + 1];
+ std::size_t remove_node(std::size_t node);
+ std::size_t legalize(std::size_t a);
+ std::size_t insert_node(std::size_t i);
+ std::size_t insert_node(std::size_t i, std::size_t prev);
+ std::size_t hash_key(double x, double y);
+ void hash_edge(std::size_t e);
+ 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
+ );
+ void link(std::size_t a, std::size_t b);
+};
- if (x < min_x) min_x = x;
- if (y < min_y) min_y = y;
- if (x > max_x) max_x = x;
- if (y > max_y) max_y = y;
+Delaunator::Delaunator (std::vector<double> const& in_coords) :
+ coords(in_coords),
+ triangles(),
+ halfedges(),
+ m_hash(),
+ m_hull(),
+ m_center_x(),
+ m_center_y(),
+ m_hash_size()
+{
+ std::size_t n = coords.size() >> 1;
- ids.push_back(i);
+ double max_x = std::numeric_limits<double>::min();
+ double max_y = std::numeric_limits<double>::min();
+ double min_x = std::numeric_limits<double>::max();
+ double min_y = std::numeric_limits<double>::max();
+ std::vector<std::size_t> ids;
+ ids.reserve(n);
+
+ for (std::size_t i = 0; i < n; i++) {
+ const double x = coords[2 * i];
+ const double y = coords[2 * i + 1];
+
+ if (x < min_x) min_x = x;
+ if (y < min_y) min_y = y;
+ if (x > max_x) max_x = x;
+ if (y > max_y) max_y = y;
+
+ ids.push_back(i);
+ }
+ const double cx = (min_x + max_x) / 2;
+ const double cy = (min_y + max_y) / 2;
+ double min_dist = std::numeric_limits<double>::max();
+
+ std::size_t i0 = INVALID_INDEX;
+ std::size_t i1 = INVALID_INDEX;
+ std::size_t i2 = INVALID_INDEX;
+
+ // pick a seed point close to the centroid
+ for (std::size_t i = 0; i < n; i++) {
+ const double d = dist(cx, cy, coords[2 * i], coords[2 * i + 1]);
+ if (d < min_dist) {
+ i0 = i;
+ min_dist = d;
}
- const double cx = (min_x + max_x) / 2;
- const double cy = (min_y + max_y) / 2;
- double min_dist = std::numeric_limits<double>::max();
+ }
- std::size_t i0 = INVALID_INDEX;
- std::size_t i1 = INVALID_INDEX;
- std::size_t i2 = INVALID_INDEX;
+ min_dist = std::numeric_limits<double>::max();
- // pick a seed point close to the centroid
- for (std::size_t i = 0; i < n; i++) {
- const double d = dist(cx, cy, coords[2 * i], coords[2 * i + 1]);
- if (d < min_dist) {
- i0 = i;
- min_dist = d;
- }
- }
-
- min_dist = std::numeric_limits<double>::max();
-
- // find the point closest to the seed
- for (std::size_t i = 0; i < n; i++) {
- if (i == i0) continue;
- const double d = dist(coords[2 * i0], coords[2 * i0 + 1], coords[2 * i], coords[2 * i + 1]);
- if (d < min_dist && d > 0.0)
- {
- i1 = i;
- min_dist = d;
- }
- }
-
- double min_radius = std::numeric_limits<double>::max();
-
- // find the third point which forms the smallest circumcircle with the first two
- for (std::size_t i = 0; i < n; i++)
+ // find the point closest to the seed
+ for (std::size_t i = 0; i < n; i++) {
+ if (i == i0) continue;
+ const double d = dist(coords[2 * i0], coords[2 * i0 + 1], coords[2 * i], coords[2 * i + 1]);
+ if (d < min_dist && d > 0.0)
{
- if (i == i0 || i == i1) continue;
+ i1 = i;
+ min_dist = d;
+ }
+ }
- const double r = circumradius(
- coords[2 * i0], coords[2 * i0 + 1],
- coords[2 * i1], coords[2 * i1 + 1],
- coords[2 * i], coords[2 * i + 1]);
+ double min_radius = std::numeric_limits<double>::max();
- if (r < min_radius)
- {
- i2 = i;
- min_radius = r;
+ // find the third point which forms the smallest circumcircle with the first two
+ for (std::size_t i = 0; i < n; i++)
+ {
+ if (i == i0 || i == i1) continue;
+
+ const double r = circumradius(
+ coords[2 * i0], coords[2 * i0 + 1],
+ coords[2 * i1], coords[2 * i1 + 1],
+ coords[2 * i], coords[2 * i + 1]);
+
+ if (r < min_radius)
+ {
+ i2 = i;
+ min_radius = r;
+ }
+ }
+
+ if (!(min_radius < std::numeric_limits<double>::max())) {
+ throw std::runtime_error("not triangulation");;
+ }
+
+ bool coord_area = area(
+ coords[2 * i0], coords[2 * i0 + 1],
+ coords[2 * i1], coords[2 * i1 + 1],
+ coords[2 * i2], coords[2 * i2 + 1]
+ ) < 0.0;
+ if (coord_area) {
+ std::swap(i1,i2);
+ }
+
+ const double i0x = coords[2 * i0];
+ const double i0y = coords[2 * i0 + 1];
+ const double i1x = coords[2 * i1];
+ const double i1y = coords[2 * i1 + 1];
+ const double i2x = coords[2 * i2];
+ const double i2y = coords[2 * i2 + 1];
+
+ std::tie(m_center_x, m_center_y) = circumcenter(i0x, i0y, i1x, i1y, i2x, i2y);
+
+ // sort the points by distance from the seed triangle circumcenter
+ // cerr << ids << endl;
+ std::sort(ids.begin(), ids.end(), sort_to_center {coords, m_center_x, m_center_y});
+ // quicksort(ids, coords, 0, n - 1, m_center_x, m_center_y);
+ // cerr << ids << endl;
+
+ m_hash_size = static_cast<std::size_t>(std::llround(std::ceil(std::sqrt(n))));
+ m_hash.reserve(m_hash_size);
+ for (std::size_t i = 0; i < m_hash_size; i++) {
+ m_hash.push_back(INVALID_INDEX);
+ }
+
+ m_hull.reserve(coords.size());
+
+ std::size_t e = insert_node(i0);
+ hash_edge(e);
+ m_hull[e].t = 0;
+
+ e = insert_node(i1, e);
+ hash_edge(e);
+ m_hull[e].t = 1;
+
+ e = insert_node(i2, e);
+ hash_edge(e);
+ m_hull[e].t = 2;
+
+ std::size_t max_triangles = n < 3 ? 1 : 2 * n - 5;
+ triangles.reserve(max_triangles * 3);
+ halfedges.reserve(max_triangles * 3);
+ add_triangle(i0, i1, i2, INVALID_INDEX, INVALID_INDEX, INVALID_INDEX);
+ double xp = std::numeric_limits<double>::quiet_NaN();
+ double yp = std::numeric_limits<double>::quiet_NaN();
+ for (std::size_t k = 0; k < n; k++) {
+ const std::size_t i = ids[k];
+ const double x = coords[2 * i];
+ const double y = coords[2 * i + 1];
+ if (check_pts_equal(x, y, xp, yp)) continue;
+ xp = x;
+ yp = y;
+ if (
+ check_pts_equal(x, y, i0x, i0y) ||
+ check_pts_equal(x, y, i1x, i1y) ||
+ check_pts_equal(x, y, i2x, i2y)
+ ) continue;
+
+ const std::size_t start_key = hash_key(x, y);
+ std::size_t key = start_key;
+ std::size_t start = INVALID_INDEX;
+ do {
+ start = m_hash[key];
+ key = (key + 1) % m_hash_size;
+ } while(
+ (start == INVALID_INDEX || m_hull[start].removed) &&
+ (key != start_key)
+ );
+
+ e = start;
+
+ while(
+ area(
+ x, y,
+ m_hull[e].x, m_hull[e].y,
+ m_hull[m_hull[e].next].x, m_hull[m_hull[e].next].y
+ ) >= 0.0
+ ) {
+ e = m_hull[e].next;
+
+ if (e == start) {
+ throw std::runtime_error("Something is wrong with the input points.");
}
}
- if (!(min_radius < std::numeric_limits<double>::max())) {
- throw std::runtime_error("not triangulation");;
+ const bool walk_back = e == start;
+
+ // add the first triangle from the point
+ std::size_t t = add_triangle(
+ m_hull[e].i,
+ i,
+ m_hull[m_hull[e].next].i,
+ INVALID_INDEX, INVALID_INDEX, m_hull[e].t
+ );
+
+ m_hull[e].t = t; // keep track of boundary triangles on the hull
+ e = insert_node(i, e);
+
+ // recursively flip triangles from the point until they satisfy the Delaunay condition
+ m_hull[e].t = legalize(t + 2);
+ if (m_hull[m_hull[m_hull[e].prev].prev].t == halfedges[t + 1]) {
+ m_hull[m_hull[m_hull[e].prev].prev].t = t + 2;
}
-
- bool coord_area = area(
- coords[2 * i0], coords[2 * i0 + 1],
- coords[2 * i1], coords[2 * i1 + 1],
- coords[2 * i2], coords[2 * i2 + 1]
- ) < 0.0;
- if (coord_area) {
- std::swap(i1,i2);
- }
-
- const double i0x = coords[2 * i0];
- const double i0y = coords[2 * i0 + 1];
- const double i1x = coords[2 * i1];
- const double i1y = coords[2 * i1 + 1];
- const double i2x = coords[2 * i2];
- const double i2y = coords[2 * i2 + 1];
-
- std::tie(m_center_x, m_center_y) = circumcenter(i0x, i0y, i1x, i1y, i2x, i2y);
-
- // sort the points by distance from the seed triangle circumcenter
- // cerr << ids << endl;
- std::sort(ids.begin(), ids.end(), sort_to_center {coords, m_center_x, m_center_y});
- // quicksort(ids, coords, 0, n - 1, m_center_x, m_center_y);
- // cerr << ids << endl;
-
- m_hash_size = static_cast<std::size_t>(std::llround(std::ceil(std::sqrt(n))));
- m_hash.reserve(m_hash_size);
- for (std::size_t i = 0; i < m_hash_size; i++) {
- m_hash.push_back(INVALID_INDEX);
- }
-
- m_hull.reserve(coords.size());
-
- std::size_t e = insert_node(i0);
- hash_edge(e);
- m_hull[e].t = 0;
-
- e = insert_node(i1, e);
- hash_edge(e);
- m_hull[e].t = 1;
-
- e = insert_node(i2, e);
- hash_edge(e);
- m_hull[e].t = 2;
-
- std::size_t max_triangles = n < 3 ? 1 : 2 * n - 5;
- triangles.reserve(max_triangles * 3);
- halfedges.reserve(max_triangles * 3);
- add_triangle(i0, i1, i2, INVALID_INDEX, INVALID_INDEX, INVALID_INDEX);
- double xp = std::numeric_limits<double>::quiet_NaN();
- double yp = std::numeric_limits<double>::quiet_NaN();
- for (std::size_t k = 0; k < n; k++) {
- const std::size_t i = ids[k];
- const double x = coords[2 * i];
- const double y = coords[2 * i + 1];
- if (check_pts_equal(x, y, xp, yp)) continue;
- xp = x;
- yp = y;
- if (
- check_pts_equal(x, y, i0x, i0y) ||
- check_pts_equal(x, y, i1x, i1y) ||
- check_pts_equal(x, y, i2x, i2y)
- ) continue;
-
- const std::size_t start_key = hash_key(x, y);
- std::size_t key = start_key;
- std::size_t start = INVALID_INDEX;
- do {
- start = m_hash[key];
- key = (key + 1) % m_hash_size;
- } while(
- (start == INVALID_INDEX || m_hull[start].removed) &&
- (key != start_key)
+ // walk forward through the hull, adding more triangles and flipping recursively
+ std::size_t q = m_hull[e].next;
+ while(
+ area(
+ x, y,
+ m_hull[q].x, m_hull[q].y,
+ m_hull[m_hull[q].next].x, m_hull[m_hull[q].next].y
+ ) < 0.0
+ ) {
+ t = add_triangle(
+ m_hull[q].i, i,
+ m_hull[m_hull[q].next].i, m_hull[m_hull[q].prev].t,
+ INVALID_INDEX, m_hull[q].t
);
-
- e = start;
-
+ m_hull[m_hull[q].prev].t = legalize(t + 2);
+ remove_node(q);
+ q = m_hull[q].next;
+ }
+ if (walk_back) {
+ // walk backward from the other side, adding more triangles and flipping
+ q = m_hull[e].prev;
while(
area(
x, y,
- m_hull[e].x, m_hull[e].y,
- m_hull[m_hull[e].next].x, m_hull[m_hull[e].next].y
- ) >= 0.0
- ) {
- e = m_hull[e].next;
-
- if (e == start) {
- throw std::runtime_error("Something is wrong with the input points.");
- }
- }
-
- const bool walk_back = e == start;
-
- // add the first triangle from the point
- std::size_t t = add_triangle(
- m_hull[e].i,
- i,
- m_hull[m_hull[e].next].i,
- INVALID_INDEX, INVALID_INDEX, m_hull[e].t
- );
-
- m_hull[e].t = t; // keep track of boundary triangles on the hull
- e = insert_node(i, e);
-
- // recursively flip triangles from the point until they satisfy the Delaunay condition
- m_hull[e].t = legalize(t + 2);
- if (m_hull[m_hull[m_hull[e].prev].prev].t == halfedges[t + 1]) {
- m_hull[m_hull[m_hull[e].prev].prev].t = t + 2;
- }
- // walk forward through the hull, adding more triangles and flipping recursively
- std::size_t q = m_hull[e].next;
- while(
- area(
- x, y,
- m_hull[q].x, m_hull[q].y,
- m_hull[m_hull[q].next].x, m_hull[m_hull[q].next].y
+ m_hull[m_hull[q].prev].x, m_hull[m_hull[q].prev].y,
+ m_hull[q].x, m_hull[q].y
) < 0.0
) {
t = add_triangle(
- m_hull[q].i, i,
- m_hull[m_hull[q].next].i, m_hull[m_hull[q].prev].t,
- INVALID_INDEX, m_hull[q].t
+ m_hull[m_hull[q].prev].i, i,
+ m_hull[q].i, INVALID_INDEX,
+ m_hull[q].t, m_hull[m_hull[q].prev].t
);
- m_hull[m_hull[q].prev].t = legalize(t + 2);
+ legalize(t + 2);
+ m_hull[m_hull[q].prev].t = t;
remove_node(q);
- q = m_hull[q].next;
+ q = m_hull[q].prev;
}
- if (walk_back) {
- // walk backward from the other side, adding more triangles and flipping
- q = m_hull[e].prev;
- while(
- area(
- x, y,
- m_hull[m_hull[q].prev].x, m_hull[m_hull[q].prev].y,
- m_hull[q].x, m_hull[q].y
- ) < 0.0
- ) {
- t = add_triangle(
- m_hull[m_hull[q].prev].i, i,
- m_hull[q].i, INVALID_INDEX,
- m_hull[q].t, m_hull[m_hull[q].prev].t
- );
- legalize(t + 2);
- m_hull[m_hull[q].prev].t = t;
- remove_node(q);
- q = m_hull[q].prev;
- }
- }
- hash_edge(e);
- hash_edge(m_hull[e].prev);
}
-
+ hash_edge(e);
+ hash_edge(m_hull[e].prev);
}
+}
- std::size_t remove_node(std::size_t node) {
- m_hull[m_hull[node].prev].next = m_hull[node].next;
- m_hull[m_hull[node].next].prev = m_hull[node].prev;
- m_hull[node].removed = true;
- return m_hull[node].prev;
+std::size_t Delaunator::remove_node(std::size_t node) {
+ m_hull[m_hull[node].prev].next = m_hull[node].next;
+ m_hull[m_hull[node].next].prev = m_hull[node].prev;
+ m_hull[node].removed = true;
+ return m_hull[node].prev;
+}
+
+std::size_t Delaunator::legalize(std::size_t a) {
+ std::size_t b = halfedges[a];
+
+ std::size_t a0 = a - a % 3;
+ std::size_t b0 = b - b % 3;
+
+ std::size_t al = a0 + (a + 1) % 3;
+ std::size_t ar = a0 + (a + 2) % 3;
+ std::size_t bl = b0 + (b + 2) % 3;
+
+ std::size_t p0 = triangles[ar];
+ std::size_t pr = triangles[a];
+ std::size_t pl = triangles[al];
+ std::size_t p1 = triangles[bl];
+
+ const bool illegal = in_circle(
+ coords[2 * p0], coords[2 * p0 + 1],
+ coords[2 * pr], coords[2 * pr + 1],
+ coords[2 * pl], coords[2 * pl + 1],
+ coords[2 * p1], coords[2 * p1 + 1]
+ );
+
+ if (illegal) {
+ triangles[a] = p1;
+ triangles[b] = p0;
+ link(a, halfedges[bl]);
+ link(b, halfedges[ar]);
+ link(ar, bl);
+
+ std::size_t br = b0 + (b + 1) % 3;
+
+ legalize(a);
+ return legalize(br);
}
+ return ar;
+}
- std::size_t legalize(std::size_t a) {
- std::size_t b = halfedges[a];
+std::size_t Delaunator::insert_node(std::size_t i) {
+ std::size_t node = m_hull.size();
+ DelaunatorPoint p = {
+ i,
+ coords[2 * i],
+ coords[2 * i + 1],
+ 0,
+ node,
+ node,
+ false
+ };
+ m_hull.push_back(p);
+ return node;
+}
- std::size_t a0 = a - a % 3;
- std::size_t b0 = b - b % 3;
+std::size_t Delaunator::insert_node(std::size_t i, std::size_t prev) {
+ std::size_t node = insert_node(i);
+ m_hull[node].next = m_hull[prev].next;
+ m_hull[node].prev = prev;
+ m_hull[m_hull[node].next].prev = node;
+ m_hull[prev].next = node;
+ return node;
+}
- std::size_t al = a0 + (a + 1) % 3;
- std::size_t ar = a0 + (a + 2) % 3;
- std::size_t bl = b0 + (b + 2) % 3;
+std::size_t Delaunator::hash_key(double x, double y) {
+ const double dx = x - m_center_x;
+ const double dy = y - m_center_y;
+ // use pseudo-angle: a measure that monotonically increases
+ // with real angle, but doesn't require expensive trigonometry
+ const double p = 1.0 - dx / (std::abs(dx) + std::abs(dy));
+ return static_cast<std::size_t>(std::llround(std::floor(
+ (2.0 + (dy < 0.0 ? -p : p)) / 4.0 * static_cast<double>(m_hash_size) //TODO:is this conversion save?
+ )));
+}
- std::size_t p0 = triangles[ar];
- std::size_t pr = triangles[a];
- std::size_t pl = triangles[al];
- std::size_t p1 = triangles[bl];
+void Delaunator::hash_edge(std::size_t e) {
+ m_hash[hash_key(m_hull[e].x, m_hull[e].y)] = e;
+}
- const bool illegal = in_circle(
- coords[2 * p0], coords[2 * p0 + 1],
- coords[2 * pr], coords[2 * pr + 1],
- coords[2 * pl], coords[2 * pl + 1],
- coords[2 * p1], coords[2 * p1 + 1]
- );
+std::size_t Delaunator::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
+) {
+ std::size_t t = triangles.size();
+ triangles.push_back(i0);
+ triangles.push_back(i1);
+ triangles.push_back(i2);
+ link(t, a);
+ link(t + 1, b);
+ link(t + 2, c);
+ return t;
+}
- if (illegal) {
- triangles[a] = p1;
- triangles[b] = p0;
- link(a, halfedges[bl]);
- link(b, halfedges[ar]);
- link(ar, bl);
-
- std::size_t br = b0 + (b + 1) % 3;
-
- legalize(a);
- return legalize(br);
- }
- return ar;
+void Delaunator::link(std::size_t a, std::size_t b) {
+ std::size_t s = halfedges.size();
+ if (a == s) {
+ halfedges.push_back(b);
+ } else if (a < s) {
+ halfedges[a] = b;
+ } else {
+ throw std::runtime_error("Cannot link edge");
}
-
- std::size_t insert_node(std::size_t i) {
- std::size_t node = m_hull.size();
- DelaunatorPoint p = {
- i,
- coords[2 * i],
- coords[2 * i + 1],
- 0,
- node,
- node,
- false
- };
- m_hull.push_back(p);
- return node;
- }
-
- std::size_t insert_node(std::size_t i, std::size_t prev) {
- std::size_t node = insert_node(i);
- m_hull[node].next = m_hull[prev].next;
- m_hull[node].prev = prev;
- m_hull[m_hull[node].next].prev = node;
- m_hull[prev].next = node;
- return node;
- }
-
- std::size_t hash_key(double x, double y) {
- const double dx = x - m_center_x;
- const double dy = y - m_center_y;
- // use pseudo-angle: a measure that monotonically increases
- // with real angle, but doesn't require expensive trigonometry
- const double p = 1.0 - dx / (std::abs(dx) + std::abs(dy));
- return static_cast<std::size_t>(std::llround(std::floor(
- (2.0 + (dy < 0.0 ? -p : p)) / 4.0 * static_cast<double>(m_hash_size) //TODO:is this conversion save?
- )));
- }
-
- void hash_edge(std::size_t e) {
- m_hash[hash_key(m_hull[e].x, m_hull[e].y)] = e;
- }
-
- 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) {
- std::size_t t = triangles.size();
- triangles.push_back(i0);
- triangles.push_back(i1);
- triangles.push_back(i2);
- link(t, a);
- link(t + 1, b);
- link(t + 2, c);
- return t;
- }
-
- void link(std::size_t a, std::size_t b) {
- std::size_t s = halfedges.size();
- if (a == s) {
- halfedges.push_back(b);
- } else if (a < s) {
- halfedges[a] = b;
- } else {
+ if (b != INVALID_INDEX) {
+ std::size_t s2 = halfedges.size();
+ if (b == s2) {
+ halfedges.push_back(a);
+ } else if (b < s2) {
+ halfedges[b] = a;
+ } else {
throw std::runtime_error("Cannot link edge");
}
- if (b != INVALID_INDEX) {
- std::size_t s2 = halfedges.size();
- if (b == s2) {
- halfedges.push_back(a);
- } else if (b < s2) {
- halfedges[b] = a;
- } else {
- throw std::runtime_error("Cannot link edge");
- }
- }
}
+}
-};
-} // end namespace delaunator
+} //namespace delaunator