UNPKG

rabbit-ear

Version:
70 lines (66 loc) 2.45 kB
/* Rabbit Ear 0.9.4 alpha 2024-04-20 (c) Kraft, GNU GPLv3 License */ import { excludeR } from './compare.js'; import { subtract2, distance, flip2 } from './vector.js'; import { clockwiseBisect2 } from './radial.js'; import { nearestPointOnLine } from './nearest.js'; import { intersectLineLine } from './intersect.js'; const recurseSkeleton = (points, lines, bisectors) => { const intersects = points .map((origin, i) => ({ vector: bisectors[i], origin })) .map((ray, i, arr) => intersectLineLine( ray, arr[(i + 1) % arr.length], excludeR, excludeR, ).point); const projections = lines.map((line, i) => ( nearestPointOnLine(line, intersects[i]) )).map(([a, b]) => [a, b]); if (points.length === 3) { return points.map(p => ({ type: "skeleton", points: [p, intersects[0]] })) .concat([{ type: "perpendicular", points: [projections[0], intersects[0]] }]); } const projectionLengths = intersects .map((intersect, i) => distance(intersect, projections[i])); let shortest = 0; projectionLengths.forEach((len, i) => { if (len < projectionLengths[shortest]) { shortest = i; } }); const solutions = [ { type: "skeleton", points: [points[shortest], intersects[shortest]], }, { type: "skeleton", points: [points[(shortest + 1) % points.length], intersects[shortest]], }, { type: "perpendicular", points: [projections[shortest], intersects[shortest]] }, ]; const newVector = clockwiseBisect2( flip2(lines[(shortest + lines.length - 1) % lines.length].vector), lines[(shortest + 1) % lines.length].vector, ); const shortest_is_last_index = shortest === points.length - 1; points.splice(shortest, 2, intersects[shortest]); lines.splice(shortest, 1); bisectors.splice(shortest, 2, newVector); if (shortest_is_last_index) { points.splice(0, 1); bisectors.splice(0, 1); lines.push(lines.shift()); } return solutions.concat(recurseSkeleton(points, lines, bisectors)); }; const straightSkeleton = (points) => { const lines = points .map((p, i, arr) => [p, arr[(i + 1) % arr.length]]) .map(side => ({ vector: subtract2(side[1], side[0]), origin: side[0] })); const bisectors = points .map((_, i, ar) => [(i - 1 + ar.length) % ar.length, i, (i + 1) % ar.length] .map(j => ar[j])) .map(p => [subtract2(p[0], p[1]), subtract2(p[2], p[1])]) .map(([a, b]) => clockwiseBisect2(a, b)); return recurseSkeleton([...points], lines, bisectors); }; export { straightSkeleton };