fix(B07): 용지도 구역이 한 필지 안이면 어느 필지인지 표기
- 필지 경계가 하나도 안 보이고 도곽을 통째로 감싼 필지가 있으면 정보 묶음 맨 위에 「구역 전체가 이 필지 안 (시군구 읍면동 리)」 한 줄 - 검증_sub4(용화리 국유림 산77-15임 한 필지 안): 화면에 안내 1개 + 지번·지목·면적·소유자 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013rJwJMVL4EE31y77TB11AP
This commit is contained in:
@@ -109,6 +109,16 @@ def _parcel_info_lines(props: dict[str, Any]) -> list[str]:
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _enclosing_note(props: dict[str, Any]) -> str:
|
||||||
|
"""구역 전체가 한 필지 안일 때 정보 묶음 맨 위 줄 — 소재지(시군구 읍면동 리)를 붙인다."""
|
||||||
|
place = " ".join(
|
||||||
|
str(props[key]).strip()
|
||||||
|
for key in ("sgg_nm", "emd_nm", "ri_nm")
|
||||||
|
if isinstance(props.get(key), str) and props[key].strip()
|
||||||
|
)
|
||||||
|
return f"구역 전체가 이 필지 안 ({place})" if place else "구역 전체가 이 필지 안"
|
||||||
|
|
||||||
|
|
||||||
def _legend_entities(drawing_id: str, origin: tuple[float, float]) -> list[dict[str, Any]]:
|
def _legend_entities(drawing_id: str, origin: tuple[float, float]) -> list[dict[str, Any]]:
|
||||||
"""범례 — 유역도에서 유역 정보표가 있던 자리(오른쪽 칸)에 놓는다."""
|
"""범례 — 유역도에서 유역 정보표가 있던 자리(오른쪽 칸)에 놓는다."""
|
||||||
entities: list[dict[str, Any]] = []
|
entities: list[dict[str, Any]] = []
|
||||||
@@ -217,6 +227,7 @@ def build_landuse_drawing(
|
|||||||
# 필지 경계 + 필지 정보. 도곽에 잘려 조각이 여럿인 필지도 정보는 한 번만 —
|
# 필지 경계 + 필지 정보. 도곽에 잘려 조각이 여럿인 필지도 정보는 한 번만 —
|
||||||
# 가장 큰 조각 가운데에 적는다(구역 안 필지 수 = 정보 묶음 수).
|
# 가장 큰 조각 가운데에 적는다(구역 안 필지 수 = 정보 묶음 수).
|
||||||
spots: dict[str, tuple[float, tuple[float, float], dict[str, Any]]] = {}
|
spots: dict[str, tuple[float, tuple[float, float], dict[str, Any]]] = {}
|
||||||
|
enclosing: set[str] = set() # 도곽을 통째로 감싼 필지
|
||||||
for index, parcel in enumerate(parcels):
|
for index, parcel in enumerate(parcels):
|
||||||
ring = parcel.get("ring") or []
|
ring = parcel.get("ring") or []
|
||||||
props = parcel.get("props") or {}
|
props = parcel.get("props") or {}
|
||||||
@@ -234,14 +245,19 @@ def build_landuse_drawing(
|
|||||||
elif label_at is not None:
|
elif label_at is not None:
|
||||||
# 도곽을 통째로 감싼 필지 — 경계선이 없으니 지정된 자리에 정보만 적는다.
|
# 도곽을 통째로 감싼 필지 — 경계선이 없으니 지정된 자리에 정보만 적는다.
|
||||||
size, center = 0.0, paper(tuple(label_at))
|
size, center = 0.0, paper(tuple(label_at))
|
||||||
|
enclosing.add(str(props.get("pnu") or f"#{index}"))
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
key = str(props.get("pnu") or f"#{index}")
|
key = str(props.get("pnu") or f"#{index}")
|
||||||
if key not in spots or size > spots[key][0]:
|
if key not in spots or size > spots[key][0]:
|
||||||
spots[key] = (size, center, props)
|
spots[key] = (size, center, props)
|
||||||
|
# 필지 경계가 하나도 안 보이면(구역이 한 필지 안) 어느 필지인지 글로 밝힌다(68-2).
|
||||||
|
no_outline = not any(len(parcel.get("ring") or []) >= 2 for parcel in parcels)
|
||||||
jibun: list[dict[str, Any]] = []
|
jibun: list[dict[str, Any]] = []
|
||||||
for key, (_size, center, props) in spots.items():
|
for key, (_size, center, props) in spots.items():
|
||||||
lines = _parcel_info_lines(props)
|
lines = _parcel_info_lines(props)
|
||||||
|
if no_outline and key in enclosing:
|
||||||
|
lines = [_enclosing_note(props), *lines]
|
||||||
top = center[1] + (len(lines) - 1) / 2.0 * _INFO_LINE_GAP
|
top = center[1] + (len(lines) - 1) / 2.0 * _INFO_LINE_GAP
|
||||||
for row, text in enumerate(lines):
|
for row, text in enumerate(lines):
|
||||||
if text:
|
if text:
|
||||||
|
|||||||
@@ -35,3 +35,45 @@ def test_one_label_group_per_parcel() -> None:
|
|||||||
e["shapeData"]["basePoint"]["x"] for e in texts if e["shapeData"]["label"] == "산1임"
|
e["shapeData"]["basePoint"]["x"] for e in texts if e["shapeData"]["label"] == "산1임"
|
||||||
}
|
}
|
||||||
assert split_x.pop() == pytest.approx(215.0 * MM)
|
assert split_x.pop() == pytest.approx(215.0 * MM)
|
||||||
|
|
||||||
|
|
||||||
|
def test_zone_inside_one_parcel_is_named_once(tmp_path) -> None:
|
||||||
|
"""작은 구역이 큰 필지 하나 안에 통째로 — 경계선이 없어도 어느 필지인지 한 번 적는다 (68-2)."""
|
||||||
|
import json
|
||||||
|
|
||||||
|
from B07_DesignDetail.B07_DesignDetail_Router_Support_Basin import _clip_parcels
|
||||||
|
|
||||||
|
props = {
|
||||||
|
"pnu": "P1",
|
||||||
|
"sgg_nm": "봉화군",
|
||||||
|
"emd_nm": "재산면",
|
||||||
|
"ri_nm": "갈산리",
|
||||||
|
"jibun": "산77-1임",
|
||||||
|
"jimok": "임야",
|
||||||
|
"parea": 1234567,
|
||||||
|
"owner_nm": "국",
|
||||||
|
}
|
||||||
|
big = [[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]]
|
||||||
|
geojson = {
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"features": [
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": props,
|
||||||
|
"geometry": {"type": "Polygon", "coordinates": [big]},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
path = tmp_path / "parcels.geojson"
|
||||||
|
path.write_text(json.dumps(geojson, ensure_ascii=False), encoding="utf-8")
|
||||||
|
parcels = _clip_parcels(path, "EPSG:4326", (4.0, 4.0, 6.0, 6.0))
|
||||||
|
assert len(parcels) == 1 and parcels[0]["ring"] == []
|
||||||
|
|
||||||
|
route = [(4.5, 4.5), (5.5, 5.5)]
|
||||||
|
drawing = build_landuse_drawing("landuse", "용지도", route, [], parcels, [], [])
|
||||||
|
labels = [
|
||||||
|
e["shapeData"]["label"] for e in drawing["entities"] if e.get("layerId") == JIBUN_LAYER_ID
|
||||||
|
]
|
||||||
|
notes = [label for label in labels if label.startswith("구역 전체가 이 필지 안")]
|
||||||
|
assert notes == ["구역 전체가 이 필지 안 (봉화군 재산면 갈산리)"]
|
||||||
|
assert labels[1:] == ["산77-1임", "임야", "1,234,567㎡", "국"]
|
||||||
|
|||||||
Reference in New Issue
Block a user