Files
Aislo/A00_Common/design/logic/design_calc_node_follow.ts
T

99 lines
3.9 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`)
* — follow.fill { previous?: { structure_id: 항목 } · only_missing } 있으면 = 저장 좌표 맞춤(같은 F1 ·
* 511-B B-5) → { xy: [{ x · y } | null(그대로)] · filled }(`fillStructureCoordinates` · items 에 structure_id)
* 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 {
fillStructureCoordinates,
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: Array<FollowingStructure & { structure_id?: string | null }>;
line: Line;
max_drift_m?: number;
interval_m?: number | null;
fill?: { previous?: Record<string, FollowingStructure> | null; only_missing?: boolean };
};
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;
if (follow.fill)
return fillStructureCoordinates(
follow.items,
xyOf(follow.line),
follow.fill.previous ?? null,
follow.fill.only_missing ?? false,
follow.interval_m ?? 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 };
},
};
}