Files
Aislo/config/config_system_terrain.py
T
eomsangdonandClaude Opus 5.5 11c75f022a refactor(767-1): 안 쓰는 지면 필터 · 서피스 지움 — 필터 넷(CSF · 격자 최저 · PMF · RANSAC) · 표현 셋(TIN + Taubin 평활 · NURBS · meshfree) · 수치지형도 비교 방식 다섯 · 안 부르는 길 정리
- 필터 = 업체 분류 · 점진 TIN · 둘의 다듬기 판만 · 분석 허용 목록 = Ground 등록부(available_filters) 한 벌
- 표현 = DTM · implicit 만 · 평활 = DTM 만 · config 기본 목록 · PRECOMPUTE · 설정 사전 맞춤(설정 지문 바뀜 — 768 에서 다시 지음)
- 등고선 = 격자 · 굳힌 격자만(삼각망 굽기 · 외곽 맞춤 · implicit RBF 폴백 걷음) · 표본기 · 경로 찾기 tin · nurbs · meshfree 갈래 걷음
- 수치지형도 = 라플라스만(TIN 둘 · TPS · ANUDEM형 · 다중해상도 걷음) · B04 단추 하나
- 안 부르는 길 — B04 JSON 점군 GET · ground-stats GET + TS · B07 옛 계획평면도(라이다) 짓기 · lidar_source · LIDAR_ID · plan_lidar 종류 이름 · SOURCE_FILTER_LABELS · MODEL_METHODS(py) · MESH_* 설정
- 옛 manifest 의 지운 갈래 줄은 DB 로 되살리지 않음 · 옛 csf 행은 미리보기 · 등고선 그대로 열림 · 지운 이름 요청 = 400
- 낡은 글 — Ground · Pipeline 머리 · WF1 「없으면 csf」 · B07 음영 기본 「csf」 → 빈 값 · 등고선 폴백 「csf」 → 404 · B04 3D 보기 처음값 · B05 Schema · B06 Prebuild · 씨닝 설명
- 시험 지움 2 — test_b04_contour_raster · test_b04_contour_equivalence(지운 삼각망 굽기 · 없는 프로젝트를 봐 건너뛰던 것)
- 시험 덜어냄 — test_b04_ground_filters CSF · 격자 최저 네 경우(지운 필터)
- 시험 고침 — 허용 목록 · 형 검사에 걸린 csf · tin · grid_min_z · meshfree · tin_sheet 견본을 ptd · implicit · laplace 로(54_22 · 238_1 · 443 · 342_2 · 346_3 · 351_1 · 442_2 · 271 + helper · 344_1 · 133_1 · 343_2 · 637 · 754_1 · 763_1 깨진 tin → 깨진 implicit · 763_3 · b05 둘 · b06 · sheet_surface TIN(도엽선) 경우 지움) · 이름만 바꿈(273_2 · 343_1 · 343_3 · 624_1)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 16:35:12 +09:00

175 lines
12 KiB
Python

