Published
Edited
Sep 14, 2019
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function triangulate(poly, context) {
const pl = poly.length;
const triangles = [];
const polyC = poly.slice();

if (pl <= 3) return poly;

const [left, index] = polyC.reduce(
(acc, cur, i) => {
const [old, ind] = acc;
if (old.length === 0) return [cur, i];
if (cur[0] < old[0]) return [cur, i];
if (cur[0] === old[0]) {
if (cur[1] < old[1]) return [cur, i];
}
return acc;
},
[[], -1]
);

let trian = [
polyC[index > 0 ? index - 1 : pl - 1],
polyC[index],
polyC[(index + 1) % pl]
];
const ccw = orientation(trian);

while (polyC.length >= 3) {
let reflex = [];
let eartip = -1;

for (let i = 0; i < polyC.length; ++i) {
if (eartip >= 0) break;

const p = i > 0 ? i - 1 : polyC.length - 1;
const n = (i + 1) % polyC.length;
const tri = [polyC[p], polyC[i], polyC[n]];

if (orientation(tri) !== ccw) {
// triangle(tri, context, { color: "rgba(255,0,0,0.1)" });
reflex.push(i);
}

let isEar = true;
for (let j = 0; j < reflex.length; ++j) {
if (reflex[j] === p || reflex[j] === n) continue;
if (inTriangle(tri, polyC[reflex[j]])) {
isEar = false;
break;
}
}

if (isEar) {
for (let j = i + 1; j < polyC.length; ++j) {
if (j === p || j === n) continue;
if (inTriangle(tri, polyC[j])) {
isEar = false;
break;
}
}
}

if (isEar) eartip = i;
}

if (eartip < 0) break;

const earp = eartip > 0 ? eartip - 1 : polyC.length - 1;
const earn = (eartip + 1) % polyC.length;
const parts = [polyC[earp], polyC[eartip], polyC[earn]];

triangles.push(parts);
polyC.splice(eartip, 1);
}

return triangles;
}
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more