Files
Aislo/A00_Common/design/logic/design_pipeline_probe_station.ts
T
eomsangdonandClaude Opus 5.5 2454bd4ba0 feat(B05 종단): 원지반 점 작은 창 = 지금 계획선(초안 포함 · 묶음 같은 계산) (368-4)
- 묶음 출력 읽기만 · ground · cross 단계 함수를 그 자리 측점 하나로 다시 부름(파생 저장 · 캐시 안 씀)
- 그 자리 측점 = [측점 추가] 뒤 묶음 측점과 같은 틀 · 반경 · 확폭(logic/design_pipeline_probe_station)
- 격자 없음 · 분석 지형 다름 = 서버 미리 뜨기 + 「저장 계획선 기준」 한 줄 · 창 글에 계획고
- 묶음 cross 차례마다 떠 있는 창 다시 그림
- 거울 시험 test_368_4(곡선표 있음 · 없음 · 직선 · 곡선 안)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QyNXY2TUKXCFMwAca2APG
2026-10-17 13:05:23 +09:00

66 lines
2.8 KiB
TypeScript

/* =============================================================================
* A00_Common/design/logic/design_pipeline_probe_station.ts
* 아무 누가거리 측점 하나(368-4) — [측점 추가] 뒤 묶음 stations 단계(`buildStations`)가 낼 그 측점과 같은
* 자리 · 틀 · 방위 · 반경 · 확폭(기존 측점 + 그 자리 누가거리로 셈) · 열쇠 = 추가 측점(`structure:plus-{m}`).
* 거울 시험 = `resources/tester/test_368_4_probe_station.py`(buildStations + 추가 측점과 대조).
* ========================================================================== */
import { stationFrameAt } from "../../../B05_Profile/logic/B05_Profile_UI_RouteEdit_Frame";
import {
curveWidenings,
designCurveWidenings,
designSpans,
planRadii,
stationKey,
} from "../../../B05_Profile/logic/B05_Profile_Sections_Stations";
import { PLUS_OWNER_PREFIX } from "../../../common_util/common_util_structure_station";
import type { DesignCurve, PipelineStation, Vertex } from "./design_pipeline_types";
const round = (value: number, digits: number): number => Number(value.toFixed(digits));
/** 그 자리 측점(지반 전) — 노선 밖이면 null. `stations` = 지금 묶음 측점(반경 · 확폭 테이퍼 이웃). */
export function probeStation(
line: ReadonlyArray<Vertex>,
curves: ReadonlyArray<DesignCurve>,
stations: ReadonlyArray<PipelineStation>,
chainageM: number,
): PipelineStation | null {
const frame = stationFrameAt(line, chainageM);
if (!frame) return null;
const chainages = [...stations.map((s) => s.chainageM), chainageM].sort((a, b) => a - b);
const index = chainages.indexOf(chainageM);
const spans = designSpans(line, curves);
let radius: number | null;
let side: "left" | "right" | null;
let widening: number;
if (spans.length) {
const out = designCurveWidenings(chainages, spans);
[radius, side, widening] = [out.radii[index], out.sides[index], out.widenings[index]];
} else {
const total = Math.max(...stations.map((s) => s.chainageM), chainageM);
const measured = planRadii(line, chainages, total);
const tapered = curveWidenings(chainages, measured.radii, measured.sides);
[radius, side, widening] = [
measured.radii[index],
tapered.sides[index],
tapered.widenings[index],
];
}
const tangent: Vertex = [frame.left[1], -frame.left[0]];
const owner = `${PLUS_OWNER_PREFIX}${Math.round(chainageM)}`;
return {
key: stationKey("structure", owner, "anchor"),
chainageM: round(chainageM, 6),
x: round(frame.origin[0], 6),
y: round(frame.origin[1], 6),
azimuthDeg: round(((Math.atan2(tangent[0], tangent[1]) * 180) / Math.PI + 360) % 360, 6),
left: [round(frame.left[0], 9), round(frame.left[1], 9)],
kind: "structure",
id: owner,
ground: null,
planRadiusM: radius,
curveOuterSide: side,
curveWideningM: widening,
};
}