36 lines
1.5 KiB
TypeScript
36 lines
1.5 KiB
TypeScript
|
|
import { describe, it, expect } from 'vitest';
|
||
|
|
import { flattenArc } from './arc';
|
||
|
|
|
||
|
|
const onCircle = (p: [number, number], c: [number, number], r: number) =>
|
||
|
|
Math.abs(Math.hypot(p[0] - c[0], p[1] - c[1]) - r) < 1e-6;
|
||
|
|
|
||
|
|
describe('flattenArc', () => {
|
||
|
|
it('flattens a CCW quarter circle, endpoints exact, all points on the circle', () => {
|
||
|
|
// centre (0,0), radius 10, from (10,0) CCW to (0,10)
|
||
|
|
const pts = flattenArc([10, 0], [0, 10], [0, 0], false, 0.1);
|
||
|
|
expect(pts[0]).toEqual([10, 0]);
|
||
|
|
expect(pts[pts.length - 1]).toEqual([0, 10]);
|
||
|
|
expect(pts.length).toBeGreaterThan(2);
|
||
|
|
for (const p of pts) expect(onCircle(p, [0, 0], 10)).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('CW arc sweeps the other way (midpoint has negative y)', () => {
|
||
|
|
// centre (0,0), radius 10, from (10,0) CW to (0,10) → goes the long way through y<0
|
||
|
|
const pts = flattenArc([10, 0], [0, 10], [0, 0], true, 0.1);
|
||
|
|
const mid = pts[Math.floor(pts.length / 2)];
|
||
|
|
expect(mid[1]).toBeLessThan(0);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('treats start==end as a full circle', () => {
|
||
|
|
const pts = flattenArc([10, 0], [10, 0], [0, 0], false, 0.5);
|
||
|
|
// a point roughly opposite the start should exist
|
||
|
|
expect(pts.some((p) => p[0] < -9)).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('respects chord tolerance (tighter tolerance → more points)', () => {
|
||
|
|
const coarse = flattenArc([10, 0], [0, 10], [0, 0], false, 1.0);
|
||
|
|
const fine = flattenArc([10, 0], [0, 10], [0, 0], false, 0.01);
|
||
|
|
expect(fine.length).toBeGreaterThan(coarse.length);
|
||
|
|
});
|
||
|
|
});
|