Skip to content

Commit 4f072c2

Browse files
committed
#2 parity with js: mapbox/delaunator@b1f360c
1 parent d5cc9f4 commit 4f072c2

File tree

3 files changed

+70
-18
lines changed

3 files changed

+70
-18
lines changed

examples/utils.hpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
namespace utils {
1010

11-
std::string read_file(const char* filename) {
11+
inline std::string read_file(const char* filename) {
1212
std::ifstream input_file(filename);
1313
if(input_file.good()) {
1414
std::string json_str(
@@ -22,7 +22,7 @@ std::string read_file(const char* filename) {
2222
}
2323
}
2424

25-
std::vector<double> get_geo_json_points(std::string const& json) {
25+
inline std::vector<double> get_geo_json_points(std::string const& json) {
2626
rapidjson::Document document;
2727
if(document.Parse(json.c_str()).HasParseError()) {
2828
throw std::runtime_error("Cannot parse JSON");
@@ -40,8 +40,22 @@ std::vector<double> get_geo_json_points(std::string const& json) {
4040
return coords;
4141
}
4242

43-
std::vector<double> get_array_points(std::string const& json) {
44-
std::vector<double> points;
43+
template <typename T>
44+
inline T get_json_value(const rapidjson::Value &v);
45+
46+
template <>
47+
inline double get_json_value(const rapidjson::Value &v) {
48+
return v.GetDouble();
49+
}
50+
51+
template <>
52+
inline size_t get_json_value(const rapidjson::Value &v) {
53+
return static_cast<size_t>(v.GetUint64());
54+
}
55+
56+
template <typename T>
57+
inline std::vector<T> get_array_points(std::string const& json) {
58+
std::vector<T> points;
4559
rapidjson::Document document;
4660
if(document.Parse(json.c_str()).HasParseError()) {
4761
throw std::runtime_error("Cannot parse JSON");
@@ -51,10 +65,10 @@ std::vector<double> get_array_points(std::string const& json) {
5165
}
5266
points.reserve(static_cast<std::size_t>(document.Size()));
5367
for(rapidjson::SizeType i = 0; i < document.Size(); i++) {
54-
points.push_back(document[i].GetDouble());
68+
// points.push_back(document[i].GetDouble());
69+
points.push_back(get_json_value<T>(document[i]));
5570
}
5671
return points;
57-
5872
}
5973

6074
} // end ns utils

include/delaunator.hpp

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ class Delaunator {
168168

169169
Delaunator(std::vector<double> const& in_coords);
170170

171+
double get_hull_area();
172+
171173
private:
172174
std::vector<std::size_t> m_hash;
173175
std::vector<DelaunatorPoint> m_hull;
@@ -401,6 +403,16 @@ Delaunator::Delaunator(std::vector<double> const& in_coords)
401403
}
402404
}
403405

406+
double Delaunator::get_hull_area() {
407+
double hull_area = 0;
408+
size_t e = m_hull_entry;
409+
do {
410+
hull_area += (m_hull[e].x - m_hull[m_hull[e].prev].x) * (m_hull[e].y + m_hull[m_hull[e].prev].y);
411+
e = m_hull[e].next;
412+
} while (e != m_hull_entry);
413+
return hull_area;
414+
}
415+
404416
std::size_t Delaunator::remove_node(std::size_t node) {
405417
m_hull[m_hull[node].prev].next = m_hull[node].next;
406418
m_hull[m_hull[node].next].prev = m_hull[node].prev;
@@ -409,7 +421,7 @@ std::size_t Delaunator::remove_node(std::size_t node) {
409421
}
410422

411423
std::size_t Delaunator::legalize(std::size_t a) {
412-
std::size_t b = halfedges[a];
424+
const std::size_t b = halfedges[a];
413425

414426
/* if the pair of triangles doesn't satisfy the Delaunay condition
415427
* (p1 is inside the circumcircle of [p0, pl, pr]), flip them,
@@ -426,17 +438,21 @@ std::size_t Delaunator::legalize(std::size_t a) {
426438
* \||/ \ /
427439
* pr pr
428440
*/
429-
std::size_t a0 = a - a % 3;
430-
std::size_t b0 = b - b % 3;
441+
const std::size_t a0 = a - a % 3;
442+
const std::size_t b0 = b - b % 3;
443+
444+
const std::size_t al = a0 + (a + 1) % 3;
445+
const std::size_t ar = a0 + (a + 2) % 3;
446+
const std::size_t bl = b0 + (b + 2) % 3;
431447

432-
std::size_t al = a0 + (a + 1) % 3;
433-
std::size_t ar = a0 + (a + 2) % 3;
434-
std::size_t bl = b0 + (b + 2) % 3;
448+
const std::size_t p0 = triangles[ar];
449+
const std::size_t pr = triangles[a];
450+
const std::size_t pl = triangles[al];
451+
const std::size_t p1 = triangles[bl];
435452

436-
std::size_t p0 = triangles[ar];
437-
std::size_t pr = triangles[a];
438-
std::size_t pl = triangles[al];
439-
std::size_t p1 = triangles[bl];
453+
// if (b == INVALID_INDEX) {
454+
// return ar;
455+
// }
440456

441457
const bool illegal = in_circle(
442458
coords[2 * p0],

test/delaunator.test.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "../examples/utils.hpp"
22
#include <catch.hpp>
3+
#include <cmath>
34
#include <delaunator.hpp>
45

56
namespace {
@@ -13,14 +14,30 @@ void validate(const std::vector<double>& coords) {
1314
(i2 != delaunator::INVALID_INDEX) && (d.halfedges[i2] != i)));
1415
}
1516
}
17+
18+
SECTION("validate triangulation") {
19+
double hull_area = d.get_hull_area();
20+
double triangles_area = 0.0;
21+
22+
for (size_t i = 0; i < d.triangles.size(); i += 3) {
23+
const double ax = coords[2 * d.triangles[i]];
24+
const double ay = coords[2 * d.triangles[i] + 1];
25+
const double bx = coords[2 * d.triangles[i + 1]];
26+
const double by = coords[2 * d.triangles[i + 1] + 1];
27+
const double cx = coords[2 * d.triangles[i + 2]];
28+
const double cy = coords[2 * d.triangles[i + 2] + 1];
29+
triangles_area += std::fabs((by - ay) * (cx - bx) - (bx - ax) * (cy - by));
30+
}
31+
REQUIRE(triangles_area == Approx(hull_area));
32+
}
1633
}
1734
} // namespace
1835

1936
TEST_CASE("triangles match JS version ouput", "[Delaunator]") {
2037
std::string points_str = utils::read_file("./test/test-files/playgrounds-1356-epsg-3857.geojson");
2138
std::string triangles_str = utils::read_file("./test/test-files/playgrounds-1356-triangles.json");
2239
std::vector<double> coords = utils::get_geo_json_points(points_str);
23-
std::vector<double> triangles = utils::get_array_points(triangles_str);
40+
std::vector<size_t> triangles = utils::get_array_points<size_t>(triangles_str);
2441
delaunator::Delaunator delaunator(coords);
2542

2643
SECTION("length of triangles is the same") {
@@ -29,7 +46,7 @@ TEST_CASE("triangles match JS version ouput", "[Delaunator]") {
2946

3047
SECTION("values are the same") {
3148
for (std::size_t i = 0; i < triangles.size(); i++) {
32-
REQUIRE(delaunator.triangles[i] == Approx(triangles[i]));
49+
REQUIRE(delaunator.triangles[i] == triangles[i]);
3350
}
3451
}
3552
}
@@ -48,3 +65,8 @@ TEST_CASE("mapbox/delaunator/issues/24", "[Delaunator]") {
4865
std::vector<double> coords = { 382, 302, 382, 328, 382, 205, 623, 175, 382, 188, 382, 284, 623, 87, 623, 341, 141, 227 };
4966
validate(coords);
5067
}
68+
69+
TEST_CASE("mapbox/delaunator/issues/13", "[Delaunator]") {
70+
std::vector<double> coords = { 4, 1, 3.7974166882130675, 2.0837249985614585, 3.2170267516619773, 3.0210869309396715, 2.337215067329615, 3.685489874065187, 1.276805078389906, 3.9872025288851036, 0.17901102978375127, 3.885476929518457, -0.8079039091377689, 3.3940516818407187, -1.550651407188842, 2.5792964886320684, -1.9489192990517052, 1.5512485534497125, -1.9489192990517057, 0.44875144655029087, -1.5506514071888438, -0.5792964886320653, -0.8079039091377715, -1.394051681840717, 0.17901102978374794, -1.8854769295184561, 1.276805078389902, -1.987202528885104, 2.337215067329611, -1.6854898740651891, 3.217026751661974, -1.021086930939675, 3.7974166882130653, -0.08372499856146409 };
71+
validate(coords);
72+
}

0 commit comments

Comments
 (0)