Files
Aislo/B05_Profile/B05_Profile_UI_Page_Stations.ts
T
eomsangdonandClaude Opus 5.5 93e86f87c6 fix(b05,b06): 측점 한 벌 — 정수 m · 같은 m 측점 하나 · 목록 전체 다시 맞춤 (272)
- 규칙: 구조물 · 관 기준 측점 = 정수 m 사사오입(일반 측점 1 m 붙기 뺌) · 측점 심는 자리 TS 짝(plantedChainages ↔ resolve_extra_stations) · 같은 m 면 구조물 측점 하나(격자 자리 grid) · 떠나면 일반 측점(oneStationList ↔ _merge_irregular_into_longitudinal)
- 서버: B05 [저장] · B06 저장 · [측점 만들기]가 목록 전체 다시 맞춤(빈 목록도 · 옛 글 · 횡단 파일 글) · 계획선 측점 줄 다시 셈 · 정본에 없는 횡단 행은 0.5 m 안 새 측점으로 옮기고 나머지 지움 · 옛 소수 측점 꼭짓점 · 편집은 정수 자리로 · 맞춤 실패는 저장을 안 막음
- 화면: 종단 그래프 · 3D · 표 · ▲▼ 한 목록(초안 반영) · C군 구간형 · 독립 기슭막이 시작 · 끝 측점 · B06 카드는 초안에 없는 옛 구조물 측점 숨김 · 고름은 같은 m 구조물 측점 먼저 · 폼 거리 칸 정수 표기 · C군 계산 구간 · 포장 나눔 경계 정수
- 옛 자료: [정수 맞춤] 단추 없앰 · 종단 보기 열 때 한 번 자동 정수 · 알림 한 줄 · [저장]하면 남음
- 시험: test_272_1 · test_272_2 새로 · 234_1 · 238_1 · b05_extra_stations_supplier · b06_patch_station · b05_station_roundtrip · b05_b06_save_roundtrip 맞춤

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LLCk2y5xE8YGVgjbTntWsY
2026-10-11 19:53:24 +09:00

63 lines
3.5 KiB
TypeScript

/* =============================================================================
* B05_Profile_UI_Page_Stations.ts
* 종단 보기 3D **측점 바** 목록 — 규칙 측점 + 구조물(비정규) 측점 · 계획고 높이 · 상단측.
* 종단 보기 본체(`design_view_profile`)가 700줄을 넘어 여기로 뗐다(계획서 24-3b).
* ========================================================================== */
import { oneStationList } from "../common_util/common_util_structure_station";
import { interpolateIrregularStations } from "./B05_Profile_UI_Page_Helpers";
import type { IrregularStation } from "./B05_Profile_UI_IrregularStations";
import type { SectionDetailResponse } from "../B06_Section/B06_Section_Api_Fetch";
export interface StationLinesInput {
detail: SectionDetailResponse;
irregular: IrregularStation[];
routePoints: ReadonlyArray<{ x: number; y: number; z?: number | null }>;
/** 편집 중 라이브 계획선 샘플(없으면 정본 계획선). */
liveSamples: ReadonlyArray<{ chainage_m: number; elevation_m: number }> | null;
/** [예상형상] 켜짐 — 측점 바를 계획고 위로 올린다. */
corridorVisible: boolean;
}
export function stationLinesOf(input: StationLinesInput) {
const { detail } = input;
// 확정 때 종단 정본에 병합해 둔 비정규 측점은 그리지 않는다. 화면의 정본은 사이드바 목록이고
// 관을 옮기면 그 목록만 따라오므로, 둘을 겹쳐 그리면 옮기기 전 자리가 그대로 남는다
// (2026-08-02 사용자 보고). 저장분은 진입 시 `restoreSections`가 목록으로 되살린다.
const regular = oneStationList(detail.longitudinal.stations, []);
const injected = interpolateIrregularStations(
regular,
input.irregular,
detail.longitudinal.length_m,
// 중심 좌표는 노선 폴리라인 기준 — 3D 마커가 노선 위에 정확히 얹힌다(2026-08-19).
input.routePoints,
);
// 예상형상이 켜져 있으면 측점 바를 **계획고** 기준으로 올린다 — 원지반 위에
// 얹힌 예상형상에 묻혀 측점 기준선이 안 보이던 문제(2026-08-23 사용자 지시).
const designAt = (chainageM: number): number | null => {
if (!input.corridorVisible) return null;
// 편집 중에는 라이브 alignment 샘플이 정본보다 새것이다(2026-08-23 지적 ③).
const samples = input.liveSamples ?? detail.longitudinal.design_profiles?.[0]?.samples;
if (!samples?.length) return null;
let best = samples[0];
for (const sample of samples) {
if (Math.abs(sample.chainage_m - chainageM) < Math.abs(best.chainage_m - chainageM)) {
best = sample;
}
}
return best.elevation_m;
};
// 측점 바 양 끝 램프용 상단측: 사용자 변경분 → solve 자동 판정 순으로 적용.
// 측점 한 벌(272) — 같은 m 면 구조물 측점 하나 · 종단 그래프 · 표와 같은 목록(`oneStationList`).
return oneStationList(detail.longitudinal.stations, injected).map((station) => {
const design = designAt(station.chainage_m);
return {
...station,
// 절토 구간에서는 계획고가 지반보다 **아래**다(2026-09-04 사용자 지적).
// max 로 잡으면 코리도가 절취해 내려간 노면을 두고 막대만 원지반에 떠 있다.
// 코리도가 켜져 있으면(designAt 이 값을 줌) 계획고를 그대로 쓴다.
center_z: design !== null && station.center_z !== null ? design : station.center_z,
};
});
}