function getVoronoiCellBorders(origin) {
function getMidLine(p) {
const midPoint = vec2.scale([], p, 0.5);
const normal = vec2.normalize([], p);
const tangent = vec2.rotate([], normal, [0, 0], Math.PI / 2);
return [midPoint, tangent];
}
let candidates = points.filter(p => !vec2.exactEquals(p, origin));
candidates = [...borderPoints, ...candidates];
candidates = candidates.map(p => vec2.sub([], p, origin));
candidates = groupBy(candidates, p => Math.atan2(p[1], p[0]));
candidates = sortedBy(candidates, ([a]) => a);
candidates = candidates.map(([, gps]) => sortedBy(gps, vec2.len)[0]);
candidates = candidates.map(getMidLine);
while (true) {
const candidates2 = neighborwiseFilter(
candidates,
(lp, l, ln) => paramLineIntersection(l, lp) < paramLineIntersection(l, ln)
);
if (candidates2.length == candidates.length) {
break;
}
candidates = candidates2;
}
return neighborwise(candidates).map(([lp, l, ln]) => [
vec2.add([], origin, paramLine(l, paramLineIntersection(l, lp))),
vec2.add([], origin, paramLine(l, paramLineIntersection(l, ln)))
]);
}