From d1d8238b83d944011b7fbc5dbbd0d547383dcadf Mon Sep 17 00:00:00 2001 From: Erica Fischer Date: Tue, 6 Aug 2024 09:14:41 -0700 Subject: [PATCH] Prescan for small deltas before doing proper simplification --- clip.cpp | 24 +++++++++++++++--------- geometry.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 12 deletions(-) diff --git a/clip.cpp b/clip.cpp index 930ceca8..ff9c560e 100644 --- a/clip.cpp +++ b/clip.cpp @@ -789,14 +789,14 @@ double distance_from_line(long long point_x, long long point_y, long long segA_x void douglas_peucker(drawvec &geom, int start, int n, double e, size_t kept, size_t retain, bool prevent_simplify_shared_nodes) { std::stack recursion_stack; - if (!geom[start + 0].necessary || !geom[start + n - 1].necessary) { + if (!(geom[start + 0].necessary > 0) || !(geom[start + n - 1].necessary > 0)) { fprintf(stderr, "endpoints not marked necessary\n"); exit(EXIT_IMPOSSIBLE); } int prev = 0; for (int here = 1; here < n; here++) { - if (geom[start + here].necessary) { + if (geom[start + here].necessary > 0) { recursion_stack.push(prev); recursion_stack.push(here); prev = here; @@ -829,9 +829,12 @@ void douglas_peucker(drawvec &geom, int start, int n, double e, size_t kept, siz if (geom[start + first] < geom[start + second]) { farthest_element_index = first; for (i = first + 1; i < second; i++) { - double temp_dist = distance_from_line(geom[start + i].x, geom[start + i].y, geom[start + first].x, geom[start + first].y, geom[start + second].x, geom[start + second].y); - - double distance = std::fabs(temp_dist); + double distance; + if (geom[start + i].necessary < 0) { + distance = 0; + } else { + distance = distance_from_line(geom[start + i].x, geom[start + i].y, geom[start + first].x, geom[start + first].y, geom[start + second].x, geom[start + second].y); + } if ((distance > e || kept < retain) && (distance > max_distance || (distance == max_distance && geom[start + i] < geom[start + farthest_element_index]))) { farthest_element_index = i; @@ -841,9 +844,12 @@ void douglas_peucker(drawvec &geom, int start, int n, double e, size_t kept, siz } else { farthest_element_index = second; for (i = second - 1; i > first; i--) { - double temp_dist = distance_from_line(geom[start + i].x, geom[start + i].y, geom[start + second].x, geom[start + second].y, geom[start + first].x, geom[start + first].y); - - double distance = std::fabs(temp_dist); + double distance; + if (geom[start + i].necessary < 0) { + distance = 0; + } else { + distance = distance_from_line(geom[start + i].x, geom[start + i].y, geom[start + second].x, geom[start + second].y, geom[start + first].x, geom[start + first].y); + } if ((distance > e || kept < retain) && (distance > max_distance || (distance == max_distance && geom[start + i] < geom[start + farthest_element_index]))) { farthest_element_index = i; @@ -917,7 +923,7 @@ static drawvec simplify_lines_basic(drawvec &geom, int z, int detail, double sim size_t out = 0; for (size_t i = 0; i < geom.size(); i++) { - if (geom[i].necessary) { + if (geom[i].necessary > 0) { geom[out++] = geom[i]; } } diff --git a/geometry.cpp b/geometry.cpp index a0330308..77c1f607 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -239,6 +239,48 @@ drawvec impose_tile_boundaries(const drawvec &geom, long long extent) { return out; } +static void mark_unnecessary(drawvec &geom, size_t start, size_t end, double e) { + double ee = e * e; + + if (geom[start] < geom[end]) { + size_t last = start; + for (size_t i = start + 1; i < end; i++) { + long long dx = geom[i].x - geom[last].x; + long long dy = geom[i].y - geom[last].y; + if (dx * dx + dy * dy < ee) { + geom[i].necessary = -1; + } else { + last = i; + } + } + } else { + size_t last = end; + for (size_t i = end - 1; i > start; i--) { + long long dx = geom[i].x - geom[last].x; + long long dy = geom[i].y - geom[last].y; + if (dx * dx + dy * dy < ee) { + geom[i].necessary = -1; + } else { + last = i; + } + } + } +} + +static void mark_unnecessary(drawvec &geom, double e) { + for (size_t i = 0; i < geom.size(); i++) { + if (geom[i].necessary > 0) { + for (size_t j = i + 1; j < geom.size(); j++) { + if (geom[j].necessary > 0) { + mark_unnecessary(geom, i, j, e); + i = j - 1; + break; + } + } + } + } +} + drawvec simplify_lines(drawvec &geom, int z, int tx, int ty, int detail, bool mark_tile_bounds, double simplification, size_t retain, drawvec const &shared_nodes, struct node *shared_nodes_map, size_t nodepos, std::string const &shared_nodes_bloom) { int res = 1 << (32 - detail - z); long long area = 1LL << (32 - z); @@ -265,7 +307,7 @@ drawvec simplify_lines(drawvec &geom, int z, int tx, int ty, int detail, bool ma auto pt = std::lower_bound(shared_nodes.begin(), shared_nodes.end(), geom[i]); if (pt != shared_nodes.end() && *pt == geom[i]) { - geom[i].necessary = true; + geom[i].necessary = 1; } if (nodepos > 0) { @@ -284,7 +326,7 @@ drawvec simplify_lines(drawvec &geom, int z, int tx, int ty, int detail, bool ma if (shared_nodes_bloom[bloom_ix] & bloom_mask) { if (bsearch(&n, shared_nodes_map, nodepos / sizeof(node), sizeof(node), nodecmp) != NULL) { - geom[i].necessary = true; + geom[i].necessary = 1; } } } @@ -295,6 +337,10 @@ drawvec simplify_lines(drawvec &geom, int z, int tx, int ty, int detail, bool ma geom = impose_tile_boundaries(geom, area); } + if (!additional[A_VISVALINGAM]) { + mark_unnecessary(geom, res * simplification); + } + for (size_t i = 0; i < geom.size(); i++) { if (geom[i].op == VT_MOVETO) { size_t j; @@ -327,7 +373,7 @@ drawvec simplify_lines(drawvec &geom, int z, int tx, int ty, int detail, bool ma size_t out = 0; for (size_t i = 0; i < geom.size(); i++) { - if (geom[i].necessary) { + if (geom[i].necessary > 0) { geom[out++] = geom[i]; } }