diff --git a/B04_wf1_Surface/B04_wf1_Surface_Engine_Watershed_Analyze.py b/B04_wf1_Surface/B04_wf1_Surface_Engine_Watershed_Analyze.py index 16c4fd0f..f0088617 100644 --- a/B04_wf1_Surface/B04_wf1_Surface_Engine_Watershed_Analyze.py +++ b/B04_wf1_Surface/B04_wf1_Surface_Engine_Watershed_Analyze.py @@ -360,6 +360,9 @@ def find_inflow_hotspots( ) -> list[tuple[float, float, int, int]]: """도로 위 **유입 집중점**을 뽑는다 — (누가거리 m, 유입면적 ㎡, 구역 번호, 구역 내 순위). + 구역 번호 `-1`은 **기본 관(세류 교차점) 자리**를 뜻한다. 나머지는 그 구역에서 보충 후보로 + 뽑은 자리다. + 왜 필요한가(2026-08-01 사용자 지시): 기본 관은 국가 수치지형도의 세류선이 도로를 가로지르는 자리라 근거가 확실하다. 그런데 관 **최대 간격**을 지키려면 세류가 없는 긴 구간에도 관을 넣어야 하는데, 이때 등간격으로 기계적으로 꽂는 대신 **물이 실제로 많이 모이는 자리**를 @@ -379,6 +382,11 @@ def find_inflow_hotspots( 전부(전체 유역의 대부분)가 관에서 두어 걸음 떨어진 칸에서 다시 최대값으로 잡혀, 정작 관이 없어 보충이 필요한 자리는 뽑히지 못한다. 노선 시·종점은 관이 아니므로 물러나지 않는다. + · **기본 관 자리 자체도 집중점으로 넣는다(구역 번호 −1).** 세류가 도로를 가로지르는 + 자리가 대개 그 노선에서 가장 큰 유역을 받는데, 그 자리는 구역 경계라 위 규칙으로는 + 영영 뽑히지 않는다(2026-08-01 사용자 지시). 위치는 관 누가거리 그대로가 아니라 + 관 ±최소간격 안에서 강도가 가장 큰 칸으로 잡는다 — 도로를 폭으로 굽는 과정에서 + 실제 유입 봉우리가 관에서 두어 걸음 옆에 놓이기 때문이다. · 강도 0인 칸은 뽑지 않는다(개수를 못 채워도 그대로 둔다). """ if curve.size == 0 or route_length_m <= 0: @@ -387,6 +395,22 @@ def find_inflow_hotspots( edges = sorted({0.0, float(route_length_m), *(float(p) for p in pipe_chainages)}) exclusion = max(1, int(round(DRAINAGE_PIPE_MIN_SPACING_M))) hotspots: list[tuple[float, float, int, int]] = [] + + # ① 기본 관 자리 — 관마다 그 근처 봉우리 하나. + for pipe_m in sorted({float(p) for p in pipe_chainages}): + center = int(round(pipe_m)) + low = max(0, center - exclusion) + high = min(curve.size - 1, center + exclusion) + if high < low: + continue + window = curve[low : high + 1] + best = int(np.argmax(window)) + if window[best] <= 0: + continue + hotspots.append((float(low + best), float(window[best]), -1, 0)) + # 관 자리와 겹치는 칸은 구역 쪽에서 다시 뽑지 않는다 — 같은 자리에 마커가 두 개 겹친다. + taken = {int(chainage) for chainage, _, _, _ in hotspots} + # ② 구역별 보충 후보 — 관과 관 사이에서 물이 많이 모이는 자리. for zone_index, (start_m, end_m) in enumerate(zip(edges, edges[1:])): span = end_m - start_m if span <= 0: @@ -401,6 +425,9 @@ def find_inflow_hotspots( if high < low: continue window = curve[low : high + 1].copy() + for index in taken: + if low <= index <= high: + window[index - low] = 0.0 for rank in range(wanted): best = int(np.argmax(window)) if window[best] <= 0: