diff --git a/docs/raw/요구_1025/_조사_530-A_지도일원화.md b/docs/raw/요구_1025/_조사_530-A_지도일원화.md new file mode 100644 index 000000000..ad7cc8a60 --- /dev/null +++ b/docs/raw/요구_1025/_조사_530-A_지도일원화.md @@ -0,0 +1,172 @@ +# 조사 530-A — 예정노선(D03) 지도 · B05 평면도 지도 일원화 + +근거 = 요구 530(`docs/raw/요구_1025/사용자요구_1025.md:1089-1112`) · 코드 읽기만(화면 실측 없음 — 코드로 충분). + +## 0. 한눈에 + +- 이미 같이 쓰는 것 = GL 지도 틀 `ui_template_gl_map.createGlMap` · 도구줄 틀 `ui_template_map_tools` · 화면 틀 `ViewState`(B04 MapRender) · 휠 · 가운데 끌기(`B05_RouteEdit_Input.bindRouteEditNavigation:58`) · 돌림(`B05_RouteEdit_Rotate.createMapRotation:52`). D03 이 B05 부품을 import 함(`D03_UI_Map.ts:32-34`). +- 따로 짠 것 = **카메라 맞춤 방식** · **겹 목록**(D03 스물 · B05 셋) · **도구줄 차례 · 단추** · GL 켬끔 취향 열쇠 · 지형 원천. +- 겹 자료는 모두 경위도(GeoJSON · 조각 · 네 귀퉁이 그림) → 어느 카메라 방식에서도 GL 이 그대로 그림. 증거 = B05 배수유역 칸이 TM 방식으로 위성 조각을 이미 그림(`B05_UI_Drainage_Gl.ts:69-90`). +- 결론 = 「공용 껍데기(도구줄 표 · 겹 목록 · 범례 · 지형 칩) + 페이지별 카메라 어댑터」 갈래 권함 · 바탕 코드 = D03 겹 쪽. + +## 1. 지금 구조 + +| 칸 | D03 예정노선 | B05 평면도(노선 편집) | 공용 | +|---|---|---|---| +| 지도 뼈대 | `D03_UI_Map.createPlanMap:181`(캔버스 두 장 · 겹 = `PlanMapLayer`) | `B05_UI_RouteEdit_Chrome.createRouteEditChrome:86` + `B05_UI_RouteEdit.ts:118`(캔버스 한 장) | — | +| GL 바탕 | `D03_UI_MapGl.createGlBase:352` → `createGlMap` | `B05_UI_RouteEdit_Gl.createRouteEditGl:50` → `B04_UI_MapGl.createTmGl:56` → `createGlMap` | `ui_template_gl_map.ts:90-220` | +| 카메라 맞춤 | 경위도 정규화(`createNormalizer`) · GL 카메라 = `UI_Map.glCamera:309-320` · TM 그림 = GL 투영에 맞춤(`logic/D03_Tm` `localTmFrame` · `UI_Map.metricFrame:323-340`) | TM 정규화(`createTmNormalizer`) · GL 이 캔버스를 따라감 = 닮음꼴 카메라 + 칸 CSS 행렬(`B04_UI_MapGl.follow:95-116` · `logic/B04_MapGl_Frame.glCameraOf`) | 둘 다 「카메라 주인 = 캔버스 view」 | +| 줌 한도 | 화면 폭 600 km(`UI_Map.ts:65 · 507-513`) | 0.5 배(기본) | `bindRouteEditNavigation` | +| 겹 | 스물(`D03_UI_LayerDefs.GROUPS:59-132`) · 받기 · 차례(`D03_UI_Layers.fetchLayer:424-`) · 범례 · 급경사 범위 · 위성 밝기 · 도엽 조각(`UI_SheetTiles`) · 옛 캔버스 대체(`UI_LayerPaint`) | 셋 = 도엽 하천 · 1 m 선 · 등고선(LAS 5 m 또는 도엽)(`RouteEdit_Gl.ts:73-85`) · 노선 둘레 300 m 띠로 GL 칸 통째 자름(`RouteEdit_Gl.ts:177-197`) | 겹 꼴 일부(`B04_UI_MapGl.lineSpecs · rasterSpec`) | +| 도구줄 | 두 줄 — 겹 줄(왼쪽 위 · `UI_Layers.ts:168-206`) + 평면 도구(오른쪽 · `UI_Map.ts:188-234`) | 한 줄(왼쪽 위 · `RouteEdit_Chrome.ts:130-171`) | `createMapTools` | +| GL 켬끔 취향 | `aislo:pref:d03.canvas`(`UI_Layers.ts:96`) | `aislo:pref:map.canvas`(B04 · 배수 같이 · `B04_UI_MapGl.ts:27`) | — | +| 위 그림 · 누름 | 긋기 · 고르기 · 지점 · 조각 · 속성 · 재기(`UI_Draw` · `UI_Edit` · `UI_Select` · `UI_Points` · `UI_Measure`) | 노드 끌기 · 곡선 · 측점 · 구조물 표 · 절/성토선 · 등고선 고름 · 자물쇠 · 횡단 미리보기(`RouteEdit_Pointer` · `_Render` · `_StructureMarks` · `_Footprint` · `_ContourLock` · `_Cross`) | — | + +## 2. 기능 대조 + +### 2-1 도구줄 단추 + +| 단추 | 하는 일 | D03 | B05 | 일원화 뒤 | +|---|---|---|---|---| +| [?] | 조작 안내 | 있음(17 줄 · `UI_Map.ts:206-226`) | 있음(9 줄 · `Chrome.ts:72-82`) | 둘 다 · 글은 페이지 몫 | +| 되돌리기 · 다시하기 | 걸음 스택 | 있음(`UI_Map.ts:200-201`) | 있음(`Chrome.ts:135-136`) | 둘 다 | +| 3D | 큰 창 | 있음(`D03_UI_3D`) | 있음(부른 쪽 · `design_view_profile_3d_modal.ts:77`) | 둘 다 · 동작 페이지 몫 | +| 돌리기 좌 · 우 | 단추 · Ctrl+휠 | 있음 | 있음 | 둘 다(이미 같은 코드) | +| 1 m 등고선 | LAS 1 m 선 | 없음 | 있음 · LAS 일 때만 열림(`RouteEdit.ts:660-664`) | 라이다 원천일 때만 보임 | +| 측점 | 눈금 · 번호 | 있음 | 있음 | 둘 다 | +| 기울기 | 구간 기울기 글 | 있음(구간 길이 · 기울기) | 있음 | 둘 다 | +| 절/성토선 | 도로 끝 · 비탈 끝 | 없음 | 있음 | B05 만 | +| 거리 재기 | 두 점 | 있음(곧은 · 노선 따라 · 브라우저 격자 높이 `UI_Measure`) | 있음(노선 위 · 서버 `/route/elevations` · `RouteEdit_Measure`) | 단추 같은 자리 · 동작 페이지 몫 | +| 측점 스냅 + 간격 | MC 맞춤 | 없음 | 있음(`Chrome.ts:160-165`) | B05 만 | +| 지형 이름 칩 | 설계 지형 표시 | 없음 | 있음 · 둘 다 있을 때만(`RouteEdit.ts:642-643`) | **지형 원천 고르기**로 바꿈(둘 다) | +| GPU 켬끔 | 옛 캔버스 | 있음(겹 줄 끝) | 있음(1 m 선 뒤 · `RouteEdit_Gl.ts:63-70`) | 둘 다 · 취향 열쇠 하나 | +| 겹 스물 | 아래 2-2 | 있음 | 없음 | 둘 다 · 페이지별 보임 표 | +| 추천 미리보기(새) | 4 갈래 선 고름(요구 530 2) | 없음 | 새로 | B05 만(530 추천 쪽 몫) | + +### 2-2 겹 + +| 겹 | D03 | B05 평면 | 원천 · 서버 길 | 임도(ROAD) 프로젝트에서 | +|---|---|---|---|---| +| 위성 | 있음 | 없음(배수유역 칸만) | `/plan/tile`(프로젝트 안 가림 · `Router.py:611`) | 바로 됨 | +| 음영기복 · 급경사 | 있음 | 없음 | `/plan/layers/raster` → `models_plan/dtm_sheet_*.npz`(`Layers.py:255-282`) | PLAN 전용(막힘) | +| 등고선 | 615 전국 조각(`contourTileSource` · 그림만) | LAS 5 m 또는 도엽 · **집기 자료**(고름 · 자물쇠 · 글 = 캔버스 · `RouteEdit_Contour.ts:191-212`) | `/plan/contour`(프로젝트 안 가림) | 조각 = 됨 · B05 집기는 지금 자료 그대로 | +| 세류 · 물 면 · 도로 · 임도 짐작 · 건물 · 지명 | 있음(도엽 조각 606) | 하천만 | `/plan/sheet-tiles`(프로젝트 안 가림 · `Router.py:350 · 363`) | 됨 | +| 올린 임도망도 | 있음 | 없음 | `/plan/layers/forest-roads`(D 자료) | PLAN 전용 | +| 지적 · 보호구역 · 산림입지 · 산사태 둘 · 단층 · 지질구조선 · 띠 | 있음 | 없음 | `/plan/layers/*` → `_layer_root:285` → `Store._project:76`(「예정노선 프로젝트가 아닙니다」) | PLAN 전용 | +| 0차곡 | 있음 | 없음 | `/plan/layers/zero-order` → `dtm_sheet` + 창고 누적(`ZeroOrder.py:262-300`) | PLAN 전용 | +| 622 새 겹 다섯(진행 중) | 붙는 중 | 없음 | `/plan/vt` · `/plan/wmt`(공용 창고 · 프로젝트 안 가림 꼴) | 됨(예정) | + +### 2-3 지형 원천 + +| 칸 | D03 | B05 | +|---|---|---| +| 지금 원천 | 수치지형도 하나 — 공용 창고 도엽을 이어 붙인 `models_plan/dtm_sheet_<방법>.npz`(`Terrain.py:1-20`) | 라이다 확정 지표면 기본 · 수치지형도 서피스도 WF1 때 같이 지음(`B04_Engine.py:362-376`) | +| 바꾸기 로직 | 없음 | **있음** — `common_util_surface_confirmation.py:82-117`(`design_terrain` · `analysis_terrain_params` · `analysis_terrain_sources`) · `B04_Service.switch_design_terrain:63-87`(확정 모델 · stage 1 params · 라이다 값 적어 둠) · `Router_Terrain.read_terrain_sources:118-138` · `choosable_terrains:141-155` · 바꾸는 때 = 추천 [적용](`Router_Replan.py:252-266 · 358` · `RouteEdit_Apply.ts:202`) | +| 브라우저 높이 | `Api.fetchPlanSurface:172-181`(`models_plan` 모델만 고름) → `heightAt`(긋기 · 재기 · 3D) | `Api_TerrainGrid.designTerrainGridNow:75` | +| 라이다 길 | 없음 — D = `project_kind PLAN` · LAS 입력 없음 · D04 연결은 D → B 한 방향(「지형은 업체가 올림」 `D04_Link.py:1-12`) · LAS 올리기 = 임도 B03 만(`B03_Router.py:141-173`) | 있음 | + +## 3. 일원화 갈래 + +| 갈래 | 뜻 | 좋음 | 나쁨 | 판정 | +|---|---|---|---|---| +| A 공용 껍데기 + 카메라 어댑터 둘 | 도구줄 표 · 겹 목록 · 받기 · 범례 · 지형 칩 = 공용 · 카메라 = D03 경위도 방식 / B05 TM 방식 그대로 | B05 캔버스 그림 · 집기 · 노선 자료 손 안 댐 · 겹은 경위도라 양쪽 GL 에 그대로 | 카메라 두 벌 남음(같은 점 몇 px 차 가능) | **권함** | +| B D03 지도로 B05 교체 | `createPlanMap` 하나 | 코드 한 벌 | B05 그림이 TM 정규화(`createTmNormalizer`) 위에 섬 → `_Render` 640 · `_StructureMarks` · `_Label` · `_Pointer` 집기 모두 다시 맞춤 · B06 연동 흔들림 | 안 권함 | +| C B05 방식으로 D03 교체 | `createTmGl` 하나 | B04 · 배수와 같은 길 | D03 600 km 줌아웃 · TM 띠 넘음에서 1차 맞춤 오차 커짐 | 안 권함 | + +### 3-1 바탕 코드 · 자리 + +- 겹 쪽 바탕 = D03(`UI_LayerDefs` · `UI_MapGl.layerSpecs:127-324` · `UI_Layers` · `UI_LayerLegend` · `UI_SlopeBands` · `UI_SatLight` · `UI_SheetTiles`) — B05 는 셋뿐. +- 자리 = 공용 폴더 새로(가칭 `A00_Common/map/`) — fetch 가 섞여 `ui_template` 엔 못 둠 · B05 가 D03 파일을 직접 부르면 페이지끼리 서로 부름. +- 페이지 설정 꼴 = 보일 단추 목록 · 보일 겹 목록 · 겹 처음 켬 · 지형 원천 기본값(D03 수치지형도 · B05 라이다) · 취향 열쇠. +- 도구줄 단추 = `ui_template_map_tools.MAP_TOOLS:22-34` 에 새 이름(지형 · 추천 미리보기 · GPU)만 더함. + +### 3-2 B05 를 깨지 않는 경계 + +| 공용 부품이 만짐 | 안 만짐(B05 그대로) | +|---|---| +| GL 바탕 겹(꼴 · 자료 · 켬끔) · 도구줄 단추 꼴 · 보임 · 겹 범례 · 지형 칩 | 캔버스 위 그림(`_Render` · `_StructureMarks` · `_Label` · `_Footprint` · `_Curve_Pick` · `_Hover`) · 누름(`_Pointer` · `_Input` · `_Keys` · `_ContourLock`) · 노선 자료(planned · curves · node_edits) · B05 · B06 공유 캐시 · [저장](`Route_Save` · `Router_Confirm`) · 관 지점 · 구조물 정본(`pipe_points.json` · `structures.json`) · B05 등고선 집기 자료 | + +- 지형 원천 바꾸기만 B05 정본에 닿음(설계 지형 = 뒤 단계 모두) — 4장. + +### 3-3 700 줄 한도(지금) + +| 파일 | 줄 | 일원화 때 | +|---|---|---| +| `B05_UI_RouteEdit.ts` | 694 | 손대지 않게(배선은 새 파일) | +| `B05_UI_RouteEdit_Recommend.ts` | 690 | 530 추천 쪽 몫 | +| `D03_UI_Layers.ts` | 688 | 공용으로 옮기며 쪼갬 | +| `D03_UI_Page.ts` | 667 | 지형 원천 배선은 새 파일 | +| `D03_PlanAnalysis_Router.py` | 651 | 임도 갈래 · 원천 인자 = 새 파일 | +| `B05_UI_RouteEdit_Render.ts` · `_Initial_Model.ts` | 640 · 640 | 안 건드림 | +| `D03_PlanAnalysis_Layers.py` | 616 | 원천 인자만 | +| `B05_Router_Replan.py` | 615 | 지형 바꿈 때만 | +| `D03_UI_Map.ts` | 568 | 도구줄 표로 바꿈 | + +### 3-4 단계(같은 파일 겹침 없게) + +| 단계 | 창 | 파일 | 앞 단계 | +|---|---|---|---| +| 1 서버 — 겹 라우터가 임도 프로젝트도 받음(범위 = B 메타 상자 · DEM = 설계 지형 npz) · 급경사 · 음영 · 0차곡에 원천 인자 · 지적 등 받은 파일은 B04 파일과 다른 이름 | 창 1 | D03 `Router` 새 조각 · `Layers.py` · `ZeroOrder.py` · `Store.py` · 새 시험 | 없음 | +| 2 화면 공용 — 겹 목록 · 겹 줄 · 범례 · 조각 · 도구줄 표 → 공용 폴더 · D03 은 부르기만(겉모습 · 수치 그대로) | 창 2 | D03 `UI_Layers` · `UI_LayerDefs` · `UI_MapGl` · `UI_LayerLegend` · `UI_LayerPaint` · `UI_SheetTiles` · `UI_SlopeBands` · `UI_SatLight` · `ui_template_map_tools` · 새 공용 폴더 | 1 과 나란히 | +| 3 B05 평면에 붙임 — 공용 겹 꼴을 `createTmGl` specs 에 더함 · 도구줄을 표로 · GPU 취향 하나 | 창 3 | B05 `RouteEdit_Chrome` · `RouteEdit_Gl` · `B04_UI_MapGl`(취향 열쇠) · 새 배선 파일 | 1 · 2 뒤 | +| 4 지형 원천 바꾸기 — D03 라이다(5장 결정 뒤) · B05 칩 → 설계 지형 바꿈 | D03 = 창 1 이어서 · B05 = 530 추천 미리보기 창과 한 창 | D03 `Api.ts` · 새 배선 · B05 `RouteEdit.ts` · `_Apply` · `Router_Replan` · `Router_Terrain` | 3 뒤 | + +- 겹침 주의 — 530 D03 긋기 일(Tab · 길이+기울기 기본)이 `D03_UI_Map.ts` 안내 글 · `UI_DrawPanel` · `UI_Draw` 를 만짐 → 2 단계는 `UI_Map.ts` 안 만지고 도구줄 표 바꿈은 3 단계 또는 긋기 일 뒤. + +## 4. 지형 원천 바꾸기 + +### 4-1 D03 에서 라이다 쓰는 조건 + +| 길 | 뜻 | 됨 · 안 됨 | +|---|---|---| +| a D 프로젝트에 LAS 올리기 | D 화면에 올리기 + B04 지면 필터 · DTM 짓기 그대로(D storage 도 `B04_PreProcess/` 배치 · `Terrain.py:3-4`) | 새 올리기 길 · 무거운 전처리 · 가장 곧음 | +| b 이어진 임도 프로젝트 LAS 빌림 | `projects.source_project_id = D` 인 B 의 확정 DTM | D04 연결 뒤에만 · D03 은 연결 전 단계라 대개 없음 | +| c 공용 라이다 창고 | 전국 등고선 창고처럼 | 없음 | + +### 4-2 바꿀 때 다시 셀 것 + +| 대상 | D03 | B05 | +|---|---|---| +| 급경사 · 음영 | 서버 `slope_layer` npz 자리만 바꿈 · 파생 열쇠에 npz 이름이 들어가 저장본이 저절로 갈림(`Layers.py:268`) | 새 겹(지금 없음) | +| 0차곡 | 수치지형도 = 창고 누적 빠른 길 · 라이다 = 통째 첫 셈 느림(616 근거 3.5~11.9 s) | 새 겹 | +| 등고선 그림 | 615 조각 = 수치지형도만 · 라이다 = LAS 등고선 따로 지어야 함 | 지금 로직(LAS ↔ 도엽 · `RouteEdit.ts:644-664`) | +| 브라우저 높이(긋기 길이+기울기 · 양각기 · 재기 · 3D) | `fetchPlanSurface` 고르는 모델만 바꿈(`Api.ts:174`) | `designTerrainGridNow` | +| 서버 [저장] | 높이 안 씀(`Network.py:9`) → 다시 셀 것 없음 | 설계 지형 = 종단 · 횡단 · 배수 · 토공 · 3D 모두(`switch_design_terrain` → `run_route_save_chain`) | +| 노선 추적(추천) | 없음 | 530 = 추천 다시 셈 없음 · 미리 셈 값만 | + +### 4-3 B05 로직 다시 씀 + +- 그대로 씀 = `analysis_terrain_*` · `switch_design_terrain` · `/route/terrain-sources`. +- 바꿀 것 = 바꾸는 때 — 지금 추천 [적용] 안(509-5) → 530 으로 추천이 미리보기만 되므로 **도구줄 지형 칩**으로 옮김 · 고르면 `/route/replan`(같은 노선 + `terrain`) 길. +- D03 에는 `analysis_terrain_*` 그대로 못 씀(stage 1 params · 확정 모델 = 임도 WF1 꼴) — D 는 원천 이름(`sheet` · `las`)만 같게 하고 npz 고르기는 D 쪽 작은 함수. + +## 5. 위험 · 사용자 결정 + +### 5-1 위험 + +| 위험 | 자리 | 막는 길 | +|---|---|---| +| 노선 띠 300 m 자르기가 GL 칸 통째(clip-path) → 위성 · 지적도 띠 안만 보임 | `RouteEdit_Gl.ts:177-197` | 등고선 · 하천 겹만 거름(MapLibre 겹 거름) · 칸 자르기 걷음 | +| 임도 프로젝트에서 지적도를 받으면 B04 `연속지적도_bounds.geojson` 을 덮어씀(열쇠 파일 없음 → 다시 받기) | `Layers.py:57 · 181-189` · `B04_GisVector.py:165` | 임도 프로젝트는 파생 저장 자리로 | +| 카메라 두 벌 — 같은 경위도 점 px 차 | `UI_Map.glCamera` 대 `glCameraOf` | 검증 창구로 대조(`screenOfLonLat` · `glCheck`) | +| GPU 취향 두 열쇠 → 하나로 하면 B04 하단 지도 · 배수 칸도 같이 바뀜 | `B04_UI_MapGl.ts:27` · `UI_Layers.ts:96` | 열쇠 하나로 · B04 · 배수 시험 같이 | +| B05 지형 바꿈 = 설계 지형 → B06 횡단 · 배수 · 토공 다시 셈 · 관 지점 · 구조물 따라감 | `Router_Replan.py:252-266` | 지금 [적용] 길 그대로 · 확인창 하나 | +| 파일 한도 — `RouteEdit.ts` 694 · `UI_Layers.ts` 688 · `Router.py` 651 | 3-3 표 | 새 파일로 | +| 530 다른 일(D03 긋기 · B05 추천 미리보기)과 같은 파일 | `D03_UI_Map.ts` · `RouteEdit.ts` · `_Recommend*` | 3-4 차례대로 | + +### 5-2 사용자 결정 거리 + +| 물음 | 갈래 | 권함 | +|---|---|---| +| ① 카메라 | A 두 벌 유지 · B 하나로 | **A** | +| ② B05 평면 처음 겹 | 지금 그대로(어두운 바탕 · 등고선 · 하천) · 위성 켬 | **지금 그대로** · 나머지 겹 끔 · 겹 줄에서 켬 | +| ③ 노선 띠 300 m 자르기 | 모든 겹 · 등고선 · 하천만 | **등고선 · 하천만** | +| ④ B05 지형 바꿈의 뜻 | 설계 지형(뒤 단계 모두) · 보기만 | **설계 지형**(지금 로직 · 확인창) | +| ⑤ D03 라이다 원천 | a D 에 LAS 올리기 · b 이어진 임도 빌림 · c 뒤로 | **a**(B04 엔진 그대로 · 연결 전에도 됨) | +| ⑥ 라이다 범위 밖(D 노선이 LAS 보다 넓을 때) | 수치지형도로 채움 · 빈칸(모름) | **빈칸** — 임의로 메우지 않는 지금 규칙(`Router_Terrain` 머리글) | +| ⑦ 새 겹의 GPU 끔(옛 캔버스) 대체 | 지음 · GL 만 | **GL 만** — 옛 캔버스는 지금 겹만 | +| ⑧ 공용 코드 자리 | 새 공용 폴더 · B04 에 둠 | **새 공용 폴더**(`A00_Common/map/` 가칭) | +| ⑨ B05 에 보일 겹 | 스물 모두 · 고른 것만 | **모두**(처음 끔) · 띠(타당성) · 올린 임도망도는 숨김 | +| ⑩ 거리 재기 동작 | 하나로 · 페이지 몫 | **페이지 몫**(단추 자리만 같게) | + +- 범위 밖으로 둔 것 = B05 배수유역도 칸 지도(`_Drainage_Gl` · 따로 칩 줄) · B04 하단 지도 · 추천 창 지도(`_Recommend_Map` · 530 추천 미리보기 일이 걷을 후보). diff --git a/docs/raw/요구_1025/_조사_530-B_노선긋기.md b/docs/raw/요구_1025/_조사_530-B_노선긋기.md new file mode 100644 index 000000000..9bdffc53c --- /dev/null +++ b/docs/raw/요구_1025/_조사_530-B_노선긋기.md @@ -0,0 +1,151 @@ +# 530-B 조사 — D03 노선 긋기(길이+기울기 기본 · Tab · 숨김 · 부채꼴 · Shift) + +원문 = `docs/raw/요구_1025/사용자요구_1025.md:1098-1102`. 코드 · DB · storage 손대지 않음 · 화면 실측 대신 storage DEM 읽기 실측(로그인 POST 피함 · 탭 열었다 닫음). + +## 0. 결론 + +- 네 방식 · 점선 원 · 후보 점 · 기울기 셈은 **있음**. 기본값 · 차례 · Tab · 숨김 = 작은 고침(한 창 반나절 꼴). +- 부채꼴 · +/− 색 · 정방향 채움 · Shift 사이 기울기 = **없음** — 새 순수 셈 하나(`compassArcs`) + 미리보기 그림 + Shift 상태 전달. +- 실측(검증 D 수치지형도 DEM · 반지름 20 m · 9 % · 점 2000): **후보 4 개 = 97.2 %** · 그중 거의 전부 「허용 호 2 개 · 각 호 끝 = + 하나 − 하나」 → 요구의 「방향 1 · 2 × 노드 2」 그대로 맞음. 나머지 2.8 % = 후보 2 · 6 · 8 개(골 · 능선 둘레). +- B05 복사(530-2) = 방식 칸 · 순수 셈 · 미리보기 그림은 떼어 씀 · `createPlanDraw`(여러 선 `PlanNetwork` · 갈래 · 연도 · 지점)는 그대로 못 옮김. + +## 1. 지금 코드 자리 + +| 항목 | 자리(파일:줄) | 지금 | +|---|---|---| +| 그리기 칸 몸 | `D03_PlanAnalysis_UI_DrawPanel.ts:154-190` | [긋기] · [연도 구역 마커](끌기) + 방식 칸 | +| 방식 칸 | `UI_DrawPanel.ts:47-145` | `createSegment` 2 × 2(`:56-70` · `columns: 2` `:63`) + 길이 · 기울기 칸(`:72-104`) · 기울기 아래 ≈ °(`:105-109`) · 노드 판(598-4 `UI_Props.ts:143-170`)도 같은 함수 | +| 방식 종류 · 차례 | `UI_DrawPanel.ts:23` · `:31-36` | `free · length · slope · both` — 차례 = 자유 · 길이 고정 / 기울기 고정 · 길이·기울기 고정 | +| 기본값 | `D03_PlanAnalysis_UI_Draw.ts:123` · 값 `UI_DrawPanel.ts:20-21` | 방식 `"free"` · 길이 20 m · 기울기 9 % (페이지 열 때마다 처음값 · 저장 안 함) | +| 옵션 칸 막힘 | `UI_DrawPanel.ts:119-123` `fieldsState` | 자유 = 둘 다 `disabled` · 길이 고정 = 기울기 막힘 · 기울기 고정 = 길이 막힘 | +| 미리보기 셈 | `UI_Draw.ts:190-231` `previewAt` | 붙기 먼저 → 방식별(`:211-219`) · `both` = 후보 전부(`:199`) 중 마우스에 가까운 것 | +| 점선 원 · 후보 점 | `D03_PlanAnalysis_UI_DrawPaint.ts:288-298` `paintPreview` | 반지름 원(점선 [3,4]) + 후보 점 모두 노랑(`--draw-map-sketch`) · 부호 색 없음 | +| 미리보기 글 | `UI_DrawPaint.ts:65-68` · `:307-318` | 길이 · 부호 붙은 % · ° (이미 +/− 글은 있음) | +| 양각기 후보 셈 | `logic/D03_PlanAnalysis_Draw.ts:110-159` `compassCandidates` | 원 360 표본 + 이분 · `|Δz| − rise` 근 → **부호 버림**(`:126`) · 동쪽부터 반시계 차례 | +| 가까운 후보 | `logic/D03_PlanAnalysis_Draw.ts:162-179` `compassPoint` | 마우스에 가장 가까운 후보 · 없으면 null(=찍기 막힘) | +| 기울기 셈 | `logic/D03_PlanAnalysis_Draw.ts:28-35` `groundSlopePct` | (z끝 − z시작) / 수평 길이 × 100 · + 오르막 | +| 지형 원천 | `UI_Page.ts:128` → `D03_PlanAnalysis_Api.ts:172-181` | `models_plan/` smooth 격자 = 수치지형도 도엽 DEM(`D03_PlanAnalysis_Terrain.py:13-15`) · 라이다 갈래 없음(530-A 몫) | +| 파이썬 짝 | `D03_PlanAnalysis_Draw.py` · 거울 시험 `test_562_1_plan_draw.py` | 서버는 [저장] 때 꼭짓점을 받은 그대로 · 양각기 셈 안 부름 | +| 노드 기록 | `logic/D03_PlanAnalysis_Span.ts:16-22` · 어긋남 `:25-33` | `{kind, length_m, slope_pct}` · 기울기는 크기만 비교(`|기울기|`) | +| 노드 다시 놓기 | `logic/D03_PlanAnalysis_Select.ts:254-287` `placeNode` | `both` = `compassPoint`(`:273`) | +| 놓인 노드 점 | `UI_DrawPaint.ts:164-179` | 흰 점 3 px + 어긋남 경고 고리 · 부호 색 없음 | +| 키 받기 | `UI_Page.ts:611-628` · `UI_Draw.ts:503-536` | window keydown · 입력 칸 초점이면 안 받음(`:613`) · Enter · Esc · Backspace | +| 키 등록부 | `A00_Common/key_registry.ts:139-142` | `plan.drawFinish` · `plan.drawBack` · Tab 줄 없음 · Shift 단독은 `chordOf` 가 빈 글(`:259`) | +| 마우스 곁 | `D03_PlanAnalysis_UI_Map.ts:104` · `:456-464` | `hover(px, py, map)` — **Shift 안 넘김**(누름만 `:445` 넘김) | +| 지도 안내 글 | `UI_Map.ts:206-225` | Tab · Shift(긋기 중) 줄 없음 · 「Shift+누름 = 선 더함」은 쉴 때 고르기 | + +## 2. 요구 대조 + +| 요구 | 지금 | 고칠 자리 | 크기 | +|---|---|---|---| +| 기본값 = 길이+기울기 고정 | 없음(자유) | `UI_Draw.ts:123` `"free"` → `"both"` | 한 줄 | +| 버튼 = 자유지정 오른쪽 | 없음(오른쪽 = 길이 고정) | `UI_DrawPanel.ts:31-36` 열쇠 차례 → `free · both · length · slope`(2 × 2 = [자유][길이·기울기] / [길이][기울기]) · 노드 판도 같이 바뀜 | 넉 줄 | +| 이름 「자유지정」 | 「자유」 | `UI_DrawPanel.ts:32` (선택) | 한 줄 | +| Tab = 자유 ↔ 길이+기울기 · 단독 고정이면 길이+기울기로 | 없음 | `UI_Draw.ts` `key()` 에 `kind === "both" ? "free" : "both"` + `kindFields.set` + 마지막 마우스 자리로 미리보기 다시 · 등록부 줄 `plan.drawKind ["Tab"]`(바꿀 수 있는 줄 → 시험 588 배선 판정 통과) · 안내 글 한 줄 | 20 줄 | +| 필요 없는 칸 = 숨김 | 일부(막힘) | `UI_DrawPanel.ts:119-123` — 방식 따라 칸 `root.hidden` · 권한 없음(`setDisabled`)만 막힘 유지 · 자유 = 칸 줄 통째 숨김 · `display:grid` 가 `[hidden]` 을 덮는지 확인 | 10 줄 | +| 점선 서클 + 노드 4 개 | 있음 | 그대로 | — | +| 방향 1 · 2(노드 2 개씩 짝) | 없음 | 새 순수 셈 `compassArcs` — 후보를 각도 차례로 · 이웃 두 후보 사이 가운데 각에서 `|Δz| < rise` 면 허용 호(=부채꼴) · 후보마다 부호 `sign(z − z0)` | 40 줄 | +| 진행 · 역방향 부채꼴 · 정방향 색 채움 | 없음 | 정방향 = 앞 구간 방향(앞앞 점 → 시작점)과 호 가운데 방향 cos 가 큰 호 · `paintPreview` 에 부채꼴(중심 → 호 → 닫음) · 정방향만 반투명 채움 | 50 줄 | +| 꼭지점 +/− 색(고르기 전 · 고른 뒤 같은 색) | 없음(모두 노랑) | 후보 점 색 = 부호 · 마우스가 고른 후보도 같은 색 · 놓인 노드도 들어온 구간 기울기 부호로 색(`UI_DrawPaint.ts:164-179` · 저장 없이 셈) · 새 지도 색 두 개 `--draw-map-slope-up/down` | 30 줄 + 시험 551-2 | +| Shift 누른 채 = 부채꼴 사이 기울기 지점(길이 유지) | 없음 | Shift 상태 = `hover` 에 shift 인자(`UI_Map.ts:104 · :461`) + keydown/keyup Shift · 창 blur 때 풂 → `previewAt` 에 「원 위 마우스 방위 · 허용 호 안으로 묶음」 · 기록 = `length`(아래 3 장) | 40 줄 | +| 완만한 땅(후보 0 · 원 전체 허용) | 막힘(`compassPoint` null → 찍기 막힘) | 원 전체가 허용이면 길이 고정처럼 어느 방향이나 | 5 줄 | + +파일 크기 — `UI_Draw.ts` 560 → 약 610 · `UI_DrawPaint.ts` 340 → 약 400 · 새 셈 파일 약 80 · 700 줄 안. + +## 3. 부채꼴 · +/− 규칙 + +### 3-1 지금 수식 + +- 후보 = 반지름 L 원 위 `|z(θ) − z0| = |s|·L` 인 방위(`logic/D03_PlanAnalysis_Draw.ts:118-127`) — +(오르막) · −(내리막) 섞여 나옴 · 부호는 버림. +- 고르기 = 마우스에 가장 가까운 후보(`:162-179`) · 방향 · 정방향 개념 없음. + +### 3-2 요구대로 셈(평면 경사면 기준 · 실측과 맞음) + +| 말 | 정의 | +|---|---| +| 최대 경사 G · 오르막 방위 θu | 시작점 둘레 땅 | +| 노드 4 개 | +쪽 θu ± α · −쪽 θu + π ± α (α = arccos(s / G)) | +| 방향 1 · 2 | 등고선 방향 θu ± 90° — 각 방향 = (+ 하나, − 하나) 짝 | +| 부채꼴 | 짝 두 노드 사이 호 = `|기울기| ≤ s` 인 방위 모두(가운데 = 0 %) | +| 정방향 | 앞 구간 방향과 가까운 쪽 호 · 반대 = 역방향 | +| 꼭지점 부호 | `sign(z(노드) − z0)` — 진행 방향 기준 + 오르막 | + +- 실측 — 이 땅 경사 중앙 65 % → 부채꼴 폭 ≈ 2·arcsin(9/65) ≈ 16° · 20 m 원에서 호 길이 약 5.6 m(가파를수록 좁음). +- 거친 땅(2.8 %) — 허용 호가 1 · 3 · 4 개 · 끝이 (+,+) · (−,−) 인 호도 나옴 → 「이웃 후보 사이 허용 호」 규칙 하나로 모두 그림 · 꼭지점 색은 각자 부호. + +### 3-3 Shift 사이 기울기 갈래 + +| 갈래 | 내용 | 판단 | +|---|---|---| +| A 원 위 마우스 방위 · 호 안으로 묶음 · 기울기 = 실제 지형 Δz / L | 길이 = L 그대로 · 보이는 % = 그 자리 땅 | **권함** — 짝 셈 · [저장] 재셈과 같은 값 | +| B 호 안 각도 비례로 −s ~ +s 나눔 | 보이는 % 가 땅과 다름 → 노드 어긋남 경고(`Span.ts:25-33`) | 안 권함 | +| C A + 값 눈금(1 % · 0.5 %)에 붙음 | 호 위 이분으로 그 % 자리 | 선택(정수 % 원하면) | + +- 노드 기록 — Shift 로 찍은 점 = `length`(길이만) **권함** · `both` + 실제 % 로 적으면 `placeNode`(`Select.ts:273`)가 크기만 보고 맞은편 후보로 튈 수 있음 · 서버 꼴(`D03_PlanAnalysis_Network.py` `NodeRecord`) 안 바뀜. +- 호 밖(가파른 쪽)에 마우스 — 가까운 호 끝(= ±s 노드)에 붙음. + +### 3-4 셈 자리 + +- 부채꼴 · 정방향 · Shift 묶음 = 화면 고르기만(서버는 꼭짓점 그대로 받고 길이 · 기울기 다시 셈) → 짝 파일(`Draw.ts` · `Draw.py`)에 안 넣고 **TS 전용 `logic/` 새 파일 + 작은 시험** 권함. 짝에 넣으면 파이썬 쪽도 같이 · 거울 시험 늘림. +- 화면 각도 — 작업 좌표(y 위) ↔ 그림 px(y 아래) · 돌린 지도 → 부채꼴 `arc` 방향 깃발을 끝점 · 가운데 점 화면 좌표로 정함(뒤집힘 흠 조심). + +## 4. Tab · 부품 상자 · B05 복사 + +### 4-1 Tab · Shift 충돌 + +| 거리 | 지금 | 처리 | +|---|---|---| +| 브라우저 초점 이동 | 긋기 중 초점 = [긋기] 단추 등 → keydown 이 window 에 옴 | 받으면 `preventDefault`(`UI_Page.ts:623-626`) → 초점 안 옮김 · 긋기 아닐 때 Tab = 그대로 초점 이동(접근성 유지) | +| 길이 · 기울기 칸에 초점 | 입력 중이면 페이지가 키를 안 받음(`UI_Page.ts:613`) | Tab = 칸 넘김(그대로) · 숨김으로 초점 칸이 사라지면 body 로 | +| 등록부 겹침 | plan 자리 Tab 없음 · 브라우저 몫(`key_registry.ts:233-242`)에도 없음 · CAD · B09 Tab 은 다른 화면 | 겹침 없음 | +| Shift+Tab | `chordOf` = "Shift+Tab" → 안 맞음 | Shift(사이 기울기) 누른 채 Tab 은 안 먹음 — 그대로 둠 | +| Shift 누른 채 누름(D03) | 긋기 중 고르기 겹은 꺼짐(`UI_Page.ts:154`) | 충돌 없음 | +| Shift 단독 키 | `keyIs` 로 못 셈 | `event.shiftKey` 직접 · 등록부엔 고정 줄(`fixed`) 「Shift 누른 채」로 표에만 | +| Shift 붙음 | 창 바꾸면 keyup 못 받음 | window blur 에서 풂 | + +### 4-2 부품 상자 + +- 방식 칸 = `createSegment` · `createInputField` · `createText` 만 · 날 `