Files
terrin/src/geom.c
2026-01-03 11:05:21 -05:00

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;
}