diff --git a/config/config_system_terrain.py b/config/config_system_terrain.py index e28ab794b..7f2a8dfde 100644 --- a/config/config_system_terrain.py +++ b/config/config_system_terrain.py @@ -100,7 +100,8 @@ SURFACE_MODEL_SYNC_TIMEOUT_SECONDS = int(os.getenv("SURFACE_MODEL_SYNC_TIMEOUT_S # footprint(외곽) 산출 SURFACE_FOOTPRINT_RESOLUTION_M = float(os.getenv("SURFACE_FOOTPRINT_RESOLUTION_M", "1.0")) -SURFACE_FOOTPRINT_GAP_CLOSE_M = float(os.getenv("SURFACE_FOOTPRINT_GAP_CLOSE_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" diff --git a/resources/tester/test_640_lidar_default.py b/resources/tester/test_640_lidar_default.py index f92ee1b75..6c2a776ef 100644 --- a/resources/tester/test_640_lidar_default.py +++ b/resources/tester/test_640_lidar_default.py @@ -134,3 +134,22 @@ def test_설정_지문이_바뀌면_implicit_다시_지음(tmp_path: Path) -> No with np.load(tmp_path / "implicit_a.npz") as new: assert len(new["center_z"]) == 2_000 assert manifest["source_filters"]["a"]["methods"]["implicit"]["center_count"] == 2_000 + + +def test_외곽_틈_닫기_3m_는_성긴_띠를_살림() -> None: + points = _plane(60.0) + gap = (points[:, 0] > 28) & (points[:, 0] < 33) # 5 m 빈 띠 — 1 m 닫기면 두 덩이 + points = points[~gap] + + def area(close_m: float) -> float: + config = dict(cfg.build_surface_model_config(), footprint_gap_close_meters=close_m) + context = TerrainContext( + xyz=points, + mask=np.ones(len(points), bool), + bounds=np.array([points.min(axis=0), points.max(axis=0)]).T, + config=config, + ) + return context.footprint_metadata()["footprint_area_m2"] + + assert cfg.SURFACE_FOOTPRINT_GAP_CLOSE_M == 3.0 + assert area(3.0) > 1.8 * area(1.0) # 한 덩이(띠 포함) 대 큰 덩이 하나