Files
tts-workshop/packages/mesh/src/trace.test.ts
T
hypercross 15c45e7106 refactor: share trace, error boundary, and proxy http helpers
Lift the trace-to-shape geometry into @tts/mesh (traceToShape/
traceToUvBounds), parameterized by scale so the web token viewer and
@tts/tabletop share one implementation. Move the CORS proxy HTTP helpers
(assetUrl, resolveAssetUrl, traceImage) into a new @tts/http package, and
make @tts/tabletop's ErrorBoundary the single source used by the web app.

This removes the duplicated ErrorBoundary, assetUrl, tabletopHttp, and
trace-to-shape code from apps/web and packages/tabletop.
2026-08-09 22:17:24 +08:00

45 lines
1.3 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { traceToShape, traceToUvBounds } from './trace.js';
describe('traceToShape', () => {
it('flips y and centers the traced shape', () => {
const trace = {
shape: { outline: [[0, 0], [10, 0], [10, 10], [0, 10]] },
width: 10,
height: 10,
};
const shape = traceToShape(trace, 0.2);
// Centered at origin, scaled to fit the 2x2 box. The y-flip reverses
// winding, so the outline is normalized to CCW (order may differ).
expect(shape.outline).toHaveLength(4);
expect(shape.outline).toEqual(
expect.arrayContaining([
[-1, 1],
[1, 1],
[1, -1],
[-1, -1],
]),
);
});
it('maps holes to clockwise winding', () => {
const trace = {
shape: {
outline: [[0, 0], [10, 0], [10, 10], [0, 10]],
holes: [[[2, 2], [2, 8], [8, 8], [8, 2]]],
},
width: 10,
height: 10,
};
const shape = traceToShape(trace, 0.2);
expect(shape.holes).toHaveLength(1);
expect(shape.holes![0]).toHaveLength(4);
});
});
describe('traceToUvBounds', () => {
it('maps the full image rectangle to the part box', () => {
const bounds = traceToUvBounds({ width: 10, height: 20 }, 0.2);
expect(bounds).toEqual({ minX: -1, minY: -2, maxX: 1, maxY: 2 });
});
});