import { describe, expect, it } from 'vitest'; import { buildPier, blockFramePoint } from '../src/core/geometry'; import { loadP1 } from './helpers'; const model = buildPier(loadP1()); const front = model.blocks.filter((b) => b.row === '전열'); const back = model.blocks.filter((b) => b.row === '후열'); describe('받침블럭 방위 (삽도 · 승인 2026-10-23)', () => { it('P1 rows are skewed by the bearing azimuth against the axis perpendicular: front ≈ −4.42°, back ≈ −3.11°', () => { expect(front.every((b) => Math.abs(b.rowSkewDeg - -4.42) < 0.02)).toBe(true); expect(back.every((b) => Math.abs(b.rowSkewDeg - -3.11) < 0.02)).toBe(true); }); it('a block side follows the bearing row: the n side of a block runs along (−sinδ, cosδ)', () => { const b = front[0]; const [s1, n1] = blockFramePoint(b, 0, -0.6); const [s2, n2] = blockFramePoint(b, 0, 0.6); const ds = s2 - s1; const dn = n2 - n1; const len = Math.hypot(ds, dn); const d = (b.rowSkewDeg * Math.PI) / 180; expect(ds / len).toBeCloseTo(-Math.sin(d), 9); expect(dn / len).toBeCloseTo(Math.cos(d), 9); }); it('turning keeps the block centre and the bearing spacing (the row is unchanged)', () => { const b = front[0]; const [s0, n0] = blockFramePoint(b, 0, 0); expect(s0).toBeCloseTo(b.s, 12); expect(n0).toBeCloseTo(b.n, 12); }); it('the turned block corners stay inside the coping ends', () => { const L = model.copingL; for (const b of model.blocks) { for (const [a, c] of [[-0.6, -0.6], [-0.6, 0.6], [0.6, -0.6], [0.6, 0.6]] as const) { const [s] = blockFramePoint(b, a, c); expect(s, `block ${b.no}`).toBeGreaterThan(0); expect(s, `block ${b.no}`).toBeLessThan(L); } } }); });