- 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>
87 lines
3.2 KiB
TypeScript
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 };
|
|
},
|
|
};
|
|
}
|