"""지형 분석·지표면 모델 생성 파라미터 (5장·5-2장).
`config_system.py` 가 700줄을 넘어 떼어냈다(2026-09-04). 값·이름은 그대로이고,
`config_system` 이 다시 내보내므로 기존 `from config.config_system import …` 는 불변이다.
"""
import os
# 5. 지형 분석 알고리즘 파라미터
# ─────────────────────────────────────────────────────────────────────────
SURFACE_LAS_CHUNK_SIZE = int(os.getenv("SURFACE_LAS_CHUNK_SIZE", "500000"))
SURFACE_DEFAULT_RGB_VALUE = int(os.getenv("SURFACE_DEFAULT_RGB_VALUE", "128"))
# 지형 파일 여러 장 병합 (2026-09-06 사용자 확정)
# ─────────────────────────────────────────────────────────────────────────
# 다른 사업지 파일이 섞여 들어오면 합친 범위가 통째로 어긋난다 — 어느 파일과도 이
# 거리 안에서 만나지 않는 파일은 업로드에서 막는다. 임도는 길어도 2~3km 라 5km 면
# 넉넉하다(2026-09-06 사용자 확정). 도엽이 나뉜 자료는 경계가 맞닿아 걸리지 않는다.
SURFACE_MERGE_MAX_GAP_M = float(os.getenv("SURFACE_MERGE_MAX_GAP_M", "5000"))
# 점이 이 수를 넘으면 아래 칸 크기로 씨닝한다(칸마다 최저점 하나). 넘지 않으면 원본
# 그대로 쓴다 — 작은 자료의 결과는 바뀌지 않는다. 1억점 = 메모리 약 3.2GB.
SURFACE_THIN_TRIGGER_POINTS = int(os.getenv("SURFACE_THIN_TRIGGER_POINTS", "100000000"))
# 씨닝 칸 크기(m). 설계 격자 1m·다듬기 칸 1m 보다 촘촘해야 결과가 안 변한다.
SURFACE_THIN_CELL_SIZE_M = float(os.getenv("SURFACE_THIN_CELL_SIZE_M", "0.5"))
# 씨닝 격자가 이보다 많아지면 범위가 비정상이다(먼 파일이 섞였거나 좌표계 불일치).
SURFACE_THIN_MAX_CELLS = int(os.getenv("SURFACE_THIN_MAX_CELLS", "400000000"))
# 점진 TIN(PTD) 지면 분류 — 장면 flat · gentle · steep(각 · 거리 묶음) · 시작 간격(씨앗 칸)
# 시작 간격 = 숲 10 m(DJI 기본 20 m 는 급한 볼록 비탈을 못 따라감)
SURFACE_PTD_SCENE = os.getenv("SURFACE_PTD_SCENE", "steep")
SURFACE_PTD_SEED_SPACING_M = float(os.getenv("SURFACE_PTD_SEED_SPACING_M", "10.0"))
# LAS 자체 지면분류(class 2) 필터 — 이 비율 이상 분류돼 있을 때만 필터로 제공한다.
# 미분류 LAS는 classification이 전부 0이라 마스크가 비어 버린다.
SURFACE_CLASSIFIED_GROUND_MIN_RATIO = float(
os.getenv("SURFACE_CLASSIFIED_GROUND_MIN_RATIO", "0.002")
)
# 자동 기본 고름만 — 점 있는 칸(한 변 아래 m) 중 class 2 가 있는 칸이 이 비율 이상이어야 분류 있음.
SURFACE_CLASSIFIED_COVERAGE_CELL_M = float(os.getenv("SURFACE_CLASSIFIED_COVERAGE_CELL_M", "10.0"))
SURFACE_CLASSIFIED_COVERAGE_MIN_RATIO = float(
os.getenv("SURFACE_CLASSIFIED_COVERAGE_MIN_RATIO", "0.5")
)
# 지면점 비율이 이 값 미만이면 필터가 사실상 실패한 것으로 보고 WARNING을 남긴다.
SURFACE_GROUND_RATIO_WARN = float(os.getenv("SURFACE_GROUND_RATIO_WARN", "0.01"))
# 계획노선이 지표면 밖으로 나가 잘릴 때, 잘린 쪽 끝에서 더 깎을 길이(m).
# 서피스 가장자리는 점 밀도가 떨어져 외곽선이 불규칙하다 — 경계에 딱 붙여 자르면
# 그 구간 지반고가 못 미덥다 (2026-09-01 사용자 확정).
# 30m 는 너무 많이 깎는다는 지적으로 3m 로 낮춤 (2026-09-04 사용자 지시).
SURFACE_ROUTE_EDGE_TRIM_M = float(os.getenv("SURFACE_ROUTE_EDGE_TRIM_M", "3.0"))
# ─────────────────────────────────────────────────────────────────────────
# 5-2. 지표면 모델 생성 파라미터 (DTM/implicit)
# ─────────────────────────────────────────────────────────────────────────
# 고를 수 있는 지면 필터 전체 — 관리자가 B04 드롭다운에서 요청할 때 쓰인다.
# 자동 전처리가 미리 만드는 조합이 아니다(그건 SURFACE_AUTO_* 가 정한다).
SURFACE_MODEL_SOURCE_FILTERS = tuple(
os.getenv("SURFACE_MODEL_SOURCE_FILTERS", "classification,ptd").split(",")
)
# 자동 전처리가 만드는 조합 — 기본 필터 1종 × 아래 표현. 나머지는 관리자 요청 시 만든다.
SURFACE_AUTO_METHODS = tuple(os.getenv("SURFACE_AUTO_METHODS", "dtm").split(","))
# 기본 필터는 입력 LAS를 보고 정한다 — 지면분류(class 2)가 있으면 그것을, 없으면 아래 값.
SURFACE_AUTO_FALLBACK_FILTER = os.getenv("SURFACE_AUTO_FALLBACK_FILTER", "ptd")
# 자동 전처리 · 확정 기본은 이 필터의 다듬기 판(`_refine`) — 요구 607.
# 다듬기(SMRF 꼴) — 칸 · 물체 기울기(rise/run · PDAL 0.15 는 급경사 능선을 깎아 0.3) · 최대 창 ·
# 판정 문턱 · 기울기 배수 · 낮은 잡점 기울기 — 나머지는 PDAL 기본.
SURFACE_REFINE_CELL_M = float(os.getenv("SURFACE_REFINE_CELL_M", "1.0"))
SURFACE_REFINE_SLOPE = float(os.getenv("SURFACE_REFINE_SLOPE", "0.3"))
SURFACE_REFINE_WINDOW_M = float(os.getenv("SURFACE_REFINE_WINDOW_M", "18.0"))
SURFACE_REFINE_THRESHOLD_M = float(os.getenv("SURFACE_REFINE_THRESHOLD_M", "0.5"))
SURFACE_REFINE_SCALAR = float(os.getenv("SURFACE_REFINE_SCALAR", "1.25"))
SURFACE_REFINE_LOW_SLOPE = float(os.getenv("SURFACE_REFINE_LOW_SLOPE", "5.0"))
# dtm 먼저 — implicit 이 dtm 메운 칸을 길잡이로 씀(766-2)
SURFACE_MODEL_PRECOMPUTE = tuple(os.getenv("SURFACE_MODEL_PRECOMPUTE", "dtm,implicit").split(","))
SURFACE_MODEL_SMOOTHING_METHODS = tuple(
os.getenv("SURFACE_MODEL_SMOOTHING_METHODS", "dtm").split(",")
)
SURFACE_MODEL_SYNC_TIMEOUT_SECONDS = int(os.getenv("SURFACE_MODEL_SYNC_TIMEOUT_SECONDS", "0"))
# footprint(외곽) 산출
SURFACE_FOOTPRINT_RESOLUTION_M = float(os.getenv("SURFACE_FOOTPRINT_RESOLUTION_M", "1.0"))
# 외곽 틈 닫기 3 m — DJI 지면점이 성긴 숲 띠까지 스캔 범위로 살림(요구 558).
SURFACE_FOOTPRINT_GAP_CLOSE_M = float(os.getenv("SURFACE_FOOTPRINT_GAP_CLOSE_M", "3.0"))
SURFACE_BOUNDARY_INSET_M = float(os.getenv("SURFACE_BOUNDARY_INSET_M", "1.0"))
SURFACE_KEEP_LARGEST_FOOTPRINT = (
os.getenv("SURFACE_KEEP_LARGEST_FOOTPRINT", "True").lower() == "true"
)
SURFACE_TILE_SIZE_M = float(os.getenv("SURFACE_TILE_SIZE_M", "50.0"))
SURFACE_MAX_PREVIEW_VERTICES = int(os.getenv("SURFACE_MAX_PREVIEW_VERTICES", "500000"))
# 표현별 파라미터 (old 버전 검증값 기준 — PLAN F)
SURFACE_DTM_GRID_RESOLUTION_M = float(os.getenv("SURFACE_DTM_GRID_RESOLUTION_M", "1.0"))
# implicit 중심점 수 = clip(지면점 × 비율, 하한, 상한) · 지면점이 하한보다 적으면 전부(요구 558).
SURFACE_IMPLICIT_POINT_RATIO = float(os.getenv("SURFACE_IMPLICIT_POINT_RATIO", "0.175"))
SURFACE_IMPLICIT_MIN_POINTS = int(os.getenv("SURFACE_IMPLICIT_MIN_POINTS", "50000"))
SURFACE_IMPLICIT_MAX_POINTS = int(os.getenv("SURFACE_IMPLICIT_MAX_POINTS", "2000000"))
SURFACE_IMPLICIT_SMOOTHING = float(os.getenv("SURFACE_IMPLICIT_SMOOTHING", "0.1"))
# 스무딩 파라미터
SURFACE_SMOOTHING_DTM_SIGMA_M = float(os.getenv("SURFACE_SMOOTHING_DTM_SIGMA_M", "0.5"))
SURFACE_SMOOTHING_DTM_SPLINE_SMOOTH = float(os.getenv("SURFACE_SMOOTHING_DTM_SPLINE_SMOOTH", "0.0"))
SURFACE_SMOOTHING_DTM_PREVIEW_RESOLUTION_M = float(
os.getenv("SURFACE_SMOOTHING_DTM_PREVIEW_RESOLUTION_M", "0.5")
)
# 등고선 파라미터
SURFACE_CONTOUR_INTERVAL_M = float(os.getenv("SURFACE_CONTOUR_INTERVAL_M", "1.0"))
SURFACE_CONTOUR_GRID_RESOLUTION_M = float(os.getenv("SURFACE_CONTOUR_GRID_RESOLUTION_M", "1.0"))
# 도엽등고선 3D 서피스 (LAS 없는 설계 — 2026-08-30 사용자 확정)
# 노선 XY bbox에 더하는 절취 여유(m). 300m = 횡단·코리도·성토면 여유(사용자 확정값).
SHEET_SURFACE_MARGIN_M = float(os.getenv("SHEET_SURFACE_MARGIN_M", "300.0"))
# 도엽등고선 DTM 격자 한 변(m). LAS DTM·등고선 캐시와 같은 1m(사용자 확정값).
SHEET_SURFACE_GRID_M = float(os.getenv("SHEET_SURFACE_GRID_M", "1.0"))
# D 예정노선 지형 격자(m) — 길이 · 원지반 기울기를 대충 보는 계획 단계라 2m(B 는 위 1m 그대로).
PLAN_TERRAIN_GRID_M = float(os.getenv("PLAN_TERRAIN_GRID_M", "2.0"))
# 위성 조각 저장본 한도(590-2 · 요구 453 사용자 확정) — 프로젝트당 MB · 넘으면 오래 안 본 것부터 지움.
PLAN_TILE_CACHE_MB = float(os.getenv("PLAN_TILE_CACHE_MB", "150"))
# 만들어 둘 등고선 보간 방식 — B04 화면에서 버튼으로 바꿔 가며 비교한다
# (2026-08-30 사용자 지시). 정의는 B04_PreProcess_Engine_SheetMethods.py.
SHEET_SURFACE_METHODS = [
method.strip()
for method in os.getenv(
"SHEET_SURFACE_METHODS",
"laplace",
).split(",")
if method.strip()
]
# 확정에 쓸 기본 방식 — 라플라스 (2026-08-30 사용자 확정).
SHEET_SURFACE_DEFAULT_METHOD = os.getenv("SHEET_SURFACE_DEFAULT_METHOD", "laplace")
# 자동 전처리가 만드는 도엽 방식 — 기본 하나뿐이다. 여섯 방식을 매번 다 만들면
# WF1의 대부분(용화 실측 891초 중 655초)을 여기서 쓴다. 나머지는 관리자가 B04에서
# 그 방식을 고를 때 만든다 (2026-09-01 사용자 확정).
SHEET_SURFACE_AUTO_METHODS = [
method.strip()
for method in os.getenv("SHEET_SURFACE_AUTO_METHODS", SHEET_SURFACE_DEFAULT_METHOD).split(",")
if method.strip()
]
# 일반 사용자 WF1 자동 확정 기본값
SURFACE_CONFIRM_DEFAULT_FILTER = os.getenv("SURFACE_CONFIRM_DEFAULT_FILTER", "ptd_refine")
# 확정 표현 = implicit · 평활 끔 — WF1 자동 짓기도 이 표현을 기본 필터에 지음(요구 558).
SURFACE_CONFIRM_DEFAULT_METHOD = os.getenv("SURFACE_CONFIRM_DEFAULT_METHOD", "implicit")
SURFACE_CONFIRM_DEFAULT_SMOOTH = (
os.getenv("SURFACE_CONFIRM_DEFAULT_SMOOTH", "False").lower() == "true"
)
def build_surface_model_config() -> dict:
"""지표면 모델 파이프라인이 사용하는 config dict를 조립한다."""
return {
"source_filters": list(SURFACE_MODEL_SOURCE_FILTERS),
"precompute": list(SURFACE_MODEL_PRECOMPUTE),
"smoothing_methods": tuple(SURFACE_MODEL_SMOOTHING_METHODS),
"sync_timeout_seconds": SURFACE_MODEL_SYNC_TIMEOUT_SECONDS,
"footprint_resolution_meters": SURFACE_FOOTPRINT_RESOLUTION_M,
"footprint_gap_close_meters": SURFACE_FOOTPRINT_GAP_CLOSE_M,
"boundary_inset_meters": SURFACE_BOUNDARY_INSET_M,
"keep_largest_footprint": SURFACE_KEEP_LARGEST_FOOTPRINT,
# 외곽 안 큰 구멍 메움 방식(766-2) — 바뀌면 모델 지문이 달라져 다시 지음
"hole_fill": "laplace",
"tile_size_meters": SURFACE_TILE_SIZE_M,
"max_preview_vertices": SURFACE_MAX_PREVIEW_VERTICES,
"dtm_grid_resolution_meters": SURFACE_DTM_GRID_RESOLUTION_M,
"implicit_point_ratio": SURFACE_IMPLICIT_POINT_RATIO,
"implicit_min_points": SURFACE_IMPLICIT_MIN_POINTS,
"implicit_max_points": SURFACE_IMPLICIT_MAX_POINTS,
"implicit_smoothing": SURFACE_IMPLICIT_SMOOTHING,
"smoothing_dtm_sigma_meters": SURFACE_SMOOTHING_DTM_SIGMA_M,
"smoothing_dtm_spline_smooth": SURFACE_SMOOTHING_DTM_SPLINE_SMOOTH,
"smoothing_dtm_preview_resolution_meters": SURFACE_SMOOTHING_DTM_PREVIEW_RESOLUTION_M,
"contour_interval_meters": SURFACE_CONTOUR_INTERVAL_M,
"contour_grid_resolution_meters": SURFACE_CONTOUR_GRID_RESOLUTION_M,
}