# 2026-09-01 구현 완료·최종 검증 대기 배경 원문 상시 계획서 축약 전의 배경·설계·검증 조건을 보존한다. 완료 아카이브가 아니며 최종 검증 전까지 보류 상태다. ### 노선 원천 일원화 + 도엽 서피스 온디맨드 (2026-09-01 신규) **배경**: 용화 자동 체인이 끝까지 돌았는데 **종단 계획선이 직선**으로 나왔다. 저장본: ``` basis: "station_alignment" ← 1차 배관 정착이 아니라 2차 폴백 PVI 3개: 0.0m(879.14) → 830.5m(839.71) → 1070.4m(826.62) ``` 원인은 **관 측점이 노선과 다른 기준에서 나온 것**이다. `pipe_points.json` 관 22개 측점이 `92.6 … 2044.9 m`로 **트림 전 원본(2,136 m) 기준**인데 확정 노선은 1,070.4 m다. 22개 중 10개가 노선 끝 너머라 계획선 산출에서 관이 통째로 버려졌다. **왜 갈렸나**: 트림·조밀화를 `Service_Chain._planned_route_points_in_project_crs()` 한 곳에만 넣었는데, **계획노선을 읽는 곳이 다섯 군데다**. | 읽는 곳 | 용도 | |---|---| | `B03_FileInput_Service_Chain.py:53` | 체인 BP·EP·CP (**트림 적용됨**) | | `common_util_drainage_context.py:116` | 배수유역·관·세부유역 (트림 없음) | | `B04_PreProcess_Router_Inflow.py:82` | 유입 분석 (트림 없음) | | `B04_PreProcess_Engine_SheetSurface.py:457,493` | 도엽 서피스 절취 범위 (트림 없음) | | `B04_PreProcess_Engine_Extent.py:20` | 지도·GIS 범위 (트림 없음) | 같은 자리를 b03 커밋 `892c33c7`도 건드렸다(shapefile 판독 누락 3곳). **노선 원천이 흩어져 있어 생기는 같은 종류의 문제**다 — 한 곳에서 나오게 모아야 한다. #### ① 도엽 서피스도 기본 하나만 자동 생성 `SHEET_SURFACE_METHODS` 6종을 매번 다 만든다 — WF1 891초 중 **655초**가 여기다. LAS 필터와 같은 규칙으로 바꾼다: 자동은 `SHEET_SURFACE_DEFAULT_METHOD`(laplace) 하나, 나머지는 B04에서 관리자가 버튼을 누를 때 그 방식만. `build_sheet_surface_from_route()`가 이미 `methods` 인자를 받으므로 엔진 변경은 최소다. #### ② 배수유역도 트림된 노선만 분석 트림된 구간 밖은 지표 데이터가 없어 유역·관 배치가 성립하지 않는다. 노선 원천을 **공용 함수 한 곳**으로 모으고 위 다섯 곳이 모두 그것을 쓰게 한다. #### ③ 트림된 지점이 종점 ②가 되면 자동으로 따라온다 — 배수유역이 트림 노선을 쓰면 마지막 정점이 종점이고, `routes_match()`가 성립해 B05 계획고·경로 정점이 그대로 물린다. **구현 체크리스트**: - [ ] 자체검증 — 용화 재실행으로 관 측점이 트림 노선 안에 들어오고 `basis`가 배관 정착으로 바뀌는지 확인 **보류**: `Engine_Extent`(지도·GIS 범위)는 트림 전 노선이 맞다 — 배경 지도는 계획 전 구간을 덮어야 사용자가 측량 범위 밖을 볼 수 있다. 트림 적용 대상이 아니다. --- ### B04 노선 3D 표시 + 서피스 밖 노선 자동 트림 (2026-09-01 신규) **배경**: 실무 자료 `용화.las`가 계획노선 2,136 m 중 **1,400 m(66%)만 덮는다**. 좌표 문제가 아니라 측량 범위 자체다 — 근거는 아래 「입력 자료 실측」. 이 상태로는 자동 설계 체인이 서피스 밖 정점에서 끊긴다. #### ① B04 3D 뷰어에 계획노선 평면 표시 노선을 **3D 데이터 최고 표고(`bounds.z[1]`) 평면**에 수평선으로 그린다. 지표면에 드리운 곡선이 아니다(사용자 확정) — 노선과 측량 범위가 평면상 어디서 어긋나는지 한눈에 보이게 하는 것이 목적이다. 뷰어 좌표 규약(`ModelContext.scene_vertices`, `TerrainViewer:584`와 동일): ``` scene.x = model.x - cx scene.y = model.z - cz scene.z = -(model.y - cy) cx,cy,cz = 모델 bounds 중심 ``` 따라서 노선은 `scene.y = bounds.z[1] - cz` 고정, x·z만 노선 좌표를 따른다. 점 목록은 이미 있는 `fetchPlannedRoute()`(`/planned-route`, 프로젝트 좌표계)를 쓴다. 색은 2D 지도와 같은 `--map-route` — 같은 선을 두 화면에서 다른 색으로 그리지 않는다. #### ② 서피스 밖 노선 자동 트림 서피스를 만든 뒤 노선에 지표 데이터가 없으면, **서피스가 덮는 구간만 남기고 자른다.** 서피스 가장자리는 불규칙하므로 잘라낸 쪽 끝에서 **30 m를 더 트림**한다(사용자 확정). - 판정은 `DtmGridSampler.sample_xy()`가 돌려주는 `valid` — 확정 DTM의 `valid_mask`가 곧 불규칙 실제 외곽이다. bounds 사각형이 아니다. - 30 m 트림은 **잘린 쪽 끝에만** 적용한다. 노선 본래 종점이 서피스 안에 있으면 멀쩡한 구간을 깎을 이유가 없다. - 자를 자리는 **`_planned_route_points_in_project_crs()` 한 곳**이다 (`Service_Chain.py:28`). 체인의 BP·EP·CP가 전부 이 함수를 지나므로 여기서 한 번 자르면 하류가 모두 유효해진다. **입력 자료 실측** (2026-09-01, `2026년 임도 용화`): | 자료 | 좌표계 | 범위 | |---|---|---| | `용화.las` (VLR) | EPSG 5176 | x 208305.7~209200.5 · y 367454.8~368097.9 | | `용화.tif`+`.tfw` | EPSG 5176 (TOWGS84) | x 208288.7~209207.3 · y 367456.2~368092.4 | | 노선 `.shp` | ITRF2000 / UTM-K (라벨 5179) | 폴리라인 2,135.9 m · 정점 121 | LAS와 정사영상 범위가 서로 일치한다 → 측량 범위가 실제로 거기까지다. 위경도로 datum 보정까지 태워 비교해도 같다 — 노선 경도 129.094721~129.108631, LAS 129.093694~129.103729. **위도는 완전히 포함, 경도만 동쪽 431 m 초과.** 변환 오류라면 남북으로도 어긋나야 하는데 그렇지 않다. 덮임: 정점 121개 중 81개 안쪽, 길이 2,136 m 중 **1,400 m(66%)**. 시점은 안쪽, 누가거리 약 1,420 m부터 벗어나 종점까지 736 m가 빠진다. 끝이 잘린 모양이고 중간이 뚫린 게 아니다 — 2회 비행 중 서쪽 1구간만 받은 것으로 보인다 (기존 프로젝트는 `cloud_merged.las` 병합본, 용화는 타일 인덱스 없는 단일 파일). **구현 체크리스트**: - [ ] 자체검증 — 용화 노선으로 트림 길이·정점 수 확인, 화면에서 노선 평면 확인 --- ### 보조 워크트리 포트 분리 — 메인 8000/5173 · 보조 8001/5174 (2026-08-31 신규) **배경**: 한 PC에서 메인 폴더와 보조 워크트리(`D:\aislo-wt\sub`)를 동시에 띄운다. `.claude/`는 두 폴더가 링크로 공유하는 한 벌이라, `dev_up.py` 하나가 자기가 어느 폴더에서 도는지 스스로 알아 포트를 골라야 한다. 경로는 PC마다 달라(집 `D:\02_Software_Prog\…`, 사무실 `C:\Program_coding\…`) 하드코딩할 수 없다. **판별 방법**: 링크 워크트리는 `.git`이 **파일**(`gitdir: …`), 메인 클론은 **디렉터리**다. `os.path.isfile(ROOT/".git")` 한 줄로 갈린다 — git 서브프로세스도, PC별 경로도 필요 없다. **배선 현황** (조사 결과 — 대부분 이미 env로 뚫려 있음): | 지점 | 환경변수 | 기본값 | 상태 | |---|---|---|---| | `config/config_system.py:44` | `SERVER_PORT` | 8000 | 기존 | | `main.py:80` | `FRONTEND_DEV_PORT` | 5173 | 기존 | | `vite.config.ts:5` | `AISLO_API_PORT` | 8000 | 기존 (프록시 대상) | | `.claude/browser_driver.py:38` | `AISLO_VITE_PORT` | 5173 | 기존 | | `.claude/dev_up.py:80` | — | 8000·5173 하드코딩 | **이번 수정** | `config_frontend.ts:14`는 `API_BASE_URL = "/api"` 상대경로 → 프론트 수정 불필요. `load_dotenv()`가 `override=False`라 프로세스 env가 추적 파일 `.env`를 이긴다 → `.env` 수정 없이 포트 분리 가능. **구현 체크리스트**: **링크 공유에서 제외해야 할 것** (조사 중 발견): `config/node_modules`는 vite 캐시(`.vite`)와 빌드 출력(`.build`)을 같이 담고, `config_system.py:48`의 `STATIC_DIR`이 그 `.build`를 서빙한다. `main.py:261`이 기동 때마다 `npm run build`를 돌리므로 **링크하면 두 백엔드가 같은 산출물을 덮어쓴다**. → `config/node_modules`·`openwebcad/node_modules`는 보조에서 `npm install` 따로. `venv`·`national_contours.gpkg`(22G)는 읽기 전용이라 링크 안전. **남는 위험 — DB 공유**: 두 백엔드가 같은 원격 DB(`dsm.chemifactory.com:53306` / `aislo_db`)를 본다. 같은 프로젝트를 양쪽에서 열면 서로 덮는다. 폴더별 DB 분리는 이번 범위 밖 — 작업 시 프로젝트를 나눠 쓴다. - [ ] 보조 워크트리에서 `dev_up.py`를 직접 실행해 8001·5174 자동 기동과 메인 환경 무충돌을 확인한다.