fix(B05): 6/7/8 단계 산출물도 영구저장소에 남긴다
확인해 보니 7(2차 유역 외곽선)과 8(기본 관)은 저장되고 있었으나
6(흐름 강도 곡선)이 빠져 있었고, 관에 누가거리가 안 붙었다.
- write_stage 의 레이어 항목이 (기하, 속성dict) 짝도 받도록 확장.
관 피처에 chainage_m / reason / stream_name 이 실린다.
- 흐름 강도 곡선은 기하가 아니라 수치 곡선이라 GeoJSON 대신
02_flow_direction.npz 에 strength_chainage_m / strength_area_m2 로 담는다.
- manifest 에 strength_points / strength_total_m2 요약 추가.
저장 확인 (실데이터)
01_primary_region.geojson 688KB kind: primary_region 1 / upstream 16 /
downstream 860 / route 1 / grid_bbox 1 / basin_boundary 1 / pipe 1
pipe 속성 = chainage_m 149.73, reason stream
01_primary_region.npz 11KB 셀 마스크 + 확장 회차
02_flow_direction.npz 2353KB direction/reaches_road/analyzed/receiver/
burned/band_elevation + 강도 곡선 71점(합계 457,404m2, 최대 150m)
manifest.json 3단계 요약 전부
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -44,13 +44,14 @@ def drainage_dir(stored_path: str) -> Path:
|
||||
def write_stage(
|
||||
stored_path: str,
|
||||
stage: str,
|
||||
layers: dict[str, Sequence[BaseGeometry]],
|
||||
layers: dict[str, Sequence[BaseGeometry | tuple[BaseGeometry, dict[str, Any]]]],
|
||||
properties: dict[str, Any],
|
||||
to_lonlat: LonLat,
|
||||
) -> str | None:
|
||||
"""한 단계의 기하 산출물을 GeoJSON으로 저장하고 매니페스트를 갱신한다.
|
||||
|
||||
`layers`는 {레이어이름: 사업지 CRS(m) 기하 목록}이며 피처 `kind` 속성이 된다.
|
||||
`layers`는 {레이어이름: 사업지 CRS(m) 기하 목록}이며 레이어 이름이 피처 `kind` 속성이
|
||||
된다. 기하 대신 `(기하, 속성dict)` 짝을 넣으면 그 속성이 피처에 함께 실린다.
|
||||
좌표는 여기서 WGS84로 바꾼다 — 저장 파일은 어떤 도구로 열어도 바로 보여야 한다.
|
||||
"""
|
||||
prefix = STAGES.get(stage)
|
||||
@@ -60,12 +61,14 @@ def write_stage(
|
||||
|
||||
features: list[dict[str, Any]] = []
|
||||
counts: dict[str, int] = {}
|
||||
for kind, geometries in layers.items():
|
||||
for index, geometry in enumerate(geometries):
|
||||
feature = _to_feature(kind, index, geometry, to_lonlat)
|
||||
for kind, entries in layers.items():
|
||||
for index, entry in enumerate(entries):
|
||||
# 항목은 기하 하나이거나 (기하, 속성) 짝이다 — 관 누가거리처럼 붙일 값이 있을 때 쓴다.
|
||||
geometry, extra = entry if isinstance(entry, tuple) else (entry, None)
|
||||
feature = _to_feature(kind, index, geometry, to_lonlat, extra)
|
||||
if feature is not None:
|
||||
features.append(feature)
|
||||
counts[kind] = len(geometries)
|
||||
counts[kind] = len(entries)
|
||||
|
||||
filename = f"{prefix}_{stage}.geojson"
|
||||
directory = drainage_dir(stored_path)
|
||||
@@ -90,14 +93,18 @@ def write_stage(
|
||||
|
||||
|
||||
def _to_feature(
|
||||
kind: str, index: int, geometry: BaseGeometry, to_lonlat: LonLat
|
||||
kind: str,
|
||||
index: int,
|
||||
geometry: BaseGeometry,
|
||||
to_lonlat: LonLat,
|
||||
extra: dict[str, Any] | None = None,
|
||||
) -> dict[str, Any] | None:
|
||||
coordinates = _to_lonlat_coords(geometry, to_lonlat)
|
||||
if coordinates is None:
|
||||
return None
|
||||
return {
|
||||
"type": "Feature",
|
||||
"properties": {"kind": kind, "index": index},
|
||||
"properties": {"kind": kind, "index": index, **(extra or {})},
|
||||
"geometry": {"type": geometry.geom_type, "coordinates": coordinates},
|
||||
}
|
||||
|
||||
|
||||
@@ -279,9 +279,19 @@ async def get_primary_region(project_id: UUID) -> dict[str, Any] | JSONResponse:
|
||||
"downstream": region.split.downstream,
|
||||
"route": [prepared["route_line"]],
|
||||
"grid_bbox": [_grid_bbox_polygon(spec)],
|
||||
# ⑦ 2차 전체 배수유역 외곽선, ⑧ 기본 관 위치.
|
||||
# ⑦ 2차 전체 배수유역 외곽선, ⑧ 기본 관 위치(누가거리·근거 포함).
|
||||
"basin_boundary": _boundary_geometry(preview.basin_boundary_xy),
|
||||
"pipe": [Point(pipe.x, pipe.y) for pipe in preview.pipes],
|
||||
"pipe": [
|
||||
(
|
||||
Point(pipe.x, pipe.y),
|
||||
{
|
||||
"chainage_m": round(pipe.chainage_m, 2),
|
||||
"reason": pipe.reason,
|
||||
"stream_name": pipe.stream_name,
|
||||
},
|
||||
)
|
||||
for pipe in preview.pipes
|
||||
],
|
||||
},
|
||||
{
|
||||
"radius_m": region.radius_m,
|
||||
@@ -331,6 +341,11 @@ def _write_stage_arrays(stored_path: str, preview: Any, domain: Any, spec: Any)
|
||||
arrays["burned"] = flow.burned.reshape(spec.n_rows, spec.n_cols)
|
||||
if preview.descent is not None:
|
||||
arrays["band_elevation"] = preview.descent.band_elevation
|
||||
# ⑥ 흐름 강도 곡선 — 기하가 아니라 수치 곡선이라 GeoJSON이 아닌 여기에 함께 담는다.
|
||||
if preview.strength_profile:
|
||||
curve = np.asarray(preview.strength_profile, dtype=np.float64)
|
||||
arrays["strength_chainage_m"] = curve[:, 0]
|
||||
arrays["strength_area_m2"] = curve[:, 1]
|
||||
write_grid_arrays(
|
||||
stored_path,
|
||||
"flow_direction",
|
||||
@@ -346,6 +361,8 @@ def _write_stage_arrays(stored_path: str, preview: Any, domain: Any, spec: Any)
|
||||
"burned": 0 if flow.burned is None else int(flow.burned.sum()),
|
||||
"outer_seeds": flow.outer_seeds,
|
||||
"interior_seeds": flow.interior_seeds,
|
||||
"strength_points": len(preview.strength_profile),
|
||||
"strength_total_m2": round(sum(area for _, area in preview.strength_profile), 1),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user