fix(bearing): 짝 받침은 거더를 따라 처음 만나는 받침 (직선교 후열 오짝 방지)
검토(2026-11-06): 후열이 전열과 같은 거더 선 위에 같은 방위각으로 놓이면(직선교) 거더선 거리가 둘 다 0이라, A1 받침이 더 먼 P1 후열(다음 경간)과 짝을 짓고 모든 받침에 WS04가 떴다. - 후보(진행 방향, 방위각 ≤ 0.1°, 거더선 ≤ 0.1 m) 중 거더를 따라 가장 가까운 받침을 짝으로 한다 - 그와 0.5 m 이내로 비슷한 거리의 후보가 더 있을 때만 WS04, 그중 거더선에 가까운 것 사용 - 테스트: A1 + A2만(교각 없음) 짝 성립 S −2 %, A1 + P1에서 전열 계산 · 후열 전열 값 가정(WS03), 직선교 합성 입력에서 전열 ①–⑤와 짝 · WS04 없음 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
364b329c54
commit
9d357de4d1
2 files changed
+48
-5
No files matched your search
@@ -77,3 +77,39 @@ describe('교량 전체 짝 받침 (bridgePairs, 구조물 순서 A1 · P1 …
|
||||
expect(pairs.map((p) => `${p.from.structure}${p.from.no}-${p.to.structure}${p.to.no}`)).toEqual(['A11-P11', 'A12-P12', 'A13-P13', 'A14-P14', 'A15-P15']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('짝 받침 성립 범위 (검토 2026-11-06)', () => {
|
||||
// A2 made from A1: each bearing moved 30 m along its girder and 0.6 m lower (S −2 %).
|
||||
const a2 = { ...a1, name: 'A2', type: 'A2' as const, bearings: a1.bearings.map((b) => {
|
||||
const t = (b.azimuthDeg! * Math.PI) / 180;
|
||||
return { ...b, pos: { e: b.pos.e + 30 * Math.sin(t), n: b.pos.n + 30 * Math.cos(t) }, z: b.z - 0.6 };
|
||||
}) };
|
||||
|
||||
it('A1 and A2 only (one span, no pier): A1 ①–⑤ pair with A2 ①–⑤, S −2 %', async () => {
|
||||
const { bridgePairs } = await import('../src/core/bridge-pairs');
|
||||
const pairs = bridgePairs([], [a1, a2]);
|
||||
expect(pairs.map((p) => `${p.from.structure}${p.from.no}-${p.to.structure}${p.to.no}`)).toEqual(['A11-A21', 'A12-A22', 'A13-A23', 'A14-A24', 'A15-A25']);
|
||||
expect(pairs.every((p) => Math.abs(p.slopePct + 2) < 1e-6 && p.warnings.length === 0)).toBe(true);
|
||||
});
|
||||
|
||||
it('A1 and P1 only: the front row ①–⑤ is computed from A1, the back row ⑥–⑩ takes the assumed front value (가정, WS03)', async () => {
|
||||
const { bridgePairs } = await import('../src/core/bridge-pairs');
|
||||
const { buildPier } = await import('../src/core/geometry');
|
||||
const m = buildPier(p1, { pairs: bridgePairs([p1], [a1]) });
|
||||
const front = m.soles.filter((s) => s.row === '전열'), back = m.soles.filter((s) => s.row === '후열');
|
||||
expect(front.every((s) => s.slopeSource === '계산' && s.pair?.structure === 'A1')).toBe(true);
|
||||
expect(back.every((s, i) => s.slopeSource === '가정' && !s.pair && s.slopePct === front[i].slopePct && s.warnings.includes('WS03'))).toBe(true);
|
||||
});
|
||||
|
||||
it('straight bridge: a back row on the same girder lines is not taken for the A1 partner (the nearest along the girder is)', () => {
|
||||
const straight: PairStructure = { name: 'P1', bearings: P1.bearings.map((b) => {
|
||||
if (b.no <= 5) return b;
|
||||
const f = P1.bearings.find((q) => q.no === b.no - 5)!;
|
||||
const t = (f.azimuthDeg * Math.PI) / 180;
|
||||
return { ...b, azimuthDeg: f.azimuthDeg, x: f.x + 1.2 * Math.sin(t), y: f.y + 1.2 * Math.cos(t) };
|
||||
}) };
|
||||
const pairs = girderPairs([A1, straight]);
|
||||
expect(pairs.map((p) => p.to.no)).toEqual([1, 2, 3, 4, 5]);
|
||||
expect(pairs.every((p) => p.warnings.length === 0)).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user