fix: guard flattenArc against zero-radius (degenerate) arcs

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
sjat 2026-06-08 22:13:58 +02:00
parent 7ddaee1454
commit e475626497
2 changed files with 10 additions and 1 deletions

View file

@ -32,4 +32,9 @@ describe('flattenArc', () => {
const fine = flattenArc([10, 0], [0, 10], [0, 0], false, 0.01); const fine = flattenArc([10, 0], [0, 10], [0, 0], false, 0.01);
expect(fine.length).toBeGreaterThan(coarse.length); expect(fine.length).toBeGreaterThan(coarse.length);
}); });
it('returns a straight segment for a degenerate zero-radius arc', () => {
const pts = flattenArc([5, 5], [5, 5], [5, 5], false, 0.1);
expect(pts).toEqual([[5, 5], [5, 5]]);
});
}); });

View file

@ -16,6 +16,10 @@ export function flattenArc(
clockwise: boolean, clockwise: boolean,
tolerance = 0.2, tolerance = 0.2,
): Vec2[] { ): Vec2[] {
// Degenerate (zero-radius) arc: nothing to sweep, return a straight segment.
const r0 = Math.hypot(start[0] - center[0], start[1] - center[1]);
if (r0 < 1e-9) return [[start[0], start[1]], [end[0], end[1]]];
const radius = Math.hypot(start[0] - center[0], start[1] - center[1]); const radius = Math.hypot(start[0] - center[0], start[1] - center[1]);
const startAngle = Math.atan2(start[1] - center[1], start[0] - center[0]); const startAngle = Math.atan2(start[1] - center[1], start[0] - center[0]);
const endAngle = Math.atan2(end[1] - center[1], end[0] - center[0]); const endAngle = Math.atan2(end[1] - center[1], end[0] - center[0]);
@ -27,7 +31,7 @@ export function flattenArc(
while (sweep <= 0) sweep += 2 * Math.PI; // sweep in (0, 2π] while (sweep <= 0) sweep += 2 * Math.PI; // sweep in (0, 2π]
} }
const maxStep = radius > tolerance ? 2 * Math.acos(1 - tolerance / radius) : Math.PI / 8; const maxStep = radius > tolerance ? 2 * Math.acos(1 - tolerance / radius) : Math.PI / 8; // fallback step for tiny radii
const steps = Math.max(1, Math.ceil(Math.abs(sweep) / maxStep)); const steps = Math.max(1, Math.ceil(Math.abs(sweep) / maxStep));
const pts: Vec2[] = []; const pts: Vec2[] = [];