Ramer-Douglas-Peucker line simplification: Difference between revisions

Content added Content deleted
(→‎{{header|Python}}: add lib header for Shapely)
(Added C solution)
Line 18: Line 18:
:*   the Wikipedia article:   [https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm Ramer-Douglas-Peucker algorithm].
:*   the Wikipedia article:   [https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm Ramer-Douglas-Peucker algorithm].
<br><br>
<br><br>

=={{header|C}}==
<lang c>#include <assert.h>
#include <math.h>
#include <stdio.h>

typedef struct point_tag {
double x;
double y;
} point_t;

// Returns the distance from point p to the line between p1 and p2
double perpendicular_distance(point_t p, point_t p1, point_t p2) {
double dx = p2.x - p1.x;
double dy = p2.y - p1.y;
double d = sqrt(dx * dx + dy * dy);
return fabs(p.x * dy - p.y * dx + p2.x * p1.y - p2.y * p1.x)/d;
}

// Simplify an array of points using the Ramer–Douglas–Peucker algorithm.
// Returns the number of output points.
size_t douglas_puecker(const point_t* points, size_t n, double epsilon,
point_t* dest, size_t length) {
assert(n >= 2);
assert(epsilon >= 0);
double max_dist = 0;
size_t index = 0;
for (size_t i = 1; i + 1 < n; ++i) {
double dist = perpendicular_distance(points[i], points[0], points[n - 1]);
if (dist > max_dist) {
max_dist = dist;
index = i;
}
}
if (max_dist > epsilon) {
size_t n1 = douglas_puecker(points, index + 1, epsilon, dest, length);
if (length >= n1 - 1) {
length -= n1 - 1;
dest += n1 - 1;
} else {
length = 0;
}
size_t n2 = douglas_puecker(points + index, n - index, epsilon, dest, length);
return n1 + n2 - 1;
}
if (length >= 2) {
dest[0] = points[0];
dest[1] = points[n - 1];
}
return 2;
}

void print_points(const point_t* points, size_t n) {
for (size_t i = 0; i < n; ++i) {
if (i > 0)
printf(" ");
printf("(%g, %g)", points[i].x, points[i].y);
}
printf("\n");
}

int main() {
point_t points[] = {
{0,0}, {1,0.1}, {2,-0.1}, {3,5}, {4,6},
{5,7}, {6,8.1}, {7,9}, {8,9}, {9,9}
};
const size_t len = sizeof(points)/sizeof(points[0]);
point_t out[len];
size_t n = douglas_puecker(points, len, 1.0, out, len);
print_points(out, n);
return 0;
}</lang>

{{out}}
<pre>
(0, 0) (2, -0.1) (3, 5) (7, 9) (9, 9)
</pre>


=={{header|C sharp|C#}}==
=={{header|C sharp|C#}}==