95 lines
2.4 KiB
C
95 lines
2.4 KiB
C
#include "include/geom.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
Tri* alltris[512];
|
|
size_t allsize = 0;
|
|
|
|
Tri* tri_init(Pt a, Pt b, Pt c) {
|
|
Tri* tri = malloc(sizeof(Tri));
|
|
*(alltris + allsize) = tri;
|
|
allsize++;
|
|
*tri = (Tri){a, b, c};
|
|
return tri;
|
|
}
|
|
|
|
bool tri_within(Pt pt, Tri* tri) {
|
|
double denom =
|
|
((tri->b.y - tri->c.y) * (tri->a.x - tri->c.x) +
|
|
(tri->c.x - tri->b.x) * (tri->a.y - tri->c.y));
|
|
double a = ((tri->b.y - tri->c.y) * (pt.x - tri->c.x) +
|
|
(tri->c.x - tri->b.x) * (pt.y - tri->c.y)) /
|
|
denom;
|
|
double b = ((tri->c.y - tri->a.y) * (pt.x - tri->c.x) +
|
|
(tri->a.x - tri->c.x) * (pt.y - tri->c.y)) /
|
|
denom;
|
|
double c = 1 - a - b;
|
|
return 0 <= a && a <= 1 && 0 <= b && b <= 1 && 0 <= c && c <= 1;
|
|
}
|
|
|
|
Pt tri_center(Tri* tri) {
|
|
return (Pt){(tri->a.x + tri->b.x + tri->c.x) / 3.0,
|
|
(tri->a.y + tri->b.y + tri->c.y) / 3.0};
|
|
}
|
|
|
|
int pt_cmp(const void* a, const void* b) {
|
|
const Pt* p = (const Pt*)a;
|
|
const Pt* q = (const Pt*)b;
|
|
|
|
if (p->x != q->x) return p->x - q->x;
|
|
return p->y - q->y;
|
|
}
|
|
|
|
static int pt_cross(const Pt a, const Pt b, const Pt c) {
|
|
return ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x));
|
|
}
|
|
|
|
Pt* cvx_hull(Pt* area, size_t n, size_t* out_n) {
|
|
if (!area || n <= 0) return NULL;
|
|
|
|
if (n == 1) {
|
|
Pt* out = malloc(2 * sizeof(Pt));
|
|
if (n == 1) out[0] = area[0];
|
|
*out_n = 1;
|
|
printf("bad things are happening... %s\n", __FUNCTION__);
|
|
return out;
|
|
}
|
|
|
|
Pt* pts = malloc(n * sizeof(Pt));
|
|
for (size_t i = 0; i < n; i++) pts[i] = area[i];
|
|
|
|
// Sort the points.
|
|
qsort(pts, n, sizeof(Pt), pt_cmp);
|
|
|
|
// Max hull size is 2 * n.
|
|
Pt* hull = malloc(2 * n * sizeof(Pt));
|
|
size_t k = 0;
|
|
|
|
// Lower hull.
|
|
for (size_t i = 0; i < n; i++) {
|
|
while (k >= 2 && pt_cross(hull[k - 2], hull[k - 1], pts[i]) <= 0) k--;
|
|
|
|
hull[k++] = pts[i];
|
|
}
|
|
|
|
// Upper hull.
|
|
for (size_t i = n - 1, t = k + 1; i > 0; i--) {
|
|
while (k >= t && pt_cross(hull[k - 2], hull[k - 1], pts[i - 1]) <= 0)
|
|
k--;
|
|
|
|
hull[k++] = pts[i - 1];
|
|
}
|
|
|
|
// Remove duplicated end/start point.
|
|
k--;
|
|
|
|
Pt* out = malloc(k * sizeof(Pt));
|
|
for (size_t i = 0; i < k; i++) { out[i] = hull[i]; }
|
|
|
|
*out_n = k;
|
|
free(pts);
|
|
free(hull);
|
|
return out;
|
|
}
|