function noiseCurvePartition(params = simplexParams, options = {}) {
const { width = 800, height = 600 } = options;
const { sampleForwards, sampleBackwards, sampleLeft, sampleRight } =
curveGenFunctions(params, {
width,
height
});
const segmentBall = (a, b, i = -1) => {
const r = vec2.dist(a, b) / 2;
const c = vec2.lerp([], a, b, 0.5);
const ball = new Ball(...c, r);
ball.segment = { a, b, i };
return ball;
};
const intersectsOther = (a, b, bt) => {
const ball = segmentBall(a, b);
for (let other of bt.within(ball, ball.r)) {
if (
vec2.segmentsIntersect(
ball.segment.a,
ball.segment.b,
other.entry.segment.a,
other.entry.segment.b
)
)
return other.entry.segment;
}
return false;
};
return (polygon, sideways = false) => {
const bt = new OnlineBT();
let a = polygon[polygon.length - 1];
for (let i = 0; i < polygon.length; i++) {
const b = polygon[i];
bt.insert(segmentBall(a, b, i));
a = b;
}
const p = findPointInPolygon(polygon);
if (!p) throw "can't find a point inside the polygon";
const pts = [p];
a = p;
let count = 1000;
let exitSegmentA;
const [followA, followB] = sideways
? [sampleBackwards, sampleForwards]
: [sampleLeft, sampleRight];
do {
let b = followA(...a);
let seg = intersectsOther(a, b, bt);
if (seg) {
exitSegmentA = seg.i;
let q = vec2.lineIntersection([], a, b, seg.a, seg.b);
pts.push(q);
break;
}
pts.push(b);
a = b;
} while (count--);
console.assert(count > 0);
a = p;
count = 1000;
pts.reverse();
let exitSegmentB;
do {
let b = followB(...a);
let seg = intersectsOther(a, b, bt);
if (seg) {
exitSegmentB = seg.i;
let q = vec2.lineIntersection([], a, b, seg.a, seg.b);
pts.push(q);
break;
}
pts.push(b);
a = b;
} while (count--);
console.assert(count > 0);
if (exitSegmentA == exitSegmentB) {
console.log({ exitSegmentA, first: pts[0], last: pts[pts.length - 1] });
}
const polygonA = [...pts, polygon[exitSegmentB]];
for (
let i = (exitSegmentB + 1) % polygon.length;
i != exitSegmentA;
i = (i + 1) % polygon.length
)
polygonA.push(polygon[i]);
const polygonB = [...pts.reverse()];
for (let i = exitSegmentA; i != exitSegmentB; i = (i + 1) % polygon.length)
polygonB.push(polygon[i]);
return [polygonA, polygonB];
};
}