fix(shape): 받침 번호가 축 반대 방향이어도 계단을 g 순서로 만든다

전·후열 받침 수가 같으면 받침을 번호 순서로 두어, 번호가 IP1 → IP3 반대로 매겨진 교각(산외교 P9: ① g 12.1,
③ g 1.3)에서 계단 경계가 거꾸로(9.42 → 4.02) 놓이고 코핑 상면이 틀렸다. 받침을 늘 g 순서로 정렬한다.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Haiku 5.5 committed 2026-11-10 16:55:22 +09:00
1 parent 7340f8c1a1
commit 0b3087e752
2 files changed
+19 -1

No files matched your search

+3 -1
View File
@@ -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 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) })); 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). // 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 // A step boundary less than half a block from the kink moves onto it (2026-11-10), so the step face is the mitre
+16
View File
@@ -115,3 +115,19 @@ describe('꺾임점 계단면 = 미터면 (2026-11-10)', () => {
expect(topAt(m, backPart(0).profile, kink + DIM.blockSize / 2 + 0.1)).toBeCloseTo(after, 9); 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));
});
});