revert(B04): 도엽 서피스 프리뷰 메시의 NURBS 곡면 적합을 되돌린다
DTM 스무딩(184296f5)이 표고 정본(npz)에서 이미 가우시안+B-spline을 걸므로 프리뷰에서 다시 NURBS를 적합하면 곡면 적합이 이중으로 걸린다.c2060f3b이전의 격자 메시로 되돌리고, 쓰지 않게 된 NURBS import를 지운다. 검증: 프리뷰 glb 정점 표고 = npz 격자 표고 (|차이| 최대 0.0000m, distance 원본·스무딩 각 161,280정점).
This commit is contained in:
@@ -27,8 +27,6 @@ from pyproj import Transformer
|
||||
from B04_PreProcess.B04_PreProcess_Engine_ModelContext import (
|
||||
atomic_npz,
|
||||
clip_and_compact_mesh,
|
||||
evaluate_nurbs_spline,
|
||||
fit_nurbs_spline,
|
||||
grid_faces,
|
||||
grid_vertices,
|
||||
write_glb,
|
||||
@@ -43,9 +41,6 @@ from config.config_system import (
|
||||
SHEET_SURFACE_MARGIN_M,
|
||||
SHEET_SURFACE_METHODS,
|
||||
SURFACE_MAX_PREVIEW_VERTICES,
|
||||
SURFACE_NURBS_CONTROL_POINTS_PER_AXIS,
|
||||
SURFACE_NURBS_DEGREE,
|
||||
SURFACE_NURBS_PATCH_SIZE_M,
|
||||
SURFACE_SMOOTHING_DTM_PREVIEW_RESOLUTION_M,
|
||||
SURFACE_SMOOTHING_DTM_SIGMA_M,
|
||||
SURFACE_SMOOTHING_DTM_SPLINE_SMOOTH,
|
||||
@@ -106,45 +101,18 @@ def _load_features_metric(
|
||||
def _preview_mesh(
|
||||
x: np.ndarray, y: np.ndarray, z: np.ndarray, valid: np.ndarray
|
||||
) -> tuple[np.ndarray, np.ndarray]:
|
||||
"""프리뷰용 정점·면 — 격자를 그대로 잇지 않고 **NURBS(B-spline) 곡면**으로 만든다.
|
||||
"""프리뷰용 정점·면 — 정점 수가 상한을 넘으면 격자를 성기게 딴다.
|
||||
|
||||
격자 삼각형을 그대로 쓰면 1m 셀 경계가 계단처럼 보인다. LAS 파이프라인이 쓰는
|
||||
것과 같은 곡면 적합(`fit_nurbs_spline`·`evaluate_nurbs_spline`)을 걸어 매끈한
|
||||
면을 얻는다(2026-08-30 사용자 지시). **표고 정본(npz)은 격자 그대로**이고 여기서
|
||||
바꾸는 것은 화면에 보이는 메시뿐이다 — 종·횡단은 격자를 샘플링한다.
|
||||
|
||||
적합에 쓰는 제어 간격은 LAS NURBS와 같은 config 값(패치 크기 ÷ 축당 제어점 수)이며,
|
||||
제어 격자가 격자보다 성기지 않도록 최소 1셀로 묶는다.
|
||||
격자를 그대로 잇는다. 한때 NURBS 곡면을 걸었으나(2026-08-30) DTM 스무딩이
|
||||
들어오면서 곡면 적합이 이중으로 걸려 되돌렸다 — 스무딩은 표고 정본(npz)에서
|
||||
한 번만 한다.
|
||||
"""
|
||||
stride = 1
|
||||
while (len(x) // stride + 1) * (len(y) // stride + 1) > SURFACE_MAX_PREVIEW_VERTICES:
|
||||
stride += 1
|
||||
px, py = x[::stride], y[::stride]
|
||||
pv = valid[::stride, ::stride]
|
||||
|
||||
cell_m = float(x[1] - x[0]) if len(x) > 1 else SHEET_SURFACE_GRID_M
|
||||
control_m = max(
|
||||
SURFACE_NURBS_PATCH_SIZE_M / max(SURFACE_NURBS_CONTROL_POINTS_PER_AXIS - 1, 1), cell_m
|
||||
)
|
||||
control_step = max(1, int(round(control_m / max(cell_m, 1e-6))))
|
||||
# 곡면 적합은 결측을 못 받는다 — 무효 셀은 가장 가까운 유효 표고로 메우고,
|
||||
# 메시를 자를 때 원래 유효 마스크로 다시 도려낸다.
|
||||
filled = z.astype(np.float64)
|
||||
if not valid.all():
|
||||
from scipy.ndimage import distance_transform_edt
|
||||
|
||||
_, (rows, cols) = distance_transform_edt(~valid, return_indices=True)
|
||||
filled = filled[rows, cols]
|
||||
cx, cy = x[::control_step], y[::control_step]
|
||||
cz = filled[::control_step, ::control_step]
|
||||
try:
|
||||
spline, z_range = fit_nurbs_spline(cx, cy, cz, SURFACE_NURBS_DEGREE)
|
||||
pz = evaluate_nurbs_spline(spline, py, px, z_range, "도엽 서피스")
|
||||
except Exception as exc: # noqa: BLE001 — 적합 실패 시 격자 메시로 되돌린다
|
||||
logger.warning("도엽 서피스: NURBS 곡면 적합 실패(%s) — 격자 메시를 씁니다.", exc)
|
||||
pz = filled[::stride, ::stride]
|
||||
|
||||
vertices = grid_vertices(px, py, np.asarray(pz, dtype=np.float64))
|
||||
pz, pv = z[::stride, ::stride], valid[::stride, ::stride]
|
||||
vertices = grid_vertices(px, py, pz.astype(np.float64))
|
||||
faces = grid_faces(len(py), len(px))
|
||||
return clip_and_compact_mesh(vertices, faces, pv.reshape(-1))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user