- 예정노선 수정 켬에도 추천 선 불투명 그대로(Render) - 스냅 + 스냅 간격 = 고르기 메뉴 하나(측점 No. · 10 m · 끔) · 도구줄 표 snap-step 줄 걷음 - 추천노선 = 여럿 고르기(공용 부품 multi · 줄 색 점 PickMenuItem.color · 끔 줄 없음) · 선 색 --draw-map-rec-1~4 · 예정노선 가이드 선은 켬끔 한 줄 - 켠 동안 등고선 띠 = LAS 는 자르지 않음 · 도엽은 계획선 + 예정노선으로 넓힘(캔버스 · GL · 도엽 다시 받기) - 시험 624_2 · 634_2 · 626_1 · 636_2 · 390_4 · b05_routeedit_initial 을 새 꼴로 고침 · 새 시험 756_1 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
100 lines
4.9 KiB
TypeScript
100 lines
4.9 KiB
TypeScript
/* =============================================================================
|
|
* B05_Profile_UI_RouteEdit_SnapStep.ts
|
|
* 노선 편집 스냅 고르기 하나(390-2 · 요구 242-11 · 589-4) — 측점 No. · 10 m · 끔(끔 = 스냅 꺼짐).
|
|
*
|
|
* 간격 = 10 m · 측점 No.(편집 창 측점 간격 · 기본 · 280-4) — 곡선 MC 를 그 간격 배수에 맞춤.
|
|
* 켬이면 저장 노선에도 같이(`station_snap_step` · 390-5 · 서버 측점 셈이 MC 측점 값 자릿수로 씀 · 옛 노선 = 측점 No.).
|
|
* 저장 노선이 스냅 켬이면 열 때 그 간격으로 고르기를 맞춤. 추천 · 서버 초기 노선은 측점 No. 그대로.
|
|
* 고르기 = 도구줄 고르기 메뉴 하나(634-3 · `chrome.snap`) · 처음 = 끔.
|
|
* 상태줄 글은 고른 간격 따라(390-4) — 측점 No. = 「일반측점에」 · 10 m = 「10 m 배수에」.
|
|
* 평면 눈금 = 일반측점(스냅이 옮기지 않음 · 280-4) + 곡선 측점(MC 에 측점 없을 때 · 252-2 · `ticks`).
|
|
* ========================================================================== */
|
|
|
|
import type { RouteDraft } from "../A00_Common/design/logic/design_pipeline_types";
|
|
import type { RouteEditChrome } from "./B05_Profile_UI_RouteEdit_Chrome";
|
|
import type { EditedCurve, Vertex } from "./logic/B05_Profile_UI_RouteEdit_Curve";
|
|
import { curveSpans, curveStations, stationsAlong } from "./logic/B05_Profile_UI_RouteEdit_Frame";
|
|
|
|
/** 고르기 값 — 옛 "0.1" · "1"(pref · 저장)은 측점 No. 로 읽음(280-4). */
|
|
const STEPS = ["10", "station"];
|
|
|
|
/** 저장 · 초안에 실리는 스냅 두 칸. */
|
|
export type SnapSetting = Pick<RouteDraft, "stationSnap" | "stationSnapStep">;
|
|
|
|
type SavedSnap = { station_snap?: boolean; station_snap_step?: number | null };
|
|
|
|
/** 스냅 뒤 상태줄 글 — `step` = 고르기 값("10" · "station"). */
|
|
export function snapFitText(step: string): string {
|
|
const where = step === "station" ? "일반측점" : `${step} m 배수`;
|
|
return `곡선 가운데(MC)를 ${where}에 맞췄습니다.`;
|
|
}
|
|
|
|
export type SnapStep = {
|
|
/** 지금 스냅 간격(m) — 측점 No. 면 측점 간격. */
|
|
(): number;
|
|
/** 스냅 켬인가(고르기가 끔이 아님). */
|
|
on: () => boolean;
|
|
/** 스냅 뒤 상태줄 글. */
|
|
text: () => string;
|
|
/** 저장 · 초안 두 칸 — 끔이면 간격 null. */
|
|
draft: () => SnapSetting;
|
|
/** 저장 노선을 읽음 — 켬이면 고르기를 그 간격으로 · 돌려줌 = 켬끔. */
|
|
load: (plan: SavedSnap) => boolean;
|
|
/** 읽은 저장 노선과 켬끔 · 간격이 다른가([확인] 보낼지). */
|
|
changed: () => boolean;
|
|
/** 편집 창 일반측점 — 끔이면 null · 켬이면 측점 간격 그대로(옮기지 않음 · 280-4). */
|
|
stations: (line: ReadonlyArray<Vertex>, curves?: ReadonlyArray<EditedCurve>) => number[] | null;
|
|
/** 평면 눈금 — `stations` + 곡선 측점(252-2) · 곡선 측점이 없으면 `stations` 그대로. */
|
|
ticks: (
|
|
line: ReadonlyArray<Vertex>,
|
|
curves: ReadonlyArray<EditedCurve>,
|
|
) => { stations: number[] | null; curveStations: number[] };
|
|
};
|
|
|
|
/** 고르기 배선 — 고름(켬 · 간격 · 끔) 때 `onChange()`. */
|
|
export function bindStationSnap(
|
|
chrome: Pick<RouteEditChrome, "snap">,
|
|
stationIntervalM: number,
|
|
onChange: () => void,
|
|
): SnapStep {
|
|
// 고르기 메뉴 하나(634-3) — 값 = "10" · "station" · 끔 null
|
|
const menu = chrome.snap;
|
|
const value = (): string => menu.value() ?? "station";
|
|
menu.onPick(() => onChange());
|
|
const on = () => menu.value() !== null;
|
|
const step = (): number | null => (value() === "station" ? null : Number(value()));
|
|
const draft = (): SnapSetting => ({ stationSnap: on(), stationSnapStep: on() ? step() : null });
|
|
let loaded: SnapSetting = { stationSnap: false, stationSnapStep: null };
|
|
const stations = (line: ReadonlyArray<Vertex>) =>
|
|
on() ? stationsAlong(line, stationIntervalM, false) : null;
|
|
const stepM = () => step() ?? stationIntervalM;
|
|
return Object.assign(stepM, {
|
|
on,
|
|
text: () => snapFitText(value()),
|
|
draft,
|
|
load: (plan: SavedSnap) => {
|
|
const snapOn = plan.station_snap === true;
|
|
const kept = String(plan.station_snap_step ?? "station");
|
|
menu.set(snapOn ? (STEPS.includes(kept) ? kept : "station") : null);
|
|
loaded = { stationSnap: snapOn, stationSnapStep: snapOn ? step() : null };
|
|
return snapOn;
|
|
},
|
|
changed: () => {
|
|
const now = draft();
|
|
return (
|
|
now.stationSnap !== loaded.stationSnap || now.stationSnapStep !== loaded.stationSnapStep
|
|
);
|
|
},
|
|
stations,
|
|
ticks: (line: ReadonlyArray<Vertex>, curves: ReadonlyArray<EditedCurve>) => {
|
|
const base = stationsAlong(line, stationIntervalM, false);
|
|
// 노선 길이 = 무한 — 호(BC~EC)는 늘 노선 안
|
|
const curve = curveStations(base, curveSpans(line, curves), Infinity, on() ? step() : null);
|
|
return {
|
|
stations: curve.length ? [...base, ...curve].sort((a, b) => a - b) : stations(line),
|
|
curveStations: curve,
|
|
};
|
|
},
|
|
});
|
|
}
|