From a22414ece40c1622588813e92a527ab47a79a389 Mon Sep 17 00:00:00 2001 From: Gathros <6323830+Gathros@users.noreply.github.com> Date: Fri, 11 May 2018 18:45:18 +0100 Subject: [PATCH 1/4] Adding graham.c --- .../gift_wrapping/graham_scan/code/c/graham.c | 114 ++++++++++++++++++ .../gift_wrapping/graham_scan/graham_scan.md | 6 + 2 files changed, 120 insertions(+) create mode 100644 chapters/computational_geometry/gift_wrapping/graham_scan/code/c/graham.c diff --git a/chapters/computational_geometry/gift_wrapping/graham_scan/code/c/graham.c b/chapters/computational_geometry/gift_wrapping/graham_scan/code/c/graham.c new file mode 100644 index 000000000..3beb3cd51 --- /dev/null +++ b/chapters/computational_geometry/gift_wrapping/graham_scan/code/c/graham.c @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include + +struct point { + double x, y; +}; + +int cmp_points(const void *a, const void *b) { + struct point point1 = *(struct point*)a; + struct point point2 = *(struct point*)b; + + if (point1.y > point2.y) { + return 1; + } else if (point1.y < point2.y) { + return -1; + } else { + return 0; + } +} + +double ccw(struct point a, struct point b, struct point c) { + return (b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x); +} + +double polar_angle(struct point origin, struct point p) { + return atan2(p.y - origin.y, p.x - origin.x); +} + +void polar_angles_sort(struct point *points, struct point origin, size_t size) { + if (size < 2) { + return; + } + + double pivot_angle = polar_angle(origin, points[size / 2]); + + int i = 0; + int j = size - 1; + while (1) { + while (polar_angle(origin, points[i]) < pivot_angle) { + i++; + } + while (polar_angle(origin, points[j]) > pivot_angle) { + j--; + } + + if (i >= j) { + break; + } + + struct point tmp = points[i]; + points[i] = points[j]; + points[j] = tmp; + + i++; + j--; + } + + polar_angles_sort(points, origin, i); + polar_angles_sort(points + i, origin, size - i); +} + +size_t graham_scan(struct point *points, size_t size) { + qsort(points, size, sizeof(struct point), cmp_points); + polar_angles_sort(points, points[0], size); + + struct point tmp_points[size + 1]; + memcpy(tmp_points + 1, points, size * sizeof(struct point)); + tmp_points[0] = tmp_points[size]; + + size_t m = 1; + for (size_t i = 2; i <= size; ++i) { + while (ccw(tmp_points[m - 1], tmp_points[m], tmp_points[i]) <= 0) { + if (m > 1) { + m--; + continue; + } else if (i == size) { + break; + } else { + i++; + } + } + + m++; + struct point tmp = tmp_points[i]; + tmp_points[i] = tmp_points[m]; + tmp_points[m] = tmp; + } + + memcpy(points, tmp_points + 1, size * sizeof(struct point)); + + return m; +} + +int main() { + struct point points[] = {{2.0, 1.9}, {1.0, 1.0}, {2.0, 4.0}, {3.0, 1.0}, + {2.0, 0.0}}; + + printf("Points:\n"); + for (size_t i = 0; i < 5; ++i) { + printf("(%f,%f)\n", points[i].x, points[i].y); + } + + size_t hull_size = graham_scan(points, 5); + + printf("\nHull:\n"); + for (size_t i = 0; i < hull_size; ++i) { + printf("(%f,%f)\n", points[i].x, points[i].y); + } + + return 0; +} diff --git a/chapters/computational_geometry/gift_wrapping/graham_scan/graham_scan.md b/chapters/computational_geometry/gift_wrapping/graham_scan/graham_scan.md index fa7ce31e2..879bf63fb 100644 --- a/chapters/computational_geometry/gift_wrapping/graham_scan/graham_scan.md +++ b/chapters/computational_geometry/gift_wrapping/graham_scan/graham_scan.md @@ -14,6 +14,8 @@ We can find whether a rotation is counter-clockwise with trigonometric functions {% method %} {% sample lang="jl" %} [import:30-32, lang:"julia"](code/julia/graham.jl) +{% sample lang="c" %} +[import:24-26, lang:"c_cpp"](code/c/graham.c) {% endmethod %} If the output of this function is 0, the points are collinear. @@ -30,6 +32,8 @@ In the end, the code should look something like this: {% method %} {% sample lang="jl" %} [import:34-69, lang:"julia"](code/julia/graham.jl) +{% sample lang="c" %} +[import:65-95, lang:"c_cpp"](code/c/graham.c) {% endmethod %} ### Bibliography @@ -41,6 +45,8 @@ In the end, the code should look something like this: {% method %} {% sample lang="jl" %} [import, lang:"julia"](code/julia/graham.jl) +{% sample lang="c" %} +[import, lang:"c_cpp"](code/c/graham.c) {% endmethod %}