- 관 라벨 stream_label = 세류선 UFID · 교차 차례 · 처음 교차점 좌표 · 끌기 · 옵션 고침에도 남음 · 관 PUT 때 id 로 되붙임 - 노선 [저장] = 라벨(관 · 지움 표지)이 같은 세류선 가장 가까운 새 교차점을 짝으로 잡음 · 짝 잡힌 교차엔 관 안 더함 - 지운 자동 관 = pipe_points.json dismissed_streams · 라벨 없던 옛 관은 자리만 → 다음 노선 [저장] 때 라벨 - 라벨 없는 옛 stream 관 = 옛 노선 누가거리 5 m 안 교차 라벨 · 겹친 관 안 지움(로그 수) - 추천 [적용] = 표지 없음 · [초기화] = 초기값 파일 그대로 - 세류선 교차 셈을 common_util_stream_crossing 으로 옮김(common_util_route_geometry 700줄 넘음) - 시험 test_507_2_stream_pipe_label · test_494_2 가짜 저장 인자 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
155 lines
6.7 KiB
Python
155 lines
6.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""507-2 자동 세류선 관 라벨 — 노선 바꾼 [저장] 에 관이 여럿 생기던 흠(요구 311-3).
|
|
|
|
못박는 것
|
|
- 라벨 = 세류선 지물 id · 교차 차례 · 처음 교차점 좌표 · 끌어 source 가 user 로 바뀌어도 남음 ·
|
|
파일 · 화면 PUT(라벨 모름)을 지나도 id 로 되붙음.
|
|
- 노선 바꾼 [저장] 두 번 = 같은 세류선 라벨 관이 있으면(옮겼어도) 안 더함 · 관 수 그대로.
|
|
- 지운 자동 관 = 지움 표지 · 다시 안 생김(라벨 없던 옛 관도 자리로 남겨 다음 [저장] 때 라벨로).
|
|
- 초기값([적용]) = 지움 표지 없음 · 새 교차 관 · save_pipe_points 표지 None = 파일 것 그대로.
|
|
- 라벨 없는 옛 stream 관 = 옛 노선 교차 5 m 안이면 라벨 · 겹친 관은 안 지우고 수만 셈.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
if str(ROOT) not in sys.path:
|
|
sys.path.insert(0, str(ROOT))
|
|
|
|
import B05_Profile.B05_Profile_Route_Save as save # noqa: E402
|
|
import common_util.common_util_drainage_pipes as drainage_pipes # noqa: E402
|
|
from B05_Profile.B05_Profile_Route_Save_Parts import vertices_of # noqa: E402
|
|
from common_util.common_util_drainage_pipes import ( # noqa: E402
|
|
PIPE_SOURCE_STREAM,
|
|
PipePoint,
|
|
parse_pipe_points,
|
|
)
|
|
from common_util.common_util_stream_crossing import ( # noqa: E402
|
|
adopt_labels,
|
|
find_stream_crossings,
|
|
keep_labels,
|
|
)
|
|
|
|
OLD = [[0.0, 0.0], [100.0, 0.0], [200.0, 0.0], [300.0, 0.0], [400.0, 0.0]]
|
|
# 앞 측점 노선을 북으로 — 세류선 교차가 30 m · 45 m 옮음(5 m 솎기 넘음)
|
|
NEW1 = [[0.0, 0.0], [100.0, 0.0], [200.0, 60.0], [300.0, 0.0], [400.0, 0.0]]
|
|
NEW2 = [[0.0, 0.0], [100.0, 0.0], [200.0, 90.0], [300.0, 0.0], [400.0, 0.0]]
|
|
STREAMS = [
|
|
{
|
|
"type": "Feature",
|
|
"properties": {"UFID": "S1", "구분": "세류"},
|
|
"geometry": {"type": "LineString", "coordinates": [[150.0, -50.0], [150.0, 120.0]]},
|
|
}
|
|
]
|
|
|
|
|
|
def _points(xy) -> list[dict[str, float]]:
|
|
return [{"x": x, "y": y} for x, y in xy]
|
|
|
|
|
|
def _save(old: list[PipePoint], old_xy, new_xy, dismissed=None) -> tuple[list[PipePoint], int]:
|
|
pairs, crossing, _ = save.followed_pipes(old, old_xy, _points(new_xy), STREAMS, dismissed)
|
|
return [pipe for _, pipe in pairs], crossing
|
|
|
|
|
|
def _legacy() -> PipePoint:
|
|
"""라벨 없는 옛 자동 관(옛 노선 교차 (150, 0))."""
|
|
return PipePoint(chainage_m=150.0, source=PIPE_SOURCE_STREAM, x=150.0, y=0.0, id="p15000")
|
|
|
|
|
|
def test_교차점에_세류선_id():
|
|
found = find_stream_crossings(vertices_of(OLD), STREAMS)
|
|
assert [(c.stream_id, round(c.x), round(c.y)) for c in found] == [("S1", 150, 0)]
|
|
|
|
|
|
def test_노선_바꾼_저장_두_번_관_수_그대로():
|
|
pipes, crossing = _save([_legacy()], OLD, NEW1)
|
|
assert crossing == 0 and len(pipes) == 1 # 고치기 전 = 옛 관 + 새 관 둘
|
|
label = pipes[0].stream_label
|
|
assert label == {"stream": "S1", "order": 1, "x": 150.0, "y": 0.0} # 처음 교차점
|
|
# 파일을 지나도 라벨 그대로 · 두 번째 노선 [저장]
|
|
again = parse_pipe_points([pipe.as_dict() for pipe in pipes])
|
|
pipes2, crossing2 = _save(again, NEW1, NEW2)
|
|
assert crossing2 == 0 and len(pipes2) == 1 and pipes2[0].stream_label == label
|
|
|
|
|
|
def test_끌어_user_로_바뀌어도_라벨_남음():
|
|
pipes, _ = _save([_legacy()], OLD, NEW1)
|
|
moved = pipes[0]
|
|
moved.source, moved.x, moved.y = "user", 170.0, 40.0 # 끌기 = user
|
|
pipes2, crossing2 = _save(parse_pipe_points([moved.as_dict()]), NEW1, NEW2)
|
|
assert crossing2 == 0 and len(pipes2) == 1 and pipes2[0].stream_label["stream"] == "S1"
|
|
|
|
|
|
def test_화면_PUT_라벨_되붙임():
|
|
stored = [
|
|
PipePoint(chainage_m=150.0, id="p15000", stream_label={"stream": "S1", "x": 1, "y": 2})
|
|
]
|
|
request = [PipePoint(chainage_m=152.0, id="p15000", source="user")] # 화면은 라벨 모름
|
|
dismissed: list = []
|
|
keep_labels(request, stored, dismissed)
|
|
assert request[0].stream_label == stored[0].stream_label and dismissed == []
|
|
|
|
|
|
def test_지운_자동_관_다시_안_생김():
|
|
pipes, _ = _save([_legacy()], OLD, NEW1)
|
|
dismissed: list = []
|
|
keep_labels([], pipes, dismissed) # 사용자가 지우고 [저장]
|
|
assert dismissed == [pipes[0].stream_label]
|
|
after, crossing = _save([], NEW1, NEW2, dismissed)
|
|
assert crossing == 0 and after == []
|
|
|
|
|
|
def test_라벨_없던_옛_관_지움도_다시_안_생김():
|
|
dismissed: list = []
|
|
keep_labels([], [_legacy()], dismissed)
|
|
assert dismissed == [{"x": 150.0, "y": 0.0}] # 자리만
|
|
after, crossing = _save([], OLD, NEW1, dismissed)
|
|
assert crossing == 0 and after == []
|
|
assert dismissed[0]["stream"] == "S1" # 다음 [저장] 때 라벨로
|
|
|
|
|
|
def test_사용자_관_지움은_표지_없음():
|
|
dismissed: list = []
|
|
keep_labels([], [PipePoint(chainage_m=50.0, x=50.0, y=0.0)], dismissed)
|
|
assert dismissed == []
|
|
|
|
|
|
def test_초기값_적용_새_교차_관():
|
|
pipes, crossing = _save([], [], NEW1, [])
|
|
assert crossing == 1 and pipes[0].stream_label["stream"] == "S1"
|
|
assert pipes[0].stream_label["y"] == 30.0
|
|
|
|
|
|
def test_지움_표지_파일(monkeypatch, tmp_path):
|
|
path = tmp_path / "pipe_points.json"
|
|
monkeypatch.setattr(drainage_pipes, "pipe_points_path", lambda _stored: path)
|
|
mark = [{"stream": "S1", "order": 1, "x": 150.0, "y": 0.0}]
|
|
drainage_pipes.save_pipe_points("x", "sig", [], None, mark)
|
|
drainage_pipes.save_pipe_points("x", "sig", [PipePoint(chainage_m=5.0)]) # None = 그대로
|
|
assert json.loads(path.read_text("utf-8"))["dismissed_streams"] == mark
|
|
assert drainage_pipes.read_dismissed(path) == mark
|
|
drainage_pipes.save_pipe_points("x", "sig", [], None, []) # [적용] = 표지 없음
|
|
assert "dismissed_streams" not in json.loads(path.read_text("utf-8"))
|
|
|
|
|
|
def test_겹친_옛_관_안_지우고_셈():
|
|
twin = PipePoint(chainage_m=152.0, source=PIPE_SOURCE_STREAM, x=152.0, y=0.0, id="p15200")
|
|
old = [_legacy(), twin]
|
|
overlap = adopt_labels(old, [], find_stream_crossings(vertices_of(OLD), STREAMS), OLD)
|
|
assert overlap == 1
|
|
assert old[0].stream_label and not old[1].stream_label # 가까운 관만 라벨
|
|
pipes, crossing = _save(parse_pipe_points([p.as_dict() for p in old]), OLD, NEW1)
|
|
assert crossing == 0 and len(pipes) == 2 # 둘 다 그대로 · 새 관 없음
|
|
|
|
|
|
def test_옆_다른_선_위_옛_관도_라벨():
|
|
"""옛 관 좌표가 다른 선 위(옆 15 m · 검증_sub3 실측) — 옛 노선 누가거리로 5 m 안이면 라벨."""
|
|
side = PipePoint(chainage_m=150.0, source=PIPE_SOURCE_STREAM, x=151.0, y=15.0, id="p15000")
|
|
pipes, crossing = _save([side], OLD, NEW1)
|
|
assert crossing == 0 and len(pipes) == 1 and pipes[0].stream_label["stream"] == "S1"
|