@thi.ng/geom-tessellate
Version:
2D/3D convex polygon tessellators
49 lines (48 loc) • 1.24 kB
JavaScript
import { pointInTriangle2 } from "@thi.ng/geom-isec/point";
import { polyArea2 } from "@thi.ng/geom-poly-utils/area";
import { range } from "@thi.ng/transducers/range";
import { signedArea2 } from "@thi.ng/vectors/signed-area";
const earCut = (tess, faces, pids) => {
let n = pids.length;
const points = tess.pointsForIDs(pids);
const order = [
...polyArea2(points) > 0 ? range(n) : range(n - 1, -1, -1)
];
let count = 2 * n - 1;
let v = n - 1, u, w;
while (count > 0 && n > 2) {
u = n <= v ? 0 : v;
v = u + 1;
v = n <= v ? 0 : v;
w = v + 1;
w = n <= w ? 0 : w;
if (__snip(points, u, v, w, n, order)) {
faces.push([pids[order[u]], pids[order[v]], pids[order[w]]]);
order.splice(v, 1);
n--;
count = 2 * n;
} else {
count--;
}
}
return faces;
};
const __snip = (points, u, v, w, n, ids) => {
const a = points[ids[u]];
const b = points[ids[v]];
const c = points[ids[w]];
if (signedArea2(a, b, c) > 0) {
for (let i = 0; i < n; i++) {
if (i !== u && i !== v && i !== w) {
if (pointInTriangle2(points[ids[i]], a, b, c)) {
return false;
}
}
}
return true;
}
return false;
};
export {
earCut
};