refactor(B04): B04_wf1_Surface -> B04_PreProcess 전면 개명

- 폴더·내부 파일 51개 접두사 개명 (git mv, 이력 보존)
- 저장소 전체 참조 치환 67파일: import 경로, 라우트 슬러그(b04-preprocess),
  라우트 키(B04_PREPROCESS), storage 경로 상수, locale, SQL 주석
- 로직 변경 없음 (기계적 치환). typecheck·백엔드 import 검증 통과

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-08 10:01:36 +09:00
co-authored by Claude Fable 5
parent 2abca64deb
commit f7528a4aa4
80 changed files with 192 additions and 192 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

+1 -1
View File
@@ -10,7 +10,7 @@
* ========================================================================== */
import { API_BASE_URL } from "@config/config_frontend";
import { fetchConfirmedSurface } from "../B04_wf1_Surface/B04_wf1_Surface_Api_Fetch";
import { fetchConfirmedSurface } from "../B04_PreProcess/B04_PreProcess_Api_Fetch";
const DB_NAME = "aislo-asset-cache";
// 담아 둔 자료의 형식이나 내용이 바뀌면 이 번호를 올린다 — 올리면 기존 보관분을 통째로 버린다.
+2 -2
View File
@@ -5,7 +5,7 @@ import {
type RoutePath,
} from "@config/config_frontend";
import type { WorkflowStage } from "@ui/ui_template_workflow_layout";
import { fetchConfirmedSurface } from "../B04_wf1_Surface/B04_wf1_Surface_Api_Fetch";
import { fetchConfirmedSurface } from "../B04_PreProcess/B04_PreProcess_Api_Fetch";
import { isProjectPreloaded, setPreloadTarget } from "./b_asset_cache";
import { navigateTo } from "./router";
@@ -17,7 +17,7 @@ export interface WorkflowState {
export const WORKFLOW_STEP_ROUTES: readonly RoutePath[] = [
ROUTES.B03_FILE_INPUT,
ROUTES.B04_WF1_SURFACE,
ROUTES.B04_PREPROCESS,
ROUTES.B05_WF2_ROUTE,
ROUTES.B06_WF3_PROFILE_CROSS,
ROUTES.B07_WF4_DESIGN_DETAIL,
+1 -1
View File
@@ -18,7 +18,7 @@ const FOOTERLESS_ROUTES: readonly RoutePath[] = [
ROUTES.B01_ACCOUNT,
ROUTES.B02_PROJ_REGISTER,
ROUTES.B03_FILE_INPUT,
ROUTES.B04_WF1_SURFACE,
ROUTES.B04_PREPROCESS,
ROUTES.B05_WF2_ROUTE,
ROUTES.B06_WF3_PROFILE_CROSS,
ROUTES.B07_WF4_DESIGN_DETAIL,
+3 -3
View File
@@ -39,8 +39,8 @@ const routeTable: Partial<Record<RoutePath, () => Promise<PageRenderer>>> = {
(await import("../B02_ProjRegister/B02_ProjRegister_UI_Page")).renderB02ProjRegister,
[ROUTES.B03_FILE_INPUT]: async () =>
(await import("../B03_FileInput/B03_FileInput_UI_Page")).renderB03FileInput,
[ROUTES.B04_WF1_SURFACE]: async () =>
(await import("../B04_wf1_Surface/B04_wf1_Surface_UI_Page")).renderB04Surface,
[ROUTES.B04_PREPROCESS]: async () =>
(await import("../B04_PreProcess/B04_PreProcess_UI_Page")).renderB04Surface,
[ROUTES.B05_WF2_ROUTE]: async () =>
(await import("../B05_wf2_Route/B05_wf2_Route_UI_Page")).renderB05Route,
[ROUTES.B06_WF3_PROFILE_CROSS]: async () =>
@@ -106,7 +106,7 @@ export async function renderCurrentRoute(outlet: HTMLElement): Promise<void> {
const workflowRoutes: readonly RoutePath[] = [
ROUTES.B02_PROJ_REGISTER,
ROUTES.B03_FILE_INPUT,
ROUTES.B04_WF1_SURFACE,
ROUTES.B04_PREPROCESS,
ROUTES.B05_WF2_ROUTE,
ROUTES.B06_WF3_PROFILE_CROSS,
ROUTES.B07_WF4_DESIGN_DETAIL,
+1 -1
View File
@@ -31,7 +31,7 @@ def _planned_route_points_in_project_crs(project_root: Path) -> list[dict[str, f
B04 `/planned-route` 조회와 같은 규칙 — CSV가 제 좌표계(crs_epsg)를 적어 두었고
프로젝트 좌표계와 다르면 한 번 옮긴다.
"""
from B04_wf1_Surface.B04_wf1_Surface_Engine_Extent import project_epsg_from_prj
from B04_PreProcess.B04_PreProcess_Engine_Extent import project_epsg_from_prj
from common_util.common_util_route_geometry import (
find_planned_route_file,
read_planned_route_csv,
+5 -5
View File
@@ -74,7 +74,7 @@ async def trigger_wf1_analysis_and_email(
await connection.commit()
stored_path = await get_project_storage_relative_path(connection, project_id)
project_info = await _get_project_notification_info(connection, project_id)
from B04_wf1_Surface.B04_wf1_Surface_Repository import get_input_file
from B04_PreProcess.B04_PreProcess_Repository import get_input_file
input_file = await get_input_file(connection, project_id, input_file_id)
@@ -83,9 +83,9 @@ async def trigger_wf1_analysis_and_email(
if not las_path.is_file():
raise FileNotFoundError("원본 LAS/LAZ 파일을 찾을 수 없습니다.")
from B04_wf1_Surface.B04_wf1_Surface_Engine import run_surface_analysis
from B04_wf1_Surface.B04_wf1_Surface_Repository import save_surface_analysis_to_db
from B04_wf1_Surface.B04_wf1_Surface_Router import write_surface_progress
from B04_PreProcess.B04_PreProcess_Engine import run_surface_analysis
from B04_PreProcess.B04_PreProcess_Repository import save_surface_analysis_to_db
from B04_PreProcess.B04_PreProcess_Router import write_surface_progress
write_surface_progress(project_root, 5, "analyzing", "WF1 분석을 시작합니다.")
@@ -119,7 +119,7 @@ async def trigger_wf1_analysis_and_email(
# 사용자다. 모두 기본값으로 자동 확정하고 B05·B06 자동 계산 체인까지 탄다.
# 관리자는 B04에서 다른 모델을 골라 재확정할 수 있다(체인은 경로가 이미
# 있으면 스스로 건너뛴다).
from B04_wf1_Surface.B04_wf1_Surface_Service import (
from B04_PreProcess.B04_PreProcess_Service import (
confirm_surface_selection,
find_surface_model_for_selection,
)
+1 -1
View File
@@ -54,7 +54,7 @@ function L(key: keyof typeof ui_locales): string {
export async function renderB03FileInput(root: HTMLElement): Promise<void> {
const dashboardUser = await fetchDashboardMe();
const completionRoute =
dashboardUser.role === "SYSTEM_ADMIN" ? ROUTES.B04_WF1_SURFACE : ROUTES.B05_WF2_ROUTE;
dashboardUser.role === "SYSTEM_ADMIN" ? ROUTES.B04_PREPROCESS : ROUTES.B05_WF2_ROUTE;
const slots = initializeSlots();
const cardMap = new Map<FileSlot, HTMLElement>();
const resultList = document.createElement("ul");
@@ -1,8 +1,8 @@
/* =============================================================================
* B04_wf1_Surface_Api_Fetch.ts
* B04_PreProcess_Api_Fetch.ts
* 1 ( ) API
*
* (B04_wf1_Surface_Router.py):
* (B04_PreProcess_Router.py):
* POST /api/projects/{project_id}/surface/analyze + DB
* GET /api/projects/{project_id}/surface/models
*
@@ -290,7 +290,7 @@ export async function fetchPlannedRoute(projectId: string): Promise<PlannedRoute
});
}
/* (B04_wf1_Surface_Router_Watershed.py)
/* (B04_PreProcess_Router_Watershed.py)
* . (B03 CSV) + ·
* . 30 .
* ------------------------------------------------------------------------ */
@@ -13,13 +13,13 @@ from typing import Any
import numpy as np
from B04_wf1_Surface.B04_wf1_Surface_Engine_Ground import (
from B04_PreProcess.B04_PreProcess_Engine_Ground import (
build_ground_masks,
run_ground_filter,
summarize_masks,
)
from B04_wf1_Surface.B04_wf1_Surface_Engine_Pipeline import build_all_terrain_models
from B04_wf1_Surface.B04_wf1_Surface_Engine_Structurize import structurize_las
from B04_PreProcess.B04_PreProcess_Engine_Pipeline import build_all_terrain_models
from B04_PreProcess.B04_PreProcess_Engine_Structurize import structurize_las
from common_util.common_util_atomic import atomic_write_npz
from common_util.common_util_json import atomic_write_json
from config.config_system import build_surface_model_config
@@ -124,7 +124,7 @@ def run_surface_analysis(
on_progress(percent, stage, message)
total_started = time.monotonic()
stage_root = project_root / "B04_wf1_Surface"
stage_root = project_root / "B04_PreProcess"
processed_dir = stage_root / "processed"
models_dir = stage_root / "models"
processed_dir.mkdir(parents=True, exist_ok=True)
@@ -232,13 +232,13 @@ def run_surface_analysis(
)
prj_path = prj_candidates[0] if prj_candidates else project_root / "result.prj"
from B04_wf1_Surface.B04_wf1_Surface_Engine_Extent import (
from B04_PreProcess.B04_PreProcess_Engine_Extent import (
download_extent,
map_meta_covers,
satellite_extent,
)
from B04_wf1_Surface.B04_wf1_Surface_Engine_GisVector import download_all_gis_vectors
from B04_wf1_Surface.B04_wf1_Surface_Engine_VWorld import (
from B04_PreProcess.B04_PreProcess_Engine_GisVector import download_all_gis_vectors
from B04_PreProcess.B04_PreProcess_Engine_VWorld import (
download_vworld_satellite_map,
get_epsg_from_prj,
)
@@ -257,7 +257,7 @@ def run_surface_analysis(
# — 수치지형도 도엽과 같은 눈금. 주변 도엽은 받지 않는다(2026-08-01 사용자 지시).
map_bounds_for_download = satellite_extent(project_root, las_bounds_dict, project_epsg)
# VWorld 지도 및 GIS 데이터 저장 위치는 B04_wf1_Surface/processed에 보관.
# VWorld 지도 및 GIS 데이터 저장 위치는 B04_PreProcess/processed에 보관.
layers = [
{"layer": "Satellite", "ext": "jpeg"},
{"layer": "Hybrid", "ext": "png"},
@@ -307,9 +307,9 @@ def run_surface_analysis(
# (실패해도 분석은 계속 — 폴백은 수동 다운로드 + 인제스트)
_report(92, "download_maps", "수치지형도 도엽 확보 중")
try:
from B04_wf1_Surface.B04_wf1_Surface_Engine_Extent import sheet_reference_points_wgs84
from B04_wf1_Surface.B04_wf1_Surface_Engine_MapSheet import neighbors_for_points
from B04_wf1_Surface.B04_wf1_Surface_Engine_SheetStore import (
from B04_PreProcess.B04_PreProcess_Engine_Extent import sheet_reference_points_wgs84
from B04_PreProcess.B04_PreProcess_Engine_MapSheet import neighbors_for_points
from B04_PreProcess.B04_PreProcess_Engine_SheetStore import (
ensure_sheets,
get_project_map_sheets_dir,
prune_sheets,
@@ -338,7 +338,7 @@ def run_surface_analysis(
if sheet_result["available"] and (
rebuild or not any(processed_dir.glob("도엽_*.geojson"))
):
from B04_wf1_Surface.B04_wf1_Surface_Engine_SheetParser import (
from B04_PreProcess.B04_PreProcess_Engine_SheetParser import (
parse_and_merge_sheets,
)
@@ -1,4 +1,4 @@
# B04_wf1_Surface_Engine_Extent.py
# B04_PreProcess_Engine_Extent.py
# 전처리에서 내려받을 범위와 기준 좌표를 정한다.
#
# 배경(2026-08-01 사용자 지시): 배경 지도·수치지형도 도엽의 기준을 라이다 범위 한가운데로
@@ -95,7 +95,7 @@ def satellite_extent(
"""
from pyproj import Transformer
from .B04_wf1_Surface_Engine_MapSheet import sheet5k_to_bounds, sheets_for_points
from .B04_PreProcess_Engine_MapSheet import sheet5k_to_bounds, sheets_for_points
points = sheet_reference_points_wgs84(project_root, las_bounds, target_epsg)
sheets = sheets_for_points(points)
@@ -145,7 +145,7 @@ def planned_route_bounds(project_root: Path, target_epsg: str) -> dict[str, floa
def project_epsg_from_prj(project_root: Path) -> str:
"""프로젝트 PRJ에서 좌표계를 읽는다. 없으면 중부원점(EPSG:5186)."""
from .B04_wf1_Surface_Engine_VWorld import get_epsg_from_prj
from .B04_PreProcess_Engine_VWorld import get_epsg_from_prj
for prj_path in sorted(project_root.glob("B03_FileInput/**/*.prj")):
return get_epsg_from_prj(prj_path.read_text(encoding="utf-8", errors="ignore"))
@@ -22,7 +22,7 @@ except ImportError:
VWORLD_API_KEY = "3DBD7306-7DBD-38BB-B292-267C5ED7AC6B"
PROJECT_ROOT = Path(__file__).resolve().parent.parent
from B04_wf1_Surface.B04_wf1_Surface_Engine_VWorld import get_epsg_from_prj
from B04_PreProcess.B04_PreProcess_Engine_VWorld import get_epsg_from_prj
logger = logging.getLogger(__name__)
@@ -9,10 +9,10 @@ from typing import Any
import numpy as np
from B04_wf1_Surface.B04_wf1_Surface_Engine_Filter_CSF import filter_csf
from B04_wf1_Surface.B04_wf1_Surface_Engine_Filter_Grid import filter_grid_min_z
from B04_wf1_Surface.B04_wf1_Surface_Engine_Filter_PMF import filter_pmf
from B04_wf1_Surface.B04_wf1_Surface_Engine_Filter_RANSAC import filter_ransac
from B04_PreProcess.B04_PreProcess_Engine_Filter_CSF import filter_csf
from B04_PreProcess.B04_PreProcess_Engine_Filter_Grid import filter_grid_min_z
from B04_PreProcess.B04_PreProcess_Engine_Filter_PMF import filter_pmf
from B04_PreProcess.B04_PreProcess_Engine_Filter_RANSAC import filter_ransac
# 필터 키 → 함수 매핑
_FILTERS = {
@@ -1,4 +1,4 @@
# B04_wf1_Surface_Engine_MapSheet.py
# B04_PreProcess_Engine_MapSheet.py
# 1:5,000 수치지형도 도엽번호 산출 엔진.
# 국토지리정보원 도엽번호 체계:
# - 경위도 1°x1° 구획: 위도 2자리 + 경도 끝 1자리 (예: 369 = 위도 36~37°, 경도 129~130°)
@@ -11,7 +11,7 @@ import numpy as np
from scipy.interpolate import RBFInterpolator, RectBivariateSpline
from scipy.spatial import Delaunay
from B04_wf1_Surface.B04_wf1_Surface_Engine_ModelContext import (
from B04_PreProcess.B04_PreProcess_Engine_ModelContext import (
ProgressCallback,
TerrainContext,
artifact_size,
@@ -14,18 +14,18 @@ from typing import Any, Callable
import numpy as np
from B04_wf1_Surface.B04_wf1_Surface_Engine_Contour import (
from B04_PreProcess.B04_PreProcess_Engine_Contour import (
CONTOUR_EXTRACTOR_VERSION,
extract_contours,
)
from B04_wf1_Surface.B04_wf1_Surface_Engine_ModelBuild import BUILDERS
from B04_wf1_Surface.B04_wf1_Surface_Engine_ModelContext import (
from B04_PreProcess.B04_PreProcess_Engine_ModelBuild import BUILDERS
from B04_PreProcess.B04_PreProcess_Engine_ModelContext import (
MODEL_VERSION,
TerrainContext,
bounds_dict,
config_signature,
)
from B04_wf1_Surface.B04_wf1_Surface_Engine_Smooth import (
from B04_PreProcess.B04_PreProcess_Engine_Smooth import (
compute_smoothing_signature,
run_smoothing,
)
@@ -1,4 +1,4 @@
# B04_wf1_Surface_Engine_SheetParser.py
# B04_PreProcess_Engine_SheetParser.py
# 1:5,000 수치지형도 도엽 zip 파서 + 9매 병합 → 레이어별 GeoJSON 산출.
#
# 레이어 코드 (보유 도엽 2매 실측 확정, 2026-07-26):
@@ -19,7 +19,7 @@ from pathlib import Path
import geopandas as gpd
import pandas as pd
from .B04_wf1_Surface_Engine_SheetStore import _load_index, get_sheet_path
from .B04_PreProcess_Engine_SheetStore import _load_index, get_sheet_path
logger = logging.getLogger(__name__)
@@ -1,11 +1,11 @@
# B04_wf1_Surface_Engine_SheetStore.py
# B04_PreProcess_Engine_SheetStore.py
# 1:5,000 수치지형도 도엽 zip — 프로젝트 영구저장소 관리.
# 저장 위치: {프로젝트 저장소}/B04_wf1_Surface/processed/map_sheets/{도엽번호}.zip
# 저장 위치: {프로젝트 저장소}/B04_PreProcess/processed/map_sheets/{도엽번호}.zip
# (위성지도·GIS 벡터 등 주변데이터와 동일한 프로젝트 processed 계층)
#
# 조사 결과(2026-07-26 실측):
# - 도엽번호 산출: 브이월드 오픈 API(api.vworld.kr)에는 색인 레이어가 없어
# 자체 알고리즘(B04_wf1_Surface_Engine_MapSheet) 사용 — 보유 도엽 10매 정합 확인.
# 자체 알고리즘(B04_PreProcess_Engine_MapSheet) 사용 — 보유 도엽 10매 정합 확인.
# - 도엽 검색: 지도서비스 내부 API `map.vworld.kr/ws3dmap/getDisitalMapList.do`
# (type=M02, searchNum=도엽번호, scale, version) — 무로그인 조회 가능.
# Ver2.0 = zip(SHP), Ver1.0 = dxf.
@@ -35,7 +35,7 @@ from config.config_system import (
VWORLD_SESSION_COOKIE,
)
from .B04_wf1_Surface_Engine_MapSheet import latlon_to_sheet5k, sheet5k_to_bounds
from .B04_PreProcess_Engine_MapSheet import latlon_to_sheet5k, sheet5k_to_bounds
logger = logging.getLogger(__name__)
@@ -61,7 +61,7 @@ def get_project_map_sheets_dir(project_storage_path: str | Path) -> Path:
project_storage_path: config_system.get_project_storage_path() 결과
(storage/{회사}/{사용자}/{프로젝트ID}).
"""
return Path(project_storage_path) / "B04_wf1_Surface" / "processed" / MAP_SHEETS_DIRNAME
return Path(project_storage_path) / "B04_PreProcess" / "processed" / MAP_SHEETS_DIRNAME
# ─────────────────────────────────────────────────────────────────────────
@@ -14,7 +14,7 @@ import trimesh
from scipy import ndimage
from scipy.interpolate import RectBivariateSpline
from B04_wf1_Surface.B04_wf1_Surface_Engine_ModelContext import (
from B04_PreProcess.B04_PreProcess_Engine_ModelContext import (
TerrainContext,
artifact_size,
atomic_npz,
@@ -29,23 +29,23 @@ from typing import Any
import numpy as np
from shapely.geometry import LineString
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Descent import ContourDescent
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Expand import expand_by_red_boundary
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Flow import (
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Descent import ContourDescent
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Expand import expand_by_red_boundary
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Flow import (
FlowClassification,
RoadRaster,
largest_ring,
outer_boundary,
trace_flow,
)
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Grid import (
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Grid import (
AZIMUTH_STEPS,
GridSpec,
TerrainGrid,
build_contour_cloud,
route_elevation_floor,
)
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Stream import (
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Stream import (
PrimaryRegion,
build_primary_region,
)
@@ -32,7 +32,7 @@ from rasterio.features import rasterize
from scipy.ndimage import distance_transform_edt
from shapely.geometry import shape
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Grid import (
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Grid import (
AZIMUTH_INVALID,
AZIMUTH_SINK,
AZIMUTH_STEPS,
@@ -21,11 +21,11 @@ from typing import Any
import numpy as np
from shapely.geometry import LineString
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Descent import (
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Descent import (
ContourDescent,
build_contour_descent,
)
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Flow import (
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Flow import (
FlowClassification,
RoadRaster,
burn_stream_flow,
@@ -33,7 +33,7 @@ from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Flow import (
outermost_cells,
rasterize_road,
)
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Grid import GridSpec, TerrainGrid
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Grid import GridSpec, TerrainGrid
from config.config_system import (
DRAINAGE_RED_EXPAND_BAND_M,
DRAINAGE_RED_EXPAND_MAX_ROUNDS,
@@ -5,7 +5,7 @@
`STAGES` 이름을 하나 넣고 `write_stage()` 호출하면 된다 파일명 규칙과 매니페스트
갱신은 여기서 일괄로 처리한다.
저장 위치: `storage/{회사}/{사용자}/{프로젝트}/B04_wf1_Surface/drainage/`
저장 위치: `storage/{회사}/{사용자}/{프로젝트}/B04_PreProcess/drainage/`
- `{단계번호}_{단계이름}.geojson` WGS84 FeatureCollection, 피처마다 `kind` 속성
- `manifest.json` 지금까지 남긴 단계 목록과 요약값
"""
@@ -41,7 +41,7 @@ LonLat = Callable[[float, float], tuple[float, float]]
def drainage_dir(stored_path: str) -> Path:
return (
Path(resolve_stored_project_path(stored_path)) / "B04_wf1_Surface" / DRAINAGE_CACHE_DIRNAME
Path(resolve_stored_project_path(stored_path)) / "B04_PreProcess" / DRAINAGE_CACHE_DIRNAME
)
@@ -24,7 +24,7 @@ from scipy.spatial import cKDTree
from shapely.geometry import LineString, MultiPolygon, Polygon, shape
from shapely.ops import unary_union
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Grid import (
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Grid import (
AZIMUTH_STEPS,
ContourCloud,
GridSpec,
@@ -5,7 +5,7 @@
전체** 잡는다(2026-07-31 사용자 지시).
여기서 정해진 1 배수유역의 bbox가 격자 해석 범위가 된다.
표고 해석·격자 생성은 `B04_wf1_Surface_Engine_Watershed_Grid.py` 맡는다.
표고 해석·격자 생성은 `B04_PreProcess_Engine_Watershed_Grid.py` 맡는다.
"""
from __future__ import annotations
@@ -20,7 +20,7 @@ from scipy.spatial import cKDTree
from shapely.geometry import LineString, MultiPolygon, Polygon, shape
from shapely.ops import substring, unary_union
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Grid import (
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Grid import (
ContourCloud,
GridSpec,
build_cell_mask,
@@ -12,11 +12,11 @@ from uuid import UUID
import aiomysql
_STAGE_ROOT = "B04_wf1_Surface"
_STAGE_ROOT = "B04_PreProcess"
def _validate_stage_path(relative_path: str) -> str:
"""B04_wf1_Surface 아래의 안전한 상대 경로인지 검증하고 posix 문자열로 반환한다."""
"""B04_PreProcess 아래의 안전한 상대 경로인지 검증하고 posix 문자열로 반환한다."""
normalized = PurePosixPath(relative_path.replace("\\", "/"))
if normalized.is_absolute() or ".." in normalized.parts:
raise ValueError("DB에는 프로젝트 루트 기준 상대 경로만 저장할 수 있습니다.")
@@ -13,23 +13,23 @@ from fastapi import APIRouter, Depends, Request
from fastapi.responses import JSONResponse, Response
from B03_FileInput.B03_FileInput_Repository import get_project_storage_relative_path
from B04_wf1_Surface.B04_wf1_Surface_Engine import (
from B04_PreProcess.B04_PreProcess_Engine import (
GROUND_POINT_CACHE_VERSION,
cache_ground_points,
run_surface_analysis,
)
from B04_wf1_Surface.B04_wf1_Surface_Engine_Extent import (
from B04_PreProcess.B04_PreProcess_Engine_Extent import (
planned_route_bounds,
project_epsg_from_prj,
)
from B04_wf1_Surface.B04_wf1_Surface_Repository import (
from B04_PreProcess.B04_PreProcess_Repository import (
clear_confirmed_surface_models,
get_input_file,
list_project_point_cloud_inputs,
list_surface_models,
save_surface_analysis_to_db,
)
from B04_wf1_Surface.B04_wf1_Surface_Schema import (
from B04_PreProcess.B04_PreProcess_Schema import (
SurfaceAnalyzeRequest,
SurfaceAnalyzeResponse,
SurfaceConfirmedResponse,
@@ -42,7 +42,7 @@ from B04_wf1_Surface.B04_wf1_Surface_Schema import (
SurfaceModelSummary,
SurfacePointCloudSampleResponse,
)
from B04_wf1_Surface.B04_wf1_Surface_Service import confirm_surface_selection
from B04_PreProcess.B04_PreProcess_Service import confirm_surface_selection
from common_util.common_util_auth import require_system_admin
from common_util.common_util_http_cache import cached_file_response
from common_util.common_util_json import atomic_write_json
@@ -62,7 +62,7 @@ logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/projects", tags=["B04 Surface Analysis"])
POINT_CLOUD_SAMPLE_LIMIT = 500_000
# 분석 진행률 파일: B04 산출 폴더 아래에 원자적으로 기록/조회한다.
PROGRESS_FILE_RELATIVE = ("B04_wf1_Surface", "processed", "progress.json")
PROGRESS_FILE_RELATIVE = ("B04_PreProcess", "processed", "progress.json")
def _progress_file_path(project_root: Path) -> Path:
@@ -315,7 +315,7 @@ async def get_surface_point_cloud(
async with pool.acquire() as connection:
stored_path = await get_project_storage_relative_path(connection, project_id)
project_root = Path(resolve_stored_project_path(stored_path))
structured_path = project_root / "B04_wf1_Surface" / "processed" / "structured.npz"
structured_path = project_root / "B04_PreProcess" / "processed" / "structured.npz"
if not structured_path.is_file():
return JSONResponse(
status_code=404,
@@ -407,7 +407,7 @@ async def get_confirmed_surface(project_id: UUID) -> SurfaceConfirmedResponse |
# 가장자리는 B05가 3D 마커 좌표를 환산할 때 쓰므로, 기존 포인트클라우드 응답과
# 같은 파일(확정 필터의 지면 포인트)에서 읽어 값이 어긋나지 않게 한다.
processed_dir = Path(resolve_stored_project_path(stored_path)) / "B04_wf1_Surface"
processed_dir = Path(resolve_stored_project_path(stored_path)) / "B04_PreProcess"
processed_dir = processed_dir / "processed"
source_path = processed_dir / "structured.npz"
if source_filter:
@@ -475,7 +475,7 @@ async def get_surface_ground_stats(project_id: UUID) -> SurfaceGroundStatsRespon
async with pool.acquire() as connection:
stored_path = await get_project_storage_relative_path(connection, project_id)
project_root = Path(resolve_stored_project_path(stored_path))
manifest_path = project_root / "B04_wf1_Surface" / "models" / "manifest.json"
manifest_path = project_root / "B04_PreProcess" / "models" / "manifest.json"
if not manifest_path.is_file():
return SurfaceGroundStatsResponse(project_id=str(project_id), filters={})
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
@@ -22,7 +22,7 @@ from uuid import UUID
from fastapi import APIRouter
from fastapi.responses import JSONResponse
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Export import drainage_dir
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Export import drainage_dir
from common_util.common_util_drainage_context import DrainageContext, load_drainage_context
from common_util.common_util_drainage_detail import DrainageDetail, build_detail
from common_util.common_util_drainage_pipes import (
@@ -14,7 +14,7 @@ from fastapi import APIRouter, Request
from fastapi.responses import JSONResponse, Response
from B03_FileInput.B03_FileInput_Repository import get_project_storage_relative_path
from B04_wf1_Surface.B04_wf1_Surface_Engine_Contour import (
from B04_PreProcess.B04_PreProcess_Engine_Contour import (
CONTOUR_EXTRACTOR_VERSION,
extract_contours,
)
@@ -89,7 +89,7 @@ async def get_surface_model_contour(
model_path = project_root / model_file_path
models_dir = model_path.parent
structured_path = project_root / "B04_wf1_Surface" / "processed" / "structured.npz"
structured_path = project_root / "B04_PreProcess" / "processed" / "structured.npz"
stem = model_path.stem
parts = stem.split("_")
if len(parts) >= 2:
@@ -18,7 +18,7 @@ router = APIRouter(prefix="/api/projects", tags=["B04 Surface GIS"])
tiles_router = APIRouter(tags=["B04 MVT Tiles"])
# 수치지형도 도엽 병합 레이어 (SheetParser 산출과 1:1 — 정의는 SHEET_LAYERS가 유일)
from B04_wf1_Surface.B04_wf1_Surface_Engine_SheetParser import SHEET_LAYERS # noqa: E402
from B04_PreProcess.B04_PreProcess_Engine_SheetParser import SHEET_LAYERS # noqa: E402
_SHEET_GEOJSON_FILES = {f"도엽_{k}": f"도엽_{k}.geojson" for k in SHEET_LAYERS}
@@ -34,7 +34,7 @@ async def get_vworld_meta(
async with pool.acquire() as connection:
stored_path = await get_project_storage_relative_path(connection, project_id)
project_root = Path(resolve_stored_project_path(stored_path))
target_dir = project_root / "B04_wf1_Surface" / "processed"
target_dir = project_root / "B04_PreProcess" / "processed"
target_layer = "white" if layer_name.lower() in ["gray", "white"] else layer_name.lower()
meta_name = f"vworld_{target_layer}_meta.json"
@@ -67,7 +67,7 @@ async def get_vworld_map(
async with pool.acquire() as connection:
stored_path = await get_project_storage_relative_path(connection, project_id)
project_root = Path(resolve_stored_project_path(stored_path))
target_dir = project_root / "B04_wf1_Surface" / "processed"
target_dir = project_root / "B04_PreProcess" / "processed"
target_layer = layer_name.lower()
if target_layer in ["gray", "white"]:
@@ -107,7 +107,7 @@ async def get_project_geojson(
async with pool.acquire() as connection:
stored_path = await get_project_storage_relative_path(connection, project_id)
project_root = Path(resolve_stored_project_path(stored_path))
target_dir = project_root / "B04_wf1_Surface" / "processed"
target_dir = project_root / "B04_PreProcess" / "processed"
layer_mapping = {
"지적도": "연속지적도_bounds.geojson",
@@ -129,7 +129,7 @@ async def get_project_geojson(
# 등고선은 전처리 이후 국가 gpkg가 추가된 경우를 대비해 요청 시점에 크롭 생성한다.
if layer == "등고선" and not filepath.exists():
from B04_wf1_Surface.B04_wf1_Surface_Engine_GisVector import (
from B04_PreProcess.B04_PreProcess_Engine_GisVector import (
crop_national_contours,
read_bounds_wgs84_from_meta,
)
@@ -185,7 +185,7 @@ async def get_vector_tile(project_id: UUID, layer: str, z: int, x: int, y: int)
async with pool.acquire() as connection:
stored_path = await get_project_storage_relative_path(connection, project_id)
project_root = Path(resolve_stored_project_path(stored_path))
target_dir = project_root / "B04_wf1_Surface" / "processed"
target_dir = project_root / "B04_PreProcess" / "processed"
layer_mapping = {
"지적도": "연속지적도_bounds.geojson",
@@ -224,7 +224,7 @@ async def get_vector_tile(project_id: UUID, layer: str, z: int, x: int, y: int)
return Response(content=empty_tile, media_type="application/x-protobuf")
cache_key = f"{project_id}_{layer}"
from B04_wf1_Surface.B04_wf1_Surface_Engine_MvtHelper import generate_mvt_tile
from B04_PreProcess.B04_PreProcess_Engine_MvtHelper import generate_mvt_tile
mvt_bytes = generate_mvt_tile(filepath, cache_key, z, x, y, layer_name=layer)
return Response(
@@ -247,7 +247,7 @@ async def get_planned_route(project_id: UUID) -> dict[str, Any] | JSONResponse:
B05의 확정 경로가 아니라 **원청이 계획선**이다. 아직 올리지 않았거나 좌표가
모자라면 목록을 돌려준다 화면은 계획선만 빼고 그대로 그린다.
"""
from B04_wf1_Surface.B04_wf1_Surface_Engine_Extent import project_epsg_from_prj
from B04_PreProcess.B04_PreProcess_Engine_Extent import project_epsg_from_prj
from common_util.common_util_route_geometry import (
find_planned_route_file,
read_planned_route_csv,
@@ -21,9 +21,9 @@ from fastapi.responses import JSONResponse
from pyproj import Transformer
from B03_FileInput.B03_FileInput_Repository import get_project_storage_relative_path
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Export import STAGES, drainage_dir
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Flow import polygonize_labels
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Grid import GridSpec
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Export import STAGES, drainage_dir
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Flow import polygonize_labels
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Grid import GridSpec
from B05_wf2_Route.B05_wf2_Route_Repository import get_surface_crs_epsg
from common_util.common_util_route_geometry import (
find_planned_route_file,
@@ -1,7 +1,7 @@
"""배수유역 분석 API 라우터 (B04 — 관리자 확인용).
계획 노선(B03 업로드 CSV) 도엽 등고선·세류선으로 배수유역을 끝까지 분석하고, 결과를
`storage/{프로젝트}/B04_wf1_Surface/drainage/` 남긴다. 30 안팎이 걸리므로 여기서 번만
`storage/{프로젝트}/B04_PreProcess/drainage/` 남긴다. 30 안팎이 걸리므로 여기서 번만
돌리고, 일반 사용자가 쓰는 B05는 저장분을 읽어 쓴다(2026-07-31 사용자 지시).
좌표는 사업지 CRS(m)에서 계산하고 응답만 WGS84로 바꿔 내보낸다.
@@ -23,13 +23,13 @@ from pyproj import Transformer
from shapely.geometry import Point, Polygon, box
from B03_FileInput.B03_FileInput_Repository import get_project_storage_relative_path
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Analyze import preview_stages
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Export import (
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Analyze import preview_stages
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Export import (
drainage_dir,
write_grid_arrays,
write_stage,
)
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Grid import (
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Grid import (
AZIMUTH_INVALID,
AZIMUTH_SINK,
AZIMUTH_STEPS,
@@ -71,7 +71,7 @@ RESPONSE_SCHEMA_VERSION = 3
def _sheet_dir(stored_path: str) -> Path:
return Path(resolve_stored_project_path(stored_path)) / "B04_wf1_Surface" / "processed"
return Path(resolve_stored_project_path(stored_path)) / "B04_PreProcess" / "processed"
def _route_input_dir(stored_path: str) -> Path:
@@ -5,7 +5,7 @@ from uuid import UUID
import aiomysql
from B04_wf1_Surface.B04_wf1_Surface_Repository import (
from B04_PreProcess.B04_PreProcess_Repository import (
confirm_surface_model,
list_surface_models,
)
@@ -25,20 +25,20 @@ import {
type DetailBasin,
type PipeSource,
type VWorldMeta,
} from "./B04_wf1_Surface_Api_Fetch";
} from "./B04_PreProcess_Api_Fetch";
import {
haloColor,
lonLatToScreen,
metricToScreen,
type Normalizer,
type ViewState,
} from "./B04_wf1_Surface_UI_MapRender";
} from "./B04_PreProcess_UI_MapRender";
import {
nearestChainage,
pointAtChainage,
resampleRoute,
type RoutePoint,
} from "./B04_wf1_Surface_UI_RouteSamples";
} from "./B04_PreProcess_UI_RouteSamples";
function L(key: keyof typeof ui_locales): string {
return ui_locales[key][currentLanguageIndex];
@@ -1,6 +1,6 @@
import * as THREE from "three";
import type { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import type { SurfaceBounds } from "./B04_wf1_Surface_Api_Fetch";
import type { SurfaceBounds } from "./B04_PreProcess_Api_Fetch";
export const SURFACE_CAMERA_FOV = 50;
const LIGHT_VIEWER_BACKGROUND = 0xf5f7f9;
@@ -12,7 +12,7 @@
* ========================================================================== */
import { themeColor } from "@ui/ui_template_palette";
import { haloColor } from "./B04_wf1_Surface_UI_MapRender";
import { haloColor } from "./B04_PreProcess_UI_MapRender";
/** 화살표 1개 — [가로, 세로, 방위(도), 도로 도달, 셀 수]. 앞 두 값의 좌표계는 호출부가 정한다. */
export type FlowArrow = [number, number, number, boolean, number];
@@ -11,7 +11,7 @@
import "@ui/ui_template_flow_legend.css";
import { currentLanguageIndex, ui_locales } from "@ui/ui_template_locale";
import { themeColor } from "@ui/ui_template_palette";
import type { RoutePoint } from "./B04_wf1_Surface_UI_RouteSamples";
import type { RoutePoint } from "./B04_PreProcess_UI_RouteSamples";
/** 강도 색띠 — 파랑(적음) → 빨강(많음). 정의처는 `ui_template_theme.css`. */
const RAMP_TOKENS: ReadonlyArray<[name: string, fallback: string]> = [
@@ -12,22 +12,22 @@
import { currentLanguageIndex, ui_locales } from "@ui/ui_template_locale";
import { themeColor } from "@ui/ui_template_palette";
import { fetchRoadInflow, type VWorldMeta } from "./B04_wf1_Surface_Api_Fetch";
import { fetchRoadInflow, type VWorldMeta } from "./B04_PreProcess_Api_Fetch";
import {
haloColor,
lonLatToScreen,
metricToScreen,
type Normalizer,
type ViewState,
} from "./B04_wf1_Surface_UI_MapRender";
} from "./B04_PreProcess_UI_MapRender";
import {
buildStrengthArray,
createFlowLegend,
drawStrengthLine,
normalizeStrength,
rampColor,
} from "./B04_wf1_Surface_UI_FlowRamp";
import { pointAtChainage, resampleRoute, type RoutePoint } from "./B04_wf1_Surface_UI_RouteSamples";
} from "./B04_PreProcess_UI_FlowRamp";
import { pointAtChainage, resampleRoute, type RoutePoint } from "./B04_PreProcess_UI_RouteSamples";
function L(key: keyof typeof ui_locales): string {
return ui_locales[key][currentLanguageIndex];
@@ -2,7 +2,7 @@
* 2D ·· (B04)
*
* , , .
* (`B04_wf1_Surface_UI_MapViewer.ts`) 700 .
* (`B04_PreProcess_UI_MapViewer.ts`) 700 .
* `ui_template_theme.css`(`--map-*`) .
* ========================================================================== */
@@ -2,7 +2,7 @@
* 2D (B04 · B05 )
*
* · · · ** ** .
* `B04_wf1_Surface_UI_MapRender.ts` 700
* `B04_PreProcess_UI_MapRender.ts` 700
* .
* ========================================================================== */
@@ -15,7 +15,7 @@ import {
lonLatToScreen,
type Normalizer,
type ViewState,
} from "./B04_wf1_Surface_UI_MapRender";
} from "./B04_PreProcess_UI_MapRender";
export type FilledRing = {
ring: ReadonlyArray<readonly [number, number]>;
@@ -1,5 +1,5 @@
import { themeColor } from "@ui/ui_template_palette";
import type { VWorldMeta } from "./B04_wf1_Surface_Api_Fetch";
import type { VWorldMeta } from "./B04_PreProcess_Api_Fetch";
// 2D 지도 벡터 레이어 렌더 엔진.
// GeoJSON 좌표를 로드 시 1회만 정규화 맵 좌표(0~1)로 사전 투영해 두고,
@@ -7,9 +7,9 @@ import {
fetchVWorldMeta,
getVWorldMapUrl,
type VWorldMeta,
} from "./B04_wf1_Surface_Api_Fetch";
import { niceScaleDistance } from "./B04_wf1_Surface_UI_Camera";
import { createDetailBasinOverlay } from "./B04_wf1_Surface_UI_Basins";
} from "./B04_PreProcess_Api_Fetch";
import { niceScaleDistance } from "./B04_PreProcess_UI_Camera";
import { createDetailBasinOverlay } from "./B04_PreProcess_UI_Basins";
import {
BACKGROUND_DEFAULT_ON,
BACKGROUND_LAYERS,
@@ -21,9 +21,9 @@ import {
gisLayerColor,
type BackgroundLayer,
type GisLayer,
} from "./B04_wf1_Surface_UI_MapLayers";
import { createFlowStrengthOverlay } from "./B04_wf1_Surface_UI_FlowStrength";
import { createWatershedOverlay } from "./B04_wf1_Surface_UI_Watershed";
} from "./B04_PreProcess_UI_MapLayers";
import { createFlowStrengthOverlay } from "./B04_PreProcess_UI_FlowStrength";
import { createWatershedOverlay } from "./B04_PreProcess_UI_Watershed";
import {
computeMapRect,
computeRouteView,
@@ -40,8 +40,8 @@ import {
type PlanBounds,
type PreparedLayer,
type ViewState,
} from "./B04_wf1_Surface_UI_MapRender";
import type { WatershedAnalysis } from "./B04_wf1_Surface_Api_Fetch";
} from "./B04_PreProcess_UI_MapRender";
import type { WatershedAnalysis } from "./B04_PreProcess_Api_Fetch";
export interface SurfaceMapViewer {
root: HTMLElement;
@@ -29,11 +29,11 @@ import {
type SurfaceModelSummary,
type SurfacePointCloudSampleResponse,
type SurfaceStatusResponse,
} from "./B04_wf1_Surface_Api_Fetch";
import { createSurfaceMapViewer } from "./B04_wf1_Surface_UI_MapViewer";
import { createSurfaceTerrainViewer } from "./B04_wf1_Surface_UI_TerrainViewer";
import { createSurfacePointCloudViewer } from "./B04_wf1_Surface_UI_Viewer";
import "./B04_wf1_Surface_UI_Style.css";
} from "./B04_PreProcess_Api_Fetch";
import { createSurfaceMapViewer } from "./B04_PreProcess_UI_MapViewer";
import { createSurfaceTerrainViewer } from "./B04_PreProcess_UI_TerrainViewer";
import { createSurfacePointCloudViewer } from "./B04_PreProcess_UI_Viewer";
import "./B04_PreProcess_UI_Style.css";
const SOURCE_FILTERS = ["grid_min_z", "csf", "pmf"] as const;
const MODEL_METHODS = ["tin", "dtm", "nurbs", "implicit", "meshfree"] as const;
@@ -1,5 +1,5 @@
/* =============================================================================
* B04_wf1_Surface_UI_Style.css
* B04_PreProcess_UI_Style.css
* 1차 워크플로우(지표면 모델 분석) 페이지 전용 스타일.
*
* 원칙(frontend.md §1): 하드코딩 색상 금지. theme.css 변수(var(--...)) 참조.
@@ -6,7 +6,7 @@ import { API_BASE_URL } from "@config/config_frontend";
import { fetchCachedBytes, fetchCachedJson } from "../A00_Common/b_asset_cache";
import { currentLanguageIndex, ui_locales } from "@ui/ui_template_locale";
import { createProgressCircle } from "@ui/ui_template_progress";
import type { SurfaceBounds, SurfaceModelSummary } from "./B04_wf1_Surface_Api_Fetch";
import type { SurfaceBounds, SurfaceModelSummary } from "./B04_PreProcess_Api_Fetch";
import {
bindCursorPivotControls,
bindSurfaceViewerTheme,
@@ -15,7 +15,7 @@ import {
SURFACE_CAMERA_FOV,
targetPlaneMetersPerPixel,
type SurfaceCameraState,
} from "./B04_wf1_Surface_UI_Camera";
} from "./B04_PreProcess_UI_Camera";
function L(key: keyof typeof ui_locales): string {
return ui_locales[key][currentLanguageIndex];
@@ -3,7 +3,7 @@ import { currentLanguageIndex, ui_locales } from "@ui/ui_template_locale";
import { createProgressCircle } from "@ui/ui_template_progress";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import type { SurfaceBounds, SurfacePointCloudSampleResponse } from "./B04_wf1_Surface_Api_Fetch";
import type { SurfaceBounds, SurfacePointCloudSampleResponse } from "./B04_PreProcess_Api_Fetch";
import {
bindCursorPivotControls,
bindSurfaceViewerTheme,
@@ -13,9 +13,9 @@ import {
SURFACE_CAMERA_FOV,
targetPlaneMetersPerPixel,
type SurfaceCameraState,
} from "./B04_wf1_Surface_UI_Camera";
} from "./B04_PreProcess_UI_Camera";
export type { SurfaceCameraState } from "./B04_wf1_Surface_UI_Camera";
export type { SurfaceCameraState } from "./B04_PreProcess_UI_Camera";
function L(key: keyof typeof ui_locales): string {
return ui_locales[key][currentLanguageIndex];
@@ -1,9 +1,9 @@
import { currentLanguageIndex, ui_locales } from "@ui/ui_template_locale";
import { themeColor } from "@ui/ui_template_palette";
import { fetchWatershedAnalysis, type WatershedAnalysis } from "./B04_wf1_Surface_Api_Fetch";
import { drawFlowArrows } from "./B04_wf1_Surface_UI_FlowArrows";
import type { Normalizer, ViewState } from "./B04_wf1_Surface_UI_MapRender";
import { drawUpstreamLines } from "./B04_wf1_Surface_UI_MapOverlays";
import { fetchWatershedAnalysis, type WatershedAnalysis } from "./B04_PreProcess_Api_Fetch";
import { drawFlowArrows } from "./B04_PreProcess_UI_FlowArrows";
import type { Normalizer, ViewState } from "./B04_PreProcess_UI_MapRender";
import { drawUpstreamLines } from "./B04_PreProcess_UI_MapOverlays";
function L(key: keyof typeof ui_locales): string {
return ui_locales[key][currentLanguageIndex];
@@ -34,7 +34,7 @@ from config.config_system import (
logger = logging.getLogger(__name__)
_STAGE_SUBDIR = Path("B06_wf3_ProfileCross")
_MODELS_SUBDIR = Path("B04_wf1_Surface") / "models"
_MODELS_SUBDIR = Path("B04_PreProcess") / "models"
def _load_route_polyline(project_root: Path, route_data_path: str) -> list[list[float]]:
@@ -97,7 +97,7 @@ def _load_pipe_chainages(project_root: Path, polyline: list[list[float]]) -> lis
"""
path = (
project_root
/ "B04_wf1_Surface"
/ "B04_PreProcess"
/ DRAINAGE_CACHE_DIRNAME
/ DRAINAGE_EDITS_DIRNAME
/ DRAINAGE_PIPE_POINTS_FILENAME
+2 -2
View File
@@ -1,6 +1,6 @@
"""B05 최적 경로 탐색 오케스트레이터.
확정된 지표면 모델(B04_wf1_Surface/models) 표고를 DTM 격자에 샘플링해
확정된 지표면 모델(B04_PreProcess/models) 표고를 DTM 격자에 샘플링해
비용면을 만들고(캐시 재사용), BPCPEP 다구간 Dijkstra로 최적 경로를
계산한 평활·측점·곡률·제약검증 메트릭을 반환한다.
"""
@@ -37,7 +37,7 @@ from config.config_system import (
)
# B04 지표면 모델 폴더명 (비용면의 표고 원본)
_MODELS_SUBDIR = Path("B04_wf1_Surface") / "models"
_MODELS_SUBDIR = Path("B04_PreProcess") / "models"
# B05 비용면 캐시 폴더명
_ROUTE_CACHE_SUBDIR = Path("B05_wf2_Route") / "route"
@@ -11,7 +11,7 @@ import {
type DetailBasinResponse,
type PipeSource,
type VWorldMeta,
} from "../B04_wf1_Surface/B04_wf1_Surface_Api_Fetch";
} from "../B04_PreProcess/B04_PreProcess_Api_Fetch";
import {
computeMapRect,
createNormalizer,
@@ -22,14 +22,14 @@ import {
type Normalizer,
type PreparedLayer,
type ViewState,
} from "../B04_wf1_Surface/B04_wf1_Surface_UI_MapRender";
} from "../B04_PreProcess/B04_PreProcess_UI_MapRender";
import { type RoutePoint } from "./B05_wf2_Route_Api_Fetch";
import type { FlowArrow } from "../B04_wf1_Surface/B04_wf1_Surface_UI_FlowArrows";
import type { FlowArrow } from "../B04_PreProcess/B04_PreProcess_UI_FlowArrows";
import {
buildStrengthArray,
createFlowLegend,
} from "../B04_wf1_Surface/B04_wf1_Surface_UI_FlowRamp";
import { resampleRoute } from "../B04_wf1_Surface/B04_wf1_Surface_UI_RouteSamples";
} from "../B04_PreProcess/B04_PreProcess_UI_FlowRamp";
import { resampleRoute } from "../B04_PreProcess/B04_PreProcess_UI_RouteSamples";
import { createPipeEditor } from "./B05_wf2_Route_UI_Drainage_Pipes";
import { createProgressCircle } from "@ui/ui_template_progress";
import { createMapContextMenu } from "@ui/ui_template_context_menu";
@@ -61,7 +61,7 @@ const CLICK_SLOP_PX = 4;
// 배수유역도 패널 — 하단 종단 패널 안쪽 우측에 도킹되는 2단 사이드 패널.
// 하단 패널이 닫히면 이 패널도 함께 화면에서 사라진다(부모 안에 들어 있으므로 자동).
// 지도는 B04에서 분리한 렌더 엔진(B04_wf1_Surface_UI_MapRender)을 그대로 재사용해
// 지도는 B04에서 분리한 렌더 엔진(B04_PreProcess_UI_MapRender)을 그대로 재사용해
// 사전 투영·LOD·뷰포트 컬링·커서 중심 줌 동작을 동일하게 얻는다.
function L(key: keyof typeof ui_locales): string {
@@ -9,16 +9,16 @@
import { currentLanguageIndex, ui_locales } from "@ui/ui_template_locale";
import { themeColor } from "@ui/ui_template_palette";
import { DRAINAGE_SHEET_LAYERS, fetchCachedSheetLayer } from "../A00_Common/b_asset_cache";
import { fetchVWorldMeta, type VWorldMeta } from "../B04_wf1_Surface/B04_wf1_Surface_Api_Fetch";
import { fetchVWorldMeta, type VWorldMeta } from "../B04_PreProcess/B04_PreProcess_Api_Fetch";
import {
computeMapRect,
computeRouteView,
type GeoJsonCollection,
type ViewState,
} from "../B04_wf1_Surface/B04_wf1_Surface_UI_MapRender";
import { normalizeStrength, rampColor } from "../B04_wf1_Surface/B04_wf1_Surface_UI_FlowRamp";
} from "../B04_PreProcess/B04_PreProcess_UI_MapRender";
import { normalizeStrength, rampColor } from "../B04_PreProcess/B04_PreProcess_UI_FlowRamp";
import type { MapContextMenu } from "@ui/ui_template_context_menu";
import type { DetailBasin } from "../B04_wf1_Surface/B04_wf1_Surface_Api_Fetch";
import type { DetailBasin } from "../B04_PreProcess/B04_PreProcess_Api_Fetch";
import type { PipeEditor, PipePoint } from "./B05_wf2_Route_UI_Drainage_Pipes";
function L(key: keyof typeof ui_locales): string {
@@ -1,6 +1,6 @@
import { themeColor } from "@ui/ui_template_palette";
import type { VWorldMeta } from "../B04_wf1_Surface/B04_wf1_Surface_Api_Fetch";
import type { ViewState } from "../B04_wf1_Surface/B04_wf1_Surface_UI_MapRender";
import type { VWorldMeta } from "../B04_PreProcess/B04_PreProcess_Api_Fetch";
import type { ViewState } from "../B04_PreProcess/B04_PreProcess_UI_MapRender";
// 배관(관 매설) 지점 편집기 — 배수유역 패널의 계획선 위 마커 표시·추가·이동·삭제.
// 마커 위치의 단일 소스는 누가거리(chainage)다. 화면 좌표는 매 프레임 노선
@@ -17,18 +17,18 @@ import {
type Normalizer,
type PreparedLayer,
type ViewState,
} from "../B04_wf1_Surface/B04_wf1_Surface_UI_MapRender";
} from "../B04_PreProcess/B04_PreProcess_UI_MapRender";
import {
drawFilledRing,
drawRidgeRing,
drawRingBadge,
drawUpstreamLines,
ringCenterOnScreen,
} from "../B04_wf1_Surface/B04_wf1_Surface_UI_MapOverlays";
import type { DetailBasin, VWorldMeta } from "../B04_wf1_Surface/B04_wf1_Surface_Api_Fetch";
import { drawFlowArrows, type FlowArrow } from "../B04_wf1_Surface/B04_wf1_Surface_UI_FlowArrows";
import { drawStrengthLine } from "../B04_wf1_Surface/B04_wf1_Surface_UI_FlowRamp";
import type { RoutePoint } from "../B04_wf1_Surface/B04_wf1_Surface_UI_RouteSamples";
} from "../B04_PreProcess/B04_PreProcess_UI_MapOverlays";
import type { DetailBasin, VWorldMeta } from "../B04_PreProcess/B04_PreProcess_Api_Fetch";
import { drawFlowArrows, type FlowArrow } from "../B04_PreProcess/B04_PreProcess_UI_FlowArrows";
import { drawStrengthLine } from "../B04_PreProcess/B04_PreProcess_UI_FlowRamp";
import type { RoutePoint } from "../B04_PreProcess/B04_PreProcess_UI_RouteSamples";
import {
basinColor,
createMetricProjector,
+1 -1
View File
@@ -14,7 +14,7 @@ import {
fetchConfirmedSurface,
listSurfaceModels,
type SurfaceModelSummary,
} from "../B04_wf1_Surface/B04_wf1_Surface_Api_Fetch";
} from "../B04_PreProcess/B04_PreProcess_Api_Fetch";
import {
confirmRoute,
fetchLatestRoute,
+1 -1
View File
@@ -4,7 +4,7 @@ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { PLYLoader } from "three/examples/jsm/loaders/PLYLoader.js";
import { API_BASE_URL } from "@config/config_frontend";
import { fetchCachedBytes, fetchCachedJson } from "../A00_Common/b_asset_cache";
import { bindCursorPivotControls } from "../B04_wf1_Surface/B04_wf1_Surface_UI_Camera";
import { bindCursorPivotControls } from "../B04_PreProcess/B04_PreProcess_UI_Camera";
import {
createRouteMarkers,
sceneToModel,
+1 -1
View File
@@ -42,7 +42,7 @@ from config.config_db import get_db_pool
logger = logging.getLogger(__name__)
_INPUT_SUBDIR = Path("B03_FileInput") / "input"
_MODELS_SUBDIR = Path("B04_wf1_Surface") / "models"
_MODELS_SUBDIR = Path("B04_PreProcess") / "models"
@dataclass
+4 -4
View File
@@ -32,10 +32,10 @@ from typing import Any
import numpy as np
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Analyze import find_inflow_hotspots
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Export import STAGES
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Flow import largest_ring, polygonize_labels
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Grid import GridSpec
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Analyze import find_inflow_hotspots
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Export import STAGES
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Flow import largest_ring, polygonize_labels
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Grid import GridSpec
from common_util.common_util_route_geometry import (
RouteVertex,
StructureCandidate,
+1 -1
View File
@@ -19,7 +19,7 @@ from dataclasses import dataclass
from pathlib import Path
from typing import Any
from B04_wf1_Surface.B04_wf1_Surface_Engine_Watershed_Export import drainage_dir
from B04_PreProcess.B04_PreProcess_Engine_Watershed_Export import drainage_dir
from common_util.common_util_json import atomic_write_json
from common_util.common_util_route_geometry import RouteVertex
from config.config_system import (
+2 -2
View File
@@ -7,8 +7,8 @@ from config.config_system import PROJECT_STORAGE_STAGE_DIRS, STORAGE_BASE_DIR
PROJECT_STORAGE_LAYOUT_V2 = (
("B03_FileInput", "input"),
("B04_wf1_Surface", "processed"),
("B04_wf1_Surface", "models"),
("B04_PreProcess", "processed"),
("B04_PreProcess", "models"),
("B05_wf2_Route", "route"),
("B06_wf3_ProfileCross", "longitudinal"),
("B06_wf3_ProfileCross", "cross_sections"),
+1 -1
View File
@@ -1,7 +1,7 @@
"""확정 지표면 모델 표고 sampler (공용).
·횡단 생성기가 의존하는 최소 표고 조회 인터페이스와, 확정된 지표면 모델
(B04_wf1_Surface/models) 일괄 XY 표고 sampler로 여는 팩토리를 제공한다.
(B04_PreProcess/models) 일괄 XY 표고 sampler로 여는 팩토리를 제공한다.
DTM valid_mask를 footprint로 결합해 데이터가 없는 영역을 임의 표고로 메우지
않는다.
+2 -2
View File
@@ -84,7 +84,7 @@ export const ROUTES = {
B01_ACCOUNT: "b01-account",
B02_PROJ_REGISTER: "b02-proj-register",
B03_FILE_INPUT: "b03-file-input",
B04_WF1_SURFACE: "b04-wf1-surface",
B04_PREPROCESS: "b04-preprocess",
B05_WF2_ROUTE: "b05-wf2-route",
B06_WF3_PROFILE_CROSS: "b06-wf3-profile-cross",
B07_WF4_DESIGN_DETAIL: "b07-wf4-design-detail",
@@ -107,7 +107,7 @@ export const PROTECTED_ROUTES: readonly RoutePath[] = [
ROUTES.B01_ACCOUNT,
ROUTES.B02_PROJ_REGISTER,
ROUTES.B03_FILE_INPUT,
ROUTES.B04_WF1_SURFACE,
ROUTES.B04_PREPROCESS,
ROUTES.B05_WF2_ROUTE,
ROUTES.B06_WF3_PROFILE_CROSS,
ROUTES.B07_WF4_DESIGN_DETAIL,
+3 -3
View File
@@ -289,7 +289,7 @@ DRAINAGE_DITCH_SAMPLE_M = float(os.getenv("DRAINAGE_DITCH_SAMPLE_M", "1.0"))
DRAINAGE_POLYGON_SIMPLIFY_M = float(os.getenv("DRAINAGE_POLYGON_SIMPLIFY_M", "2.0"))
# 이 면적(㎡) 미만의 유역 조각은 버린다(격자 노이즈 제거).
DRAINAGE_MIN_BASIN_AREA_M2 = float(os.getenv("DRAINAGE_MIN_BASIN_AREA_M2", "100.0"))
# 격자 해석 결과 캐시 파일명. 프로젝트 저장소의 B04_wf1_Surface/drainage/ 아래에 놓인다.
# 격자 해석 결과 캐시 파일명. 프로젝트 저장소의 B04_PreProcess/drainage/ 아래에 놓인다.
DRAINAGE_CACHE_DIRNAME = "drainage"
DRAINAGE_CACHE_FILENAME = "watershed_grid.npz"
# 분석 응답 자체를 그대로 담아 두는 파일. 재산정하지 않는 한 이걸 그대로 돌려준다 —
@@ -660,7 +660,7 @@ FOREST_ROAD_PROFILE_ALIGNMENT = {
STORAGE_BASE_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), "storage")
# 1:5,000 수치지형도 도엽 저장 폴더명 — 프로젝트 영구저장소 하위
# (storage/{회사}/{사용자}/{프로젝트ID}/B04_wf1_Surface/processed/map_sheets/)
# (storage/{회사}/{사용자}/{프로젝트ID}/B04_PreProcess/processed/map_sheets/)
MAP_SHEETS_DIRNAME = "map_sheets"
MAP_SHEETS_INDEX_FILENAME = "map_sheets_index.json"
@@ -687,7 +687,7 @@ RESOURCE_LOG_RETENTION_DAYS = 30 # 로그 보관: 1개월
PROJECT_STORAGE_STAGE_DIRS = frozenset(
{
"B03_FileInput",
"B04_wf1_Surface",
"B04_PreProcess",
"B05_wf2_Route",
"B06_wf3_ProfileCross",
"B07_wf4_DesignDetail",
+4 -4
View File
@@ -227,9 +227,9 @@ CREATE TABLE IF NOT EXISTS processed_point_cloud (
input_file_id INT NOT NULL, -- FK는 later
project_id CHAR(36) NOT NULL, -- FK는 later
process_type VARCHAR(50), -- filtered, sampled, classified
processed_file_path VARCHAR(500), -- storage/.../B04_wf1_Surface/processed/...
processed_file_path VARCHAR(500), -- storage/.../B04_PreProcess/processed/...
converted_format VARCHAR(50), -- ply, laz, las 등
converted_file_path VARCHAR(500), -- storage/.../B04_wf1_Surface/processed/...
converted_file_path VARCHAR(500), -- storage/.../B04_PreProcess/processed/...
point_count INT,
min_z FLOAT,
max_z FLOAT,
@@ -258,7 +258,7 @@ CREATE TABLE IF NOT EXISTS surface_models (
status VARCHAR(50) DEFAULT 'PROCESSING', -- PROCESSING, COMPLETE, CONFIRMED, FAILED
crs_epsg INT,
resolution_m FLOAT,
model_file_path VARCHAR(500), -- storage/.../B04_wf1_Surface/models/...
model_file_path VARCHAR(500), -- storage/.../B04_PreProcess/models/...
generation_params JSON, -- filter_type, algorithm, params
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
completed_at TIMESTAMP NULL DEFAULT NULL
@@ -270,7 +270,7 @@ CREATE TABLE IF NOT EXISTS terrain_layers (
surface_model_id INT NOT NULL, -- FK는 later
layer_name VARCHAR(100), -- 지표, 제1층, 제2층
geometry_type VARCHAR(50), -- POINTCLOUD, GRID, MESH, CONTOUR
layer_file_path VARCHAR(500), -- storage/.../B04_wf1_Surface/models/...
layer_file_path VARCHAR(500), -- storage/.../B04_PreProcess/models/...
file_format VARCHAR(50), -- geojson, geotiff, ply, obj
file_size_mb FLOAT,
statistics JSON, -- min_z, max_z, mean_slope, point_count
+7 -7
View File
@@ -28,13 +28,13 @@ from A09_Security.A09_Security_Router import router as a09_security_router
from B01_Dashboard.B01_Dashboard_Router import router as b01_dashboard_router
from B02_ProjRegister.B02_ProjRegister_Router import router as b02_proj_register_router
from B03_FileInput.B03_FileInput_Router import router as b03_file_input_router
from B04_wf1_Surface.B04_wf1_Surface_Router import router as b04_surface_router
from B04_wf1_Surface.B04_wf1_Surface_Router_Basins import router as b04_basins_router
from B04_wf1_Surface.B04_wf1_Surface_Router_Contour import router as b04_surface_contour_router
from B04_wf1_Surface.B04_wf1_Surface_Router_GIS import router as b04_surface_gis_router
from B04_wf1_Surface.B04_wf1_Surface_Router_GIS import tiles_router
from B04_wf1_Surface.B04_wf1_Surface_Router_Inflow import router as b04_inflow_router
from B04_wf1_Surface.B04_wf1_Surface_Router_Watershed import router as b04_watershed_router
from B04_PreProcess.B04_PreProcess_Router import router as b04_surface_router
from B04_PreProcess.B04_PreProcess_Router_Basins import router as b04_basins_router
from B04_PreProcess.B04_PreProcess_Router_Contour import router as b04_surface_contour_router
from B04_PreProcess.B04_PreProcess_Router_GIS import router as b04_surface_gis_router
from B04_PreProcess.B04_PreProcess_Router_GIS import tiles_router
from B04_PreProcess.B04_PreProcess_Router_Inflow import router as b04_inflow_router
from B04_PreProcess.B04_PreProcess_Router_Watershed import router as b04_watershed_router
from B05_wf2_Route.B05_wf2_Route_Router import router as b05_route_router
from B06_wf3_ProfileCross.B06_wf3_ProfileCross_Router import router as b06_section_router
from B06_wf3_ProfileCross.B06_wf3_ProfileCross_Router_Confirm import (
+1 -1
View File
@@ -16,7 +16,7 @@ sys.path.insert(0, str(PROJECT_ROOT))
import geopandas as gpd
from B04_wf1_Surface.B04_wf1_Surface_Engine_MapSheet import (
from B04_PreProcess.B04_PreProcess_Engine_MapSheet import (
latlon_to_sheet5k,
neighbors_3x3,
sheet5k_center,
+3 -3
View File
@@ -1,6 +1,6 @@
"""도엽 프로젝트 영구저장소(SheetStore) 실테스트.
- 저장 위치: {프로젝트 저장소}/B04_wf1_Surface/processed/map_sheets/
- 저장 위치: {프로젝트 저장소}/B04_PreProcess/processed/map_sheets/
- ensure_sheets: 보유 도엽은 즉시 반환, 미보유는 자동 다운로드(세션 만료 자동 재로그인)
"""
@@ -10,8 +10,8 @@ from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(PROJECT_ROOT))
from B04_wf1_Surface.B04_wf1_Surface_Engine_MapSheet import neighbors_3x3
from B04_wf1_Surface.B04_wf1_Surface_Engine_SheetStore import (
from B04_PreProcess.B04_PreProcess_Engine_MapSheet import neighbors_3x3
from B04_PreProcess.B04_PreProcess_Engine_SheetStore import (
ensure_sheets,
get_project_map_sheets_dir,
get_sheet_path,
+4 -4
View File
@@ -7,12 +7,12 @@ import numpy as np
PROJECT_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(PROJECT_ROOT))
from B04_wf1_Surface.B04_wf1_Surface_Engine_VWorld import download_vworld_satellite_map
from B04_wf1_Surface.B04_wf1_Surface_Engine_GisVector import download_all_gis_vectors
from B04_PreProcess.B04_PreProcess_Engine_VWorld import download_vworld_satellite_map
from B04_PreProcess.B04_PreProcess_Engine_GisVector import download_all_gis_vectors
PRJ_PATH = PROJECT_ROOT / "storage/1/3/acb9170b-9ac8-49b3-82a0-51cfa32bb42d/B03_FileInput/input/prj/result.prj"
NPZ_PATH = PROJECT_ROOT / "storage/1/3/acb9170b-9ac8-49b3-82a0-51cfa32bb42d/B04_wf1_Surface/processed/ground_points_csf.npz"
OUTPUT_DIR = PROJECT_ROOT / "storage/1/3/acb9170b-9ac8-49b3-82a0-51cfa32bb42d/B04_wf1_Surface/processed"
NPZ_PATH = PROJECT_ROOT / "storage/1/3/acb9170b-9ac8-49b3-82a0-51cfa32bb42d/B04_PreProcess/processed/ground_points_csf.npz"
OUTPUT_DIR = PROJECT_ROOT / "storage/1/3/acb9170b-9ac8-49b3-82a0-51cfa32bb42d/B04_PreProcess/processed"
def main():
print("Loading NPZ to get bounds...")
+2 -2
View File
@@ -1,6 +1,6 @@
/* =============================================================================
* ui_template_locale_b1.ts
* B (B01_Dashboard ~ B04_wf1_Surface)
* B (B01_Dashboard ~ B04_PreProcess)
*
* ui_template_locale_common.ts WF_Step_*
* ( ).
@@ -265,7 +265,7 @@ export const ui_locales_b1 = {
"Background upload is unavailable in this browser.",
],
/* --- B04_wf1_Surface 지표면 모델 분석 --- */
/* --- B04_PreProcess 지표면 모델 분석 --- */
B04_Surface_Title: ["전처리", "Preprocess"],
B04_Surface_Field_InputId: ["입력 파일 ID", "Input File ID"],
B04_Surface_Field_InputId_Placeholder: ["예: 1", "e.g. 1"],