diff --git a/A00_Common/b_page_state.ts b/A00_Common/b_page_state.ts index fd30b73b..9c05c761 100644 --- a/A00_Common/b_page_state.ts +++ b/A00_Common/b_page_state.ts @@ -109,6 +109,10 @@ export const STATE_REGISTRY = { culvertmove: { bucket: "draft", scope: "route", legacy: (p, r) => `b06:culvertmove:${p}:${r}` }, /** 암 경계선 오프셋(측점별). */ rockb: { bucket: "draft", scope: "route", legacy: (p, r) => `b06:rockb:${p}:${r}` }, + /** 측점별 암 절토 경사비(1:n 의 n) — 카드에서 넣은 사용자 값(2026-09-07). + * 암 경계선(`rockb`)과 같은 자리·같은 꼴이다. 재계산에 **계산 전에** 실어 보내야 + * 설계선이 새 경사로 그려진다(값만 베껴 붙이면 그림과 숫자가 어긋난다). */ + cutslope: { bucket: "draft", scope: "route" }, /** 소단 제원(측점키 → {width_m, interval_m, slope_deg}) — 계획서 3-9. * 사용자가 구간에 놓은 값이라 재계산에 함께 실어 보내야 한다. 안 실으면 계획선을 * 고치는 순간 계단이 사라진다(암 경계선이 옛 키를 보던 것과 같은 자리). */ diff --git a/B05_Profile/B05_Profile_Structure_Types.json b/B05_Profile/B05_Profile_Structure_Types.json index f6862a92..3abed2df 100644 --- a/B05_Profile/B05_Profile_Structure_Types.json +++ b/B05_Profile/B05_Profile_Structure_Types.json @@ -505,10 +505,65 @@ "placement": "interval", "style": { "color": "#2ec5dc", - "abbr": "소단" + "abbr": "소단구" }, "drawing_views": ["cross_section", "quantity"], - "options": [] + "options": [ + { + "key": "length_m", + "label": "길이", + "input": "number", + "unit": "m", + "default": 10, + "required": false, + "phase": "b05" + }, + { + "key": "before_m", + "label": "기준측점 전", + "input": "number", + "unit": "m", + "default": 5, + "required": false, + "phase": "b05" + }, + { + "key": "after_m", + "label": "기준측점 후", + "input": "number", + "unit": "m", + "default": 5, + "required": false, + "phase": "b05" + }, + { + "key": "width_m", + "label": "폭", + "input": "number", + "unit": "m", + "default": 0.5, + "required": false, + "phase": "b05" + }, + { + "key": "interval_m", + "label": "간격(사면길이)", + "input": "number", + "unit": "m", + "default": 3, + "required": false, + "phase": "b05" + }, + { + "key": "slope_deg", + "label": "사면 쪽 기울기", + "input": "number", + "unit": "°", + "default": 0, + "required": false, + "phase": "b05" + } + ] }, { "type_id": "chute", @@ -910,6 +965,73 @@ } ] }, + { + "type_id": "berm", + "group": "C", + "name": "소단", + "placement": "interval", + "style": { + "color": "#7f9a63", + "abbr": "소단" + }, + "drawing_views": ["profile", "cross_section", "quantity"], + "options": [ + { + "key": "length_m", + "label": "길이", + "input": "number", + "unit": "m", + "default": 10, + "required": false, + "phase": "b05" + }, + { + "key": "before_m", + "label": "기준측점 전", + "input": "number", + "unit": "m", + "default": 5, + "required": false, + "phase": "b05" + }, + { + "key": "after_m", + "label": "기준측점 후", + "input": "number", + "unit": "m", + "default": 5, + "required": false, + "phase": "b05" + }, + { + "key": "width_m", + "label": "폭", + "input": "number", + "unit": "m", + "default": 0.5, + "required": false, + "phase": "b05" + }, + { + "key": "interval_m", + "label": "간격(사면길이)", + "input": "number", + "unit": "m", + "default": 3, + "required": false, + "phase": "b05" + }, + { + "key": "slope_deg", + "label": "안쪽 기울기", + "input": "number", + "unit": "°", + "default": 0, + "required": false, + "phase": "b05" + } + ] + }, { "type_id": "erosion_check", "group": "D", diff --git a/B05_Profile/B05_Profile_UI_RouteEdit.ts b/B05_Profile/B05_Profile_UI_RouteEdit.ts index fdf9159f..09a1f611 100644 --- a/B05_Profile/B05_Profile_UI_RouteEdit.ts +++ b/B05_Profile/B05_Profile_UI_RouteEdit.ts @@ -29,15 +29,39 @@ import { showToast } from "@ui/ui_template_elements"; import { fetchDrainageLayers } from "./B05_Profile_UI_Drainage_Parts"; import { fetchRoutePlan, replanRoute, resetRoutePlan } from "./B05_Profile_Api_Replan"; import type { RoutePlanCurve } from "./B05_Profile_Api_Replan"; -import { dragHandleTo as curveDragTo } from "./B05_Profile_UI_RouteEdit_Curve"; +import { buildEditedPolyline, dragHandleTo as curveDragTo } from "./B05_Profile_UI_RouteEdit_Curve"; +import { + bindRouteEditNavigation, + contourBandRect, + handleAtScreen, + nodeAtScreen, + segmentAtScreen, +} from "./B05_Profile_UI_RouteEdit_Input"; +import { + centerDirectionOf, + createCurveLabel, + deflectionRad, +} from "./B05_Profile_UI_RouteEdit_Label"; +import { + bindHistoryControls, + createRouteEditHistory, + type RouteEditHistory, + type RouteEditSnapshot, +} from "./B05_Profile_UI_RouteEdit_History"; import "./B05_Profile_UI_Style_RouteEdit.css"; /** 노드를 잡았다고 볼 거리(px). 손가락·마우스 모두 무리 없는 크기. */ const NODE_HIT_PX = 9; /** 노드 반지름(px). */ const NODE_R = 4; -/** 끌기로 볼 최소 이동(px) — 이보다 작으면 클릭으로 본다. */ -const DRAG_THRESHOLD_PX = 3; +/** 선을 두 번 눌러 노드를 끼울 때, 선에서 이만큼(px) 안쪽이면 그 선으로 본다. */ +const SEGMENT_HIT_PX = 12; +/** 등고선을 보일 **노선 둘레 띠**(m) — 사용자 지시 ⑥(2026-09-07). + * + * 노선에서 이만큼 밖의 등고선은 안 그린다. **창 크기와 무관한 고정 띠**라 창을 늘리거나 + * 줄여도 띠가 흔들리지 않는다(사용자가 「다이나믹 창이라 조심」이라 한 자리). 화면 밖을 + * 걸러내는 일은 `drawPreparedLayer` 가 이미 하므로 여기서는 띠만 덧씌운다. */ +const CONTOUR_BAND_M = 300; /** 곡선 시작·끝점 손잡이 크기(px) — 노드 동그라미와 구별되게 **속 빈 네모**로 그린다. * 처음엔 3.5px 였는데 선과 색이 같아 눈에도 안 띄고 집기도 어려웠다(2026-09-07 실화면). */ const CURVE_HANDLE_PX = 5; @@ -56,28 +80,24 @@ export async function openRouteEditModal(