diff --git a/src/core/geometry.ts b/src/core/geometry.ts index 792f566..9f1ed5e 100644 --- a/src/core/geometry.ts +++ b/src/core/geometry.ts @@ -331,7 +331,9 @@ export function buildPier(input: PierInput, ctx: PierContext = {}): PierModel { }; const frontPlaced = front.map((b) => ({ no: b.no, row: '전열' as Row, z: b.z, ...place(b) })); const backPlaced = back.map((b) => ({ no: b.no, row: '후열' as Row, z: b.z, ...place(b) })); - if (unequalRows) { frontPlaced.sort((a,b)=>a.g-b.g); backPlaced.sort((a,b)=>a.g-b.g); } + // Rows run along the coping (2026-11-10): bearing numbers may run against IP1 → IP3 (산외교 P9 ① at g 12.1, ③ at 1.3), + // so the steps are always built in g order, not number order. + frontPlaced.sort((a,b)=>a.g-b.g); backPlaced.sort((a,b)=>a.g-b.g); // Step boundaries sit midway between consecutive front bearings in coping coordinates (spec §4.3). // A step boundary less than half a block from the kink moves onto it (2026-11-10), so the step face is the mitre diff --git a/tests/kink-steps.test.ts b/tests/kink-steps.test.ts index b72dd1a..9e25fcd 100644 --- a/tests/kink-steps.test.ts +++ b/tests/kink-steps.test.ts @@ -115,3 +115,19 @@ describe('꺾임점 계단면 = 미터면 (2026-11-10)', () => { expect(topAt(m, backPart(0).profile, kink + DIM.blockSize / 2 + 0.1)).toBeCloseTo(after, 9); }); }); + +describe('받침 번호가 축 반대 방향인 교각 (2026-11-10)', () => { + it('steps are built in g order: bounds rise and each step top is its own bearing seat', () => { + // P1 with the bearing numbers reversed in each row (⑤ … ① along IP1 → IP3). + const p1 = (() => { + const wb = XLSX.read(readFileSync(fileURLToPath(new URL('../도면추출/samples/운곡교P1입력.xlsx', import.meta.url))), { type: 'buffer' }); + return parseWorkbook(wb).piers.find((p) => p.name === 'P1')!; + })(); + const renumber = (no: number) => (no <= 5 ? 6 - no : 16 - no); + const reversed = { ...p1, bearings: p1.bearings.map((b) => ({ ...b, no: renumber(b.no) })) }; + const a = buildPier(p1), b = buildPier(reversed); + for (const m of [a, b]) m.segments.forEach((s) => expect(s.s1).toBeGreaterThan(s.s0)); + expect(b.segments.map((s) => s.top)).toEqual(a.segments.map((s) => s.top)); + expect(b.segments.map((s) => s.s0)).toEqual(a.segments.map((s) => s.s0)); + }); +});