Files
Aislo/A00_Common/design/logic/design_calc_node_follow.ts
T
eomsangdonandClaude Opus 5.5 162d32620e refactor(472-4 ① 시설 따라감): 서버 구조물 따라감도 TS followStructures 한 벌 — Node 입구 facility.follow
- common_util_route_follow.follow_structures = run_calc 겉(같은 계약 · 제자리 고침 · site 간격 = 서버 측점 간격)
- 저장 때 좌표 맞춤 fill_structure_coordinates 는 파이썬 남음(옛 좌표 지킴 · 0.1 mm 반올림 — TS placeOnLine 과 규칙 달라 옮기면 값 바뀜) · 등록부 note
- 등록부 node:facility.follow · NODE_IDS · 시험 test_472_4_follow_node(옛 코드 빨강) · 344_2 · 380_3 · 410 · 459 통과

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 09:39:54 +09:00

87 lines
3.2 KiB
TypeScript

/* =============================================================================
* A00_Common/design/logic/design_calc_node_follow.ts
* 계산 Node 입구(`design_calc_node.ts`)의 따라감 몫(PLAN 472-4 ①) — 측점 열쇠 · 시설 따라감 · 추가 측점 ·
* 꼭짓점 세움. 브라우저 묶음이 쓰는 같은 TS 를 부름 · 파이썬은 `common_util_calc_runner.run_calc` 로.
*
* profile.seat 입력 seat { ground_s · ground_z(저장 선형 표본) · policy(파이썬 `AlignmentPolicy.as_dict`) ·
* base_pvi(옮기기 전) · base(옮긴 꼭짓점) · born · held } → 꼭짓점 목록(`seatBornNodes`)
* facility.follow 입력 follow { items: [{ placement · chainage_m · start_m · end_m · x · y }] · line ·
* max_drift_m · interval_m(site 맞춤 간격) } → [{ item · drift_m · far }](`followStructures`)
* facility.plus_follow 입력 plus { rows: [{ chainage_m · x · y }] · line: [[x, y]](새 노선) } →
* { rows: [{ chainage_m · x · y }](`followPlusRows` · 정수 m · 같은 m 하나) · moved: 옮긴 수 }
* ========================================================================== */
import { seatBornNodes } from "../../../B05_Profile/logic/B05_Profile_Grade_Seat";
import {
followPlusRows,
followStructures,
type FollowingStructure,
} from "@util/common_util_route_follow";
import type {
AlignmentNode,
AlignmentPolicy,
} from "../../../B05_Profile/logic/B05_Profile_UI_Profile_Alignment";
type Line = Array<[number, number]>;
const xyOf = (line: Line) => line.map(([x, y]) => ({ x, y }));
export interface FollowInputs {
follow?: {
items: FollowingStructure[];
line: Line;
max_drift_m?: number;
interval_m?: number | null;
};
plus?: { rows: Array<{ chainage_m: number; x?: number | null; y?: number | null }>; line: Line };
seat?: {
ground_s: number[];
ground_z: number[];
policy: AlignmentPolicy;
base_pvi: AlignmentNode[];
base: AlignmentNode[];
born: number[];
held?: number[];
};
}
/** id → 셈(입구 `RUNNERS` 에 얹음). */
export function followRunners(inputs: FollowInputs): Record<string, () => unknown> {
return {
"profile.seat": () => {
const seat = inputs.seat;
if (!seat) return null;
const base = {
chainage: seat.ground_s,
ground: seat.ground_z,
policy: seat.policy,
basePvi: seat.base_pvi,
};
return seatBornNodes(base, seat.base, seat.born, seat.held ?? []);
},
"facility.follow": () => {
const follow = inputs.follow;
if (!follow) return null;
return followStructures(
follow.items,
xyOf(follow.line),
follow.max_drift_m,
follow.interval_m ?? null,
);
},
"facility.plus_follow": () => {
const plus = inputs.plus;
if (!plus) return null;
const line = xyOf(plus.line);
const moved = followStructures(plus.rows, line).filter(
({ item }, index) => item.chainage_m !== plus.rows[index].chainage_m,
).length;
const rows = followPlusRows(plus.rows, line).map(({ chainage_m, x, y }) => ({
chainage_m,
x: x ?? null,
y: y ?? null,
}));
return { rows, moved };
},
};
}