auto: 2026-07-29 20:06 (EOMSANGDON-HOME)
This commit is contained in:
@@ -435,6 +435,51 @@ def _assemble_march_polygon(
|
||||
return polygon
|
||||
|
||||
|
||||
def _refine_road_edge(polygon: Polygon, road_line: LineString) -> Polygon:
|
||||
"""경계의 도로변 구간을 도로선 원해상도 좌표로 치환한다.
|
||||
|
||||
단순화(simplify)가 도로변 경계를 뭉개 도로를 가로지르는 것을 막는다
|
||||
(2026-07-29 사용자 지시: 경계 참조를 도로선 해상도와 매칭).
|
||||
"""
|
||||
coords = list(polygon.exterior.coords)[:-1]
|
||||
count = len(coords)
|
||||
near = [road_line.distance(Point(c)) < 6.0 for c in coords]
|
||||
if not any(near) or all(near):
|
||||
return polygon
|
||||
start = next(i for i in range(count) if not near[i])
|
||||
coords = coords[start:] + coords[:start]
|
||||
near = near[start:] + near[:start]
|
||||
ring: list[tuple[float, float]] = []
|
||||
i = 0
|
||||
while i < count:
|
||||
if not near[i]:
|
||||
ring.append(coords[i])
|
||||
i += 1
|
||||
continue
|
||||
j = i
|
||||
while j < count and near[j]:
|
||||
j += 1
|
||||
t1 = road_line.project(Point(coords[i]))
|
||||
t2 = road_line.project(Point(coords[j - 1]))
|
||||
segment = substring(road_line, min(t1, t2), max(t1, t2))
|
||||
if segment.geom_type == "LineString" and len(segment.coords) >= 2:
|
||||
segment_coords = list(segment.coords)
|
||||
if t1 > t2:
|
||||
segment_coords.reverse()
|
||||
ring.extend(segment_coords)
|
||||
else:
|
||||
ring.extend(coords[i:j])
|
||||
i = j
|
||||
if len(ring) < 4:
|
||||
return polygon
|
||||
refined = Polygon(ring).buffer(0)
|
||||
if refined.geom_type == "MultiPolygon":
|
||||
refined = max(refined.geoms, key=lambda part: part.area)
|
||||
if refined.is_empty or refined.geom_type != "Polygon":
|
||||
return polygon
|
||||
return refined
|
||||
|
||||
|
||||
def build_watershed_basins(
|
||||
vertices: list[Any],
|
||||
candidates: list[StructureCandidate],
|
||||
@@ -455,7 +500,8 @@ def build_watershed_basins(
|
||||
if contour_index.tree is None:
|
||||
logger.warning("표고 속성이 있는 등고선이 없어 유역을 산정하지 못했습니다.")
|
||||
return []
|
||||
spot_index = ContourIndex(spot_features, elevation_keys)
|
||||
# 표고점은 참조하지 않는다(2026-07-29 사용자 지시: 계측 측점 데이터라 오류 유입).
|
||||
_ = spot_features
|
||||
road_line = LineString([(vertex.x, vertex.y) for vertex in vertices])
|
||||
|
||||
ordered = sorted(candidates, key=lambda item: item.chainage_m)
|
||||
@@ -569,13 +615,13 @@ def build_watershed_basins(
|
||||
outlet_z = contour_index.nearest_elevation(outlet, UPHILL_PROBE_RADIUS_M)
|
||||
if outlet_z is None:
|
||||
outlet_z = _interpolate_vertex(vertices, candidate.chainage_m)[2]
|
||||
top_z = max(
|
||||
contour_index.max_elevation_within(polygon) or outlet_z,
|
||||
spot_index.max_elevation_within(polygon) or outlet_z,
|
||||
)
|
||||
# 표고차는 등고선만으로 계산한다(표고점 미참조 — 사용자 지시).
|
||||
top_z = contour_index.max_elevation_within(polygon) or outlet_z
|
||||
boundary_line = polygon.simplify(5.0, preserve_topology=True)
|
||||
if boundary_line.is_empty or boundary_line.geom_type != "Polygon":
|
||||
boundary_line = polygon
|
||||
# 도로변 경계는 단순화 없이 도로선 해상도를 유지한다.
|
||||
boundary_line = _refine_road_edge(boundary_line, road_line)
|
||||
boundary = [[float(x), float(y)] for x, y in boundary_line.exterior.coords]
|
||||
if flow_length <= 0.0:
|
||||
flow_length = max(
|
||||
|
||||
Reference in New Issue
Block a user