fix(abut): 교대 받침 방위각을 읽어 받침블럭 회전에 반영

- 원인: 교대 파서가 받침 시트의 방위각 열(6번째)을 읽지 않아, 블럭이 항상 교대축에 맞춰 그려졌음
- 방위각을 교각과 같은 변환(swapXYAzimuth)으로 읽고, 교대축 직각 기준 블럭 회전각(rotDeg)을 계산해 블럭·몰탈패드를 블럭 중심에서 회전
- 운곡교 A1: 회전 약 4.42° (교각 규칙과 같은 값). 날개벽(skew) 선과의 차이는 0.63°로 시안 AW01 값과 같음
- ② 받침 ELEVATION TABLE에 방위각 CAD / 진북, 블럭 회전 열 추가. 읽을 수 없는 방위각은 AP08 경고 후 축 방향 유지
- 테스트 5건 추가, 전체 647건 통과, 타입 검사·빌드 통과. 브라우저 시각 확인은 미실시

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ypshimandClaude Opus 5.5 committed 2026-11-03 18:20:05 +09:00
1 parent 7e3ba306f3
commit 4e3950eb67
7 files changed
+106 -6

No files matched your search

+11 -1
View File
@@ -7,6 +7,7 @@
*/
import * as XLSX from 'xlsx';
import { parseDms } from '../dms';
import { swapXYAzimuth } from '../coordinate-frame';
import type { Issue } from '../types';
import type { AbutInput, AbutPoint, AbutType, WingForm } from './geometry';
import type { AbutShape } from './shape';
@@ -24,6 +25,8 @@ export interface AbutRecordBearing {
seatEl?: number;
/** 이 받침에 적힌 받침높이 (mm). */
bearingHeightMm: number;
/** 받침 방위각 (deg, model-xy, 교각과 같은 swapXYAzimuth 변환). 비었거나 읽을 수 없으면 없음. */
azimuthDeg?: number;
row: string;
}
@@ -162,12 +165,19 @@ export function parseAbutments(wb: XLSX.WorkBook): AbutParseResult {
continue;
}
const h = num(c[8]);
if (!isBlank(c[5]) && parseDms(String(c[5])) === null) {
issues.push({ code: 'AP08', level: 'W', pier: ab.name, sheet: rec.sheet, message: `${rec.sheet} ${rec.row}행: 받침 방위각을 읽을 수 없습니다. 예: 75°56'55.9" 형식. 블럭은 교대축에 맞춥니다.` });
}
ab.bearings.push({
no: num(c[1]),
pos: { e: num(c[3]), n: num(c[2]) },
z: num(c[4]),
seatEl: isBlank(c[7]) ? undefined : num(c[7]),
bearingHeightMm: h,
azimuthDeg: (() => {
const deg = isBlank(c[5]) ? null : parseDms(String(c[5]));
return deg === null ? undefined : swapXYAzimuth(deg);
})(),
row: `${rec.sheet} ${rec.row}행`,
});
}
@@ -193,7 +203,7 @@ export function toAbutInput(rec: AbutRecord): AbutInput {
ip1: rec.ip1,
ip2: rec.ip2,
ip3: rec.ip3,
bearings: rec.bearings.map((b) => ({ no: b.no, pos: b.pos, z: b.z, seatEl: b.seatEl })),
bearings: rec.bearings.map((b) => ({ no: b.no, pos: b.pos, z: b.z, seatEl: b.seatEl, azimuthDeg: b.azimuthDeg })),
skewDeg: rec.skewDeg,
slopeI: rec.slopeI,
wings: rec.wings,