- 편집 모달 「분석 지형: 라이다 · 수치지형도」 고르기 · 라이다와 수치지형도 서피스가 둘 다 있을 때만 보임 · 기본 라이다 · 값은 화면 상태 pref(routeedit-terrain) - 고르면 등고선 · 구간 기울기 · 거리 재기 지반고 · 횡단 미리보기 · 종단 띠를 고른 지형으로 다시 그림 · 노선 추천도 고른 지형으로 요청 - 서버 통로(elevations · cross-preview · profile-preview · initial)가 terrain(las · sheet) 을 받아 sampler 를 고름 · GET route/terrain-sources 새 길 - 확정 params · [확인] 재계산 · 종 · 횡단 · 3D 정본은 안 바뀜 - 지표면 허용 목록에 sheet_* 여섯 넣음 — 54-22 뒤 LAS 없는 프로젝트 sheet_laplace 가 막혀 있던 길도 풀림 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UoSr2sqvYtBf1dtQdus88s
152 lines
8.6 KiB
TypeScript
152 lines
8.6 KiB
TypeScript
import { createButton } from "@ui/ui_template_elements";
|
|
import "@ui/ui_template_modal.css";
|
|
|
|
/* =============================================================================
|
|
* B05_Profile_UI_RouteEdit_Chrome.ts
|
|
* 계획노선 편집 모달의 **뼈대** — 창·단추·오버레이 판을 만들고 자주 쓰는 요소를 집어 준다.
|
|
*
|
|
* `B05_Profile_UI_RouteEdit.ts` 가 700줄을 넘겨 떼어낸 조각이다(2026-09-12). 생김새만 있고
|
|
* 동작은 없다 — 배선은 본체와 각 조각(`_Apply`·`_Rotate`·`_History`…)이 한다.
|
|
*
|
|
* **배치**(2026-09-12 사용자 지시 ⑩~⑬·⑱) — 아래 정보행을 없애고 지도 위 오버레이로 옮겼다.
|
|
* 단추는 제목행 오른쪽, 조작 설명은 지도 왼쪽 위 2열, 상태·범례는 왼쪽 아래, 잰 값은 오른쪽
|
|
* 아래. 메인 창은 왼쪽으로 밀고 오른쪽 세로 칸에 횡단 두 판이 앉는다.
|
|
*
|
|
* 겉틀 — 배경 · 제목줄은 공용 모달 조각(`ui-modal__backdrop` · `ui-modal__top`). `openModal` 은
|
|
* 안 씀 — 바깥 누름 · Esc 로 닫혀 고치던 노선을 날리고, 제목줄에 단추 묶음 · 오른쪽 횡단 칸이 못 앉음.
|
|
* ========================================================================== */
|
|
|
|
/** 회전 단추 아이콘 — **반만 도는 화살표**(2026-09-12 사용자 지시 ㉙). 한 바퀴를 다 그린
|
|
* 기호(`↺`·`↻`)는 「한 바퀴 돈다」로 읽혀 한 칸씩 도는 동작과 안 맞았다. */
|
|
export const HALF_TURN_ICON = {
|
|
ccw: `<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" fill="none"
|
|
stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M13 8a5 5 0 0 0-10 0" /><path d="M3 8 1.2 5.6" /><path d="M3 8 5.4 6.6" /></svg>`,
|
|
cw: `<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" fill="none"
|
|
stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M3 8a5 5 0 0 1 10 0" /><path d="M13 8 14.8 5.6" /><path d="M13 8 10.6 6.6" /></svg>`,
|
|
};
|
|
|
|
export interface RouteEditChrome {
|
|
overlay: HTMLElement;
|
|
canvas: HTMLCanvasElement;
|
|
status: HTMLElement;
|
|
busy: HTMLElement;
|
|
measureBox: HTMLElement;
|
|
measureText: HTMLElement;
|
|
measureButton: HTMLButtonElement;
|
|
minorContourButton: HTMLButtonElement;
|
|
/** 분석 지형 고르기(PLAN 133-1) — 라이다 있는 프로젝트만 보임(감싼 label 의 hidden). */
|
|
terrainSelect: HTMLSelectElement;
|
|
}
|
|
|
|
/** 모달을 만들어 `document.body` 에 붙이고, 자주 쓰는 요소를 집어 돌려준다. */
|
|
export function createRouteEditChrome(): RouteEditChrome {
|
|
const overlay = document.createElement("div");
|
|
overlay.className = "ui-modal__backdrop b05-routeedit";
|
|
overlay.innerHTML = `
|
|
<div class="b05-routeedit__box" role="dialog" aria-label="계획노선 편집">
|
|
<div class="ui-modal__top b05-routeedit__head">
|
|
<h3>계획노선 편집</h3>
|
|
<span class="b05-routeedit__rec-now" data-rec-now></span>
|
|
<span class="b05-routeedit__actions">
|
|
<button type="button" class="ui-btn ui-btn--ghost" data-act="recommend" disabled
|
|
title="예상노선 추적 · 영선 · 토공 최소 · 기울기 최소 · 비중 계산 중 하나로 노선을 추천받아 미리 봅니다">노선 추천</button>
|
|
<i class="b05-routeedit__divider" aria-hidden="true"></i>
|
|
<label class="b05-routeedit__terrain" hidden
|
|
title="편집 창 분석(등고선 · 지반고 · 기울기 · 횡단 미리보기 · 종단 띠 · 추천)에 쓸 지형 — 확정 지표면 · 종횡단은 안 바뀝니다">분석 지형
|
|
<select class="ui-select ui-select--sm" data-act="terrain">
|
|
<option value="las">라이다</option>
|
|
<option value="sheet">수치지형도</option>
|
|
</select>
|
|
</label>
|
|
<button type="button" class="ui-btn ui-btn--ghost" data-act="contour-minor"
|
|
aria-pressed="false" disabled
|
|
title="1m 간격 등고선을 얇고 옅게 겹칩니다 (확대하면 보임)">1m 등고선</button>
|
|
<button type="button" class="ui-btn ui-btn--ghost" data-act="measure"
|
|
title="노선 위 두 점을 눌러 거리·기울기를 잽니다 (Shift+클릭도 같음)">거리 재기</button>
|
|
<i class="b05-routeedit__divider" aria-hidden="true"></i>
|
|
<button type="button" class="ui-btn ui-btn--ghost" data-act="undo"
|
|
title="되돌리기 (Ctrl+Z)" disabled>↶ 되돌리기</button>
|
|
<button type="button" class="ui-btn ui-btn--ghost" data-act="redo"
|
|
title="다시하기 (Ctrl+Y)" disabled>↷ 다시하기</button>
|
|
<button type="button" class="ui-btn ui-btn--ghost" data-act="reset" disabled
|
|
title="전처리 때 만든 초기값 노선(예상노선 추적)으로 되돌립니다 — 다시 계산은 [확인]에서">초기화</button>
|
|
<button type="button" class="ui-btn ui-btn--ghost" data-act="cancel">취소</button>
|
|
<button type="button" class="ui-btn ui-btn--filled" data-act="apply"
|
|
title="이 노선으로 배수유역부터 다시 계산합니다 — 결과가 새 초기값이 되고 종횡단 · 구조물 · 관 옵션 편집은 새 노선 기본값으로 바뀝니다">확인</button>
|
|
</span>
|
|
<span data-slot="close"></span>
|
|
</div>
|
|
<div class="b05-routeedit__canvas-wrap">
|
|
<canvas class="b05-routeedit__canvas"></canvas>
|
|
<div class="b05-routeedit__hint">
|
|
<span>노드 끌기 = 옮기기</span><span>노드 클릭 = R 라벨</span>
|
|
<span>선 두 번 클릭 = 노드 추가</span><span>노드 오른쪽 클릭 = 삭제</span>
|
|
<span>측점 눈금 클릭 = 횡단 미리보기</span><span>Shift+클릭 = 거리·기울기</span>
|
|
<span>가운데(휠) 버튼 끌기 = 지도 이동</span><span>휠 = 확대</span>
|
|
</div>
|
|
<div class="b05-routeedit__spin">
|
|
<button type="button" class="ui-btn ui-btn--glass" data-act="rotate-ccw"
|
|
title="반시계로 돌리기" aria-label="반시계로 돌리기">${HALF_TURN_ICON.ccw}</button>
|
|
<button type="button" class="ui-btn ui-btn--glass" data-act="rotate-cw"
|
|
title="시계로 돌리기" aria-label="시계로 돌리기">${HALF_TURN_ICON.cw}</button>
|
|
</div>
|
|
<div class="b05-routeedit__measure" hidden>
|
|
<span class="b05-routeedit__measure-text"></span>
|
|
<span data-slot="measure-close"></span>
|
|
</div>
|
|
<div class="b05-routeedit__info">
|
|
<span class="b05-routeedit__status">노선을 읽는 중…</span>
|
|
<span class="b05-routeedit__legend">
|
|
<i class="is-expected"></i> 예상노선(원본)
|
|
<i class="is-planned"></i> 계획노선
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="b05-routeedit__strip" data-strip>
|
|
<div class="b05-routeedit__strip-head">
|
|
<span data-strip-note>종단을 읽는 중…</span>
|
|
</div>
|
|
<div class="b05-routeedit__strip-graph" data-strip-graph></div>
|
|
</div>
|
|
<div class="b05-routeedit__busy" hidden><span></span></div>
|
|
</div>
|
|
<div class="b05-routeedit__side"></div>`;
|
|
document.body.append(overlay);
|
|
|
|
const closeButton = createButton({ label: "✕", variant: "ghost" });
|
|
closeButton.classList.add("b05-routeedit__close");
|
|
closeButton.setAttribute("aria-label", "닫기");
|
|
overlay.querySelector('[data-slot="close"]')!.replaceWith(closeButton);
|
|
|
|
const measureCloseButton = createButton({ label: "✕", variant: "ghost" });
|
|
measureCloseButton.classList.add("b05-routeedit__measure-close");
|
|
measureCloseButton.setAttribute("aria-label", "닫기");
|
|
measureCloseButton.title = "닫기";
|
|
overlay.querySelector('[data-slot="measure-close"]')!.replaceWith(measureCloseButton);
|
|
|
|
const canvas = overlay.querySelector<HTMLCanvasElement>(".b05-routeedit__canvas")!;
|
|
const status = overlay.querySelector<HTMLElement>(".b05-routeedit__status")!;
|
|
const measureBox = overlay.querySelector<HTMLElement>(".b05-routeedit__measure")!;
|
|
const measureText = overlay.querySelector<HTMLElement>(".b05-routeedit__measure-text")!;
|
|
const measureButton = overlay.querySelector<HTMLButtonElement>('[data-act="measure"]')!;
|
|
const busy = overlay.querySelector<HTMLElement>(".b05-routeedit__busy")!;
|
|
const minorContourButton = overlay.querySelector<HTMLButtonElement>(
|
|
'[data-act="contour-minor"]',
|
|
)!;
|
|
const terrainSelect = overlay.querySelector<HTMLSelectElement>('[data-act="terrain"]')!;
|
|
|
|
return {
|
|
overlay,
|
|
canvas,
|
|
status,
|
|
busy,
|
|
measureBox,
|
|
measureText,
|
|
measureButton,
|
|
minorContourButton,
|
|
terrainSelect,
|
|
};
|
|
}
|