feat(B03/B04): LAS 없이 도엽등고선으로 3D 서피스를 만들어 설계한다
- B03: 'LAS 없이 설계' 토글 — LAS 필수카드 비활성화, las_free 플래그로
업로드·완료 검증 면제, 계획노선 CSV를 WF1 분석 입력으로 사용
- B04: 신규 Engine_SheetSurface — 도엽_등고선.geojson을 노선 bbox+300m
직사각형으로 절취, 배수유역 엔진의 등고선 정점구름·Delaunay TIN 보간을
재사용해 dtm_sheet.npz(1m 격자, LAS DTM과 동일 형식) + 프리뷰 glb 생성.
build_surface_sampler('sheet','dtm')로 종·횡단·배수 하류 계산 무수정 동작
- WF1: las_free면 run_sheet_surface_analysis로 분기, sheet/dtm 자동 확정.
VWorld·도엽 확보 블록을 download_geodata()로 추출해 두 경로가 공유
- LAS가 있어도 도엽 서피스를 함께 생성·등록(참고용), B04에
'도엽등고 3D 서피스' 별도 컨테이너로 표시
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,7 @@ from config.config_db import get_db_pool
|
||||
from config.config_system import (
|
||||
AUTO_DESIGN_CHAIN_ENABLED,
|
||||
SEND_ANALYSIS_COMPLETION_EMAIL,
|
||||
SURFACE_CONTOUR_INTERVAL_M,
|
||||
SURFACE_MODEL_PRECOMPUTE,
|
||||
SURFACE_MODEL_SOURCE_FILTERS,
|
||||
)
|
||||
@@ -79,9 +80,15 @@ async def trigger_wf1_analysis_and_email(
|
||||
input_file = await get_input_file(connection, project_id, input_file_id)
|
||||
|
||||
project_root = Path(resolve_stored_project_path(stored_path))
|
||||
las_path = project_root / Path(str(input_file["raw_file_path"]))
|
||||
if not las_path.is_file():
|
||||
raise FileNotFoundError("원본 LAS/LAZ 파일을 찾을 수 없습니다.")
|
||||
source_path = project_root / Path(str(input_file["raw_file_path"]))
|
||||
# LAS 없는 설계(2026-08-30): 입력이 계획노선 CSV면 도엽등고선 서피스 분석으로 간다.
|
||||
las_free = str(input_file.get("file_type") or "").lower() not in {"las", "laz"}
|
||||
if not source_path.is_file():
|
||||
raise FileNotFoundError(
|
||||
"계획 노선 파일을 찾을 수 없습니다."
|
||||
if las_free
|
||||
else "원본 LAS/LAZ 파일을 찾을 수 없습니다."
|
||||
)
|
||||
|
||||
from B04_PreProcess.B04_PreProcess_Engine import run_surface_analysis
|
||||
from B04_PreProcess.B04_PreProcess_Repository import save_surface_analysis_to_db
|
||||
@@ -92,15 +99,27 @@ async def trigger_wf1_analysis_and_email(
|
||||
def _on_progress(percent: int, stage: str, message: str) -> None:
|
||||
write_surface_progress(project_root, percent, stage, message)
|
||||
|
||||
analysis_result = await asyncio.to_thread(
|
||||
run_surface_analysis,
|
||||
project_root,
|
||||
las_path,
|
||||
source_filters=source_filters,
|
||||
methods=methods,
|
||||
force=False,
|
||||
on_progress=_on_progress,
|
||||
)
|
||||
if las_free:
|
||||
from B04_PreProcess.B04_PreProcess_Engine_SheetSurface import (
|
||||
run_sheet_surface_analysis,
|
||||
)
|
||||
|
||||
analysis_result = await asyncio.to_thread(
|
||||
run_sheet_surface_analysis,
|
||||
project_root,
|
||||
source_path,
|
||||
on_progress=_on_progress,
|
||||
)
|
||||
else:
|
||||
analysis_result = await asyncio.to_thread(
|
||||
run_surface_analysis,
|
||||
project_root,
|
||||
source_path,
|
||||
source_filters=source_filters,
|
||||
methods=methods,
|
||||
force=False,
|
||||
on_progress=_on_progress,
|
||||
)
|
||||
|
||||
auto_confirmation_error: str | None = None
|
||||
auto_confirmed = False
|
||||
@@ -124,7 +143,17 @@ async def trigger_wf1_analysis_and_email(
|
||||
find_surface_model_for_selection,
|
||||
)
|
||||
|
||||
selection = surface_confirmation_defaults()
|
||||
# LAS 없는 설계는 도엽 서피스 모델(sheet/dtm)로 확정한다.
|
||||
selection = (
|
||||
{
|
||||
"source_filter": "sheet",
|
||||
"method": "dtm",
|
||||
"smooth": False,
|
||||
"contour_interval_m": SURFACE_CONTOUR_INTERVAL_M,
|
||||
}
|
||||
if las_free
|
||||
else surface_confirmation_defaults()
|
||||
)
|
||||
try:
|
||||
model_id = await find_surface_model_for_selection(
|
||||
connection, project_id, selection
|
||||
|
||||
Reference in New Issue
Block a user