|
|
|
@@ -1,14 +1,14 @@
|
|
|
|
|
"""B07 계획평면도 종류 · 정보 조각 (PLAN 60장).
|
|
|
|
|
|
|
|
|
|
① 측점 둘에서 성토사면 외곽선 폭 = 횡단 설계 값(노견 끝 · 설계선이 지반에 닿는 자리)
|
|
|
|
|
② 종류 더하기 · 지우기(기본 넷 포함) · 다시 읽어 같음
|
|
|
|
|
③ 대피소 · 사토장 자리 — 한 자리에 둘 다
|
|
|
|
|
② 종류 더하기 · 지우기(기본 종류 포함) · 다시 읽어 같음 · 기본 = 지형도 하나
|
|
|
|
|
③ (없앰 — 대피소 · 사토장 자리는 524-1 에서 지움)
|
|
|
|
|
④ 고른 조각만 도면 층으로 얹힘
|
|
|
|
|
⑤ 조각 잘게(67장) — 노견선 · 성토 외곽선 · 절토 외곽선 따로 · 기본 넷 처음 체크 = 옛 그림 ·
|
|
|
|
|
옛 종류 파일의 slope_outline 펼침 · 종류 업데이트(기본 넷 포함) · 확정본 풀림 · 배수시설 기호
|
|
|
|
|
⑤ 조각 잘게(67장) — 노견선 · 성토 외곽선 · 절토 외곽선 따로 · 기본 처음 체크 = 옛 그림 ·
|
|
|
|
|
옛 종류 파일의 slope_outline 펼침 · 종류 업데이트(기본 포함) · 확정본 풀림 · 배수시설 기호
|
|
|
|
|
⑥ IP 표(94장) — 예시 검산 · 도-분-초 올림 · 장마다 그 장 IP 한 번 · 표 밑 선 자름 · 층
|
|
|
|
|
⑦ 용지도 종류(93장) — 기본 종류 · 옛 종류 폴더에 한 번 더함(지우면 안 살아남) · 용지 조각 층
|
|
|
|
|
⑧ 배수유역도 종류(109장) — 양식 watershed · 한 장 목록 · 지우기 · 다시 만들기 · IP 표 두 줄 차례 ·
|
|
|
|
|
⑦ 용지도 조각(93장) — 용지 조각 층
|
|
|
|
|
⑧ 배수유역도 종류(109장) — 새 종류로 더함 · 양식 watershed · 한 장 목록 · 지우기 · 다시 만들기 · IP 표 두 줄 차례 ·
|
|
|
|
|
용지도 상자 안 선 0
|
|
|
|
|
⑨ 종류 차례(140-2) — 끌어 놓은 차례 그대로 · 다시 읽어 같음 · 앞선 종류가 바뀐 종류만 확정 풂 · 목록 어긋나면 거절
|
|
|
|
|
"""
|
|
|
|
@@ -38,16 +38,13 @@ from B07_DesignDetail.B07_DesignDetail_Engine_Frame_Export import drawing_to_dxf
|
|
|
|
|
from B07_DesignDetail.B07_DesignDetail_Router_Support_Io import _read_manifest, _write_manifest
|
|
|
|
|
from B07_DesignDetail.B07_DesignDetail_Router_Support_Plan import (
|
|
|
|
|
_kinds_dir,
|
|
|
|
|
_refuge_items,
|
|
|
|
|
add_kind,
|
|
|
|
|
delete_kind,
|
|
|
|
|
list_kinds,
|
|
|
|
|
plan_kind_items,
|
|
|
|
|
read_marks,
|
|
|
|
|
reorder_kinds,
|
|
|
|
|
slope_records,
|
|
|
|
|
update_kind,
|
|
|
|
|
write_marks,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -139,54 +136,23 @@ def test_outline_width_equals_cross_design_at_two_stations(tmp_path: Path) -> No
|
|
|
|
|
|
|
|
|
|
def test_kinds_add_delete_persist(tmp_path: Path) -> None:
|
|
|
|
|
root = tmp_path / "project"
|
|
|
|
|
assert [k["name"] for k in list_kinds(root)] == [
|
|
|
|
|
"지형",
|
|
|
|
|
"노선배치도",
|
|
|
|
|
"대피소",
|
|
|
|
|
"라이다",
|
|
|
|
|
"용지도",
|
|
|
|
|
"배수유역도",
|
|
|
|
|
]
|
|
|
|
|
assert [k["name"] for k in list_kinds(root)] == ["지형도"] # 기본 = 하나
|
|
|
|
|
assert [k["id"] for k in DEFAULT_KINDS] == ["terrain"]
|
|
|
|
|
assert "refuge" not in DEFAULT_KINDS[0]["pieces"]
|
|
|
|
|
added = add_kind(root, "내 평면도", ["centerline", "station", "nope"])
|
|
|
|
|
assert added["pieces"] == ["centerline", "station"]
|
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
|
add_kind(root, "내 평면도", ["centerline"]) # 같은 이름
|
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
|
add_kind(root, "빈 것", [])
|
|
|
|
|
delete_kind(root, "terrain") # 기본 넷도 지움
|
|
|
|
|
delete_kind(root, "terrain") # 기본 종류도 지움
|
|
|
|
|
again = list_kinds(root) # 다시 읽어 같음
|
|
|
|
|
assert [k["name"] for k in again] == [
|
|
|
|
|
"노선배치도",
|
|
|
|
|
"대피소",
|
|
|
|
|
"라이다",
|
|
|
|
|
"용지도",
|
|
|
|
|
"배수유역도",
|
|
|
|
|
"내 평면도",
|
|
|
|
|
]
|
|
|
|
|
assert [k["name"] for k in again] == ["내 평면도"]
|
|
|
|
|
assert again[-1]["pieces"] == ["centerline", "station"]
|
|
|
|
|
with pytest.raises(FileNotFoundError):
|
|
|
|
|
delete_kind(root, "terrain")
|
|
|
|
|
for kind in list(again):
|
|
|
|
|
delete_kind(root, kind["id"])
|
|
|
|
|
assert list_kinds(root) == [] # 다 지우면 비어 있음(기본 넷이 되살아나지 않음)
|
|
|
|
|
assert {k["id"] for k in DEFAULT_KINDS} == {
|
|
|
|
|
"terrain",
|
|
|
|
|
"route",
|
|
|
|
|
"layout",
|
|
|
|
|
"lidar",
|
|
|
|
|
"landuse",
|
|
|
|
|
"watershed",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_refuge_marks_same_spot(tmp_path: Path) -> None:
|
|
|
|
|
root = tmp_path / "project"
|
|
|
|
|
write_marks(root, [{"chainage_m": 20, "refuge": True, "spoil": True}, {"chainage_m": 5}])
|
|
|
|
|
assert read_marks(root) == [{"chainage_m": 20.0, "refuge": True, "spoil": True}]
|
|
|
|
|
route = [(0.0, 0.0, 0.0), (40.0, 0.0, 40.0)]
|
|
|
|
|
items = _refuge_items(root, route, 0.0, 40.0)["items"]
|
|
|
|
|
assert [item["label"] for item in items] == ["대피소 · 사토장"]
|
|
|
|
|
assert items[0]["y"] == pytest.approx(20.0)
|
|
|
|
|
delete_kind(root, again[0]["id"])
|
|
|
|
|
assert list_kinds(root) == [] # 다 지우면 비어 있음(기본이 되살아나지 않음)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_drawing_has_only_chosen_pieces() -> None:
|
|
|
|
@@ -223,23 +189,23 @@ def test_default_kinds_keep_old_picture_and_legacy_file(tmp_path: Path) -> None:
|
|
|
|
|
outline = {"road_edge", "fill_outline", "cut_outline"}
|
|
|
|
|
# 옛 slope_outline 자리를 나눈 셋이 그대로 채움 · 배수시설은 옛 그림에 없음(용지도는 따로)
|
|
|
|
|
for kind in DEFAULT_KINDS:
|
|
|
|
|
if kind["id"] not in ("landuse", "watershed"):
|
|
|
|
|
assert outline <= set(kind["pieces"]) and "drainage" not in kind["pieces"]
|
|
|
|
|
assert outline <= set(kind["pieces"]) and "drainage" not in kind["pieces"]
|
|
|
|
|
folder = _kinds_dir(root)
|
|
|
|
|
folder.mkdir(parents=True)
|
|
|
|
|
(folder / "old.json").write_text(
|
|
|
|
|
json.dumps({"name": "옛것", "pieces": ["slope_outline", "station"], "order": 0}), "utf-8"
|
|
|
|
|
)
|
|
|
|
|
kind = next(k for k in list_kinds(root) if k["id"] == "old") # 용지도는 이관으로 더해짐
|
|
|
|
|
kind = next(k for k in list_kinds(root) if k["id"] == "old")
|
|
|
|
|
assert set(kind["pieces"]) == outline | {"station"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_update_kind_default_and_release_confirmed(tmp_path: Path) -> None:
|
|
|
|
|
root = tmp_path / "project"
|
|
|
|
|
route = add_kind(root, "노선배치도", ["centerline"])["id"]
|
|
|
|
|
manifest = _read_manifest(root)
|
|
|
|
|
manifest["drawings"] = {
|
|
|
|
|
"plan_terrain": {"confirmed": True},
|
|
|
|
|
"plan_route": {"confirmed": True},
|
|
|
|
|
f"plan_{route}": {"confirmed": True},
|
|
|
|
|
}
|
|
|
|
|
_write_manifest(root, manifest)
|
|
|
|
|
update_kind(root, "terrain", "지형2", ["contour", "centerline"]) # 기본 종류 고침
|
|
|
|
@@ -254,7 +220,7 @@ def test_update_kind_default_and_release_confirmed(tmp_path: Path) -> None:
|
|
|
|
|
assert [k["id"] for k in list_kinds(root)][0] == "terrain" # 차례 그대로
|
|
|
|
|
drawings = _read_manifest(root)["drawings"]
|
|
|
|
|
assert drawings["plan_terrain"]["confirmed"] is False
|
|
|
|
|
assert drawings["plan_route"]["confirmed"] is True
|
|
|
|
|
assert drawings[f"plan_{route}"]["confirmed"] is True
|
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
|
update_kind(root, "terrain", "노선배치도", ["contour"]) # 다른 종류와 같은 이름
|
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
@@ -320,7 +286,6 @@ def test_ip_table_drawing_clips_lines_under_table(tmp_path: Path) -> None:
|
|
|
|
|
assert ip["cells"][2][2]["text"] == "100.00000" # Y = 동(x)
|
|
|
|
|
assert ip["cells"][3][1]["text"] == "90-00-00.00"
|
|
|
|
|
assert {layer["id"] for layer in drawing["layers"]} >= {layer_id("ip_table")}
|
|
|
|
|
assert "ip_table" in next(k for k in DEFAULT_KINDS if k["id"] == "route")["pieces"]
|
|
|
|
|
# DXF — 표 → 선 + 글(IP 묶음: 바깥 4 · 세로 10 · 가로 20 · 글 17)
|
|
|
|
|
raw, skipped = drawing_to_dxf({"entities": [mine[1]], "layers": drawing["layers"]})
|
|
|
|
|
(tmp_path / "ip.dxf").write_bytes(raw)
|
|
|
|
@@ -329,22 +294,6 @@ def test_ip_table_drawing_clips_lines_under_table(tmp_path: Path) -> None:
|
|
|
|
|
assert {"90-00-00.00", "15.00000"} <= {t.dxf.text for t in space.query("TEXT")}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_landuse_kind_added_once_to_old_folder(tmp_path: Path) -> None:
|
|
|
|
|
root = tmp_path / "project"
|
|
|
|
|
folder = _kinds_dir(root)
|
|
|
|
|
folder.mkdir(parents=True)
|
|
|
|
|
for order, kind in enumerate(DEFAULT_KINDS[:4]): # 93장 앞에 내려 둔 기본 넷
|
|
|
|
|
(folder / f"{kind['id']}.json").write_text(
|
|
|
|
|
json.dumps({"name": kind["name"], "pieces": kind["pieces"], "order": order}), "utf-8"
|
|
|
|
|
)
|
|
|
|
|
kinds = list_kinds(root)
|
|
|
|
|
assert [k["id"] for k in kinds][-2:] == ["landuse", "watershed"] # 늘어난 기본 종류 둘
|
|
|
|
|
assert kinds[-2]["pieces"] == ["contour", "centerline", "parcel", "parcel_info", "emd", "sgg"]
|
|
|
|
|
assert len(list_kinds(root)) == 6 # 두 번 읽어도 한 번
|
|
|
|
|
delete_kind(root, "landuse")
|
|
|
|
|
assert "landuse" not in [k["id"] for k in list_kinds(root)] # 지운 것은 안 살아남
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_landuse_pieces_become_layers() -> None:
|
|
|
|
|
pieces = {
|
|
|
|
|
"parcel": {"lines": [[[0.0, 0.0], [10.0, 0.0]]]},
|
|
|
|
@@ -370,11 +319,11 @@ def test_landuse_pieces_become_layers() -> None:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_watershed_kind_layout_one_sheet(tmp_path: Path) -> None:
|
|
|
|
|
"""배수유역도 = 기본 종류 · 양식 watershed · 조각 없음 · 장이 여럿이어도 목록은 한 장."""
|
|
|
|
|
"""배수유역도 = 새 종류 · 양식 watershed · 조각 없음 · 장이 여럿이어도 목록은 한 장."""
|
|
|
|
|
root = tmp_path / "project"
|
|
|
|
|
watershed = next(k for k in list_kinds(root) if k["id"] == "watershed")
|
|
|
|
|
assert watershed == {
|
|
|
|
|
"id": "watershed",
|
|
|
|
|
added = add_kind(root, "배수유역도", [], "watershed")
|
|
|
|
|
assert next(k for k in list_kinds(root) if k["id"] == added["id"]) == {
|
|
|
|
|
"id": added["id"],
|
|
|
|
|
"name": "배수유역도",
|
|
|
|
|
"pieces": [],
|
|
|
|
|
"layout": "watershed",
|
|
|
|
@@ -387,13 +336,13 @@ def test_watershed_kind_layout_one_sheet(tmp_path: Path) -> None:
|
|
|
|
|
]
|
|
|
|
|
items = plan_kind_items(root, {"stations": stations})
|
|
|
|
|
terrain = [item for item in items if item["plan_kind"] == "terrain"]
|
|
|
|
|
mine = [item for item in items if item["plan_kind"] == "watershed"]
|
|
|
|
|
mine = [item for item in items if item["plan_kind"] == added["id"]]
|
|
|
|
|
assert len(terrain) > 1
|
|
|
|
|
assert mine == [
|
|
|
|
|
{
|
|
|
|
|
"id": "plan_watershed",
|
|
|
|
|
"id": f"plan_{added['id']}",
|
|
|
|
|
"label": "배수유역도",
|
|
|
|
|
"plan_kind": "watershed",
|
|
|
|
|
"plan_kind": added["id"],
|
|
|
|
|
"plan_kind_name": "배수유역도",
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
@@ -402,9 +351,10 @@ def test_watershed_kind_layout_one_sheet(tmp_path: Path) -> None:
|
|
|
|
|
def test_watershed_kind_delete_and_add_again(tmp_path: Path) -> None:
|
|
|
|
|
"""× 로 지우면 안 살아남 · 「새 종류」 양식 유역도로 다시 만듦 · 업데이트는 양식 그대로."""
|
|
|
|
|
root = tmp_path / "project"
|
|
|
|
|
delete_kind(root, "watershed")
|
|
|
|
|
assert "watershed" not in [k["id"] for k in list_kinds(root)]
|
|
|
|
|
assert "watershed" not in [k["id"] for k in list_kinds(root)] # 다시 읽어도 안 살아남
|
|
|
|
|
first = add_kind(root, "배수유역도", [], "watershed")
|
|
|
|
|
delete_kind(root, first["id"])
|
|
|
|
|
assert first["id"] not in [k["id"] for k in list_kinds(root)]
|
|
|
|
|
assert first["id"] not in [k["id"] for k in list_kinds(root)] # 다시 읽어도 안 살아남
|
|
|
|
|
added = add_kind(root, "배수유역도", ["contour"], "watershed") # 조각은 버림
|
|
|
|
|
assert added["layout"] == "watershed" and added["pieces"] == []
|
|
|
|
|
again = next(k for k in list_kinds(root) if k["id"] == added["id"])
|
|
|
|
@@ -418,21 +368,6 @@ def test_watershed_kind_delete_and_add_again(tmp_path: Path) -> None:
|
|
|
|
|
add_kind(root, "이상한 양식", ["contour"], "nope")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_watershed_kind_added_once_to_folder_with_landuse(tmp_path: Path) -> None:
|
|
|
|
|
"""용지도 표시가 있는 옛 폴더 — 배수유역도만 한 번 더해짐 · 지우면 안 살아남."""
|
|
|
|
|
root = tmp_path / "project"
|
|
|
|
|
folder = _kinds_dir(root)
|
|
|
|
|
folder.mkdir(parents=True)
|
|
|
|
|
for order, kind in enumerate(DEFAULT_KINDS[:5]):
|
|
|
|
|
(folder / f"{kind['id']}.json").write_text(
|
|
|
|
|
json.dumps({"name": kind["name"], "pieces": kind["pieces"], "order": order}), "utf-8"
|
|
|
|
|
)
|
|
|
|
|
(folder / "_landuse_added").touch()
|
|
|
|
|
assert [k["id"] for k in list_kinds(root)][-1] == "watershed"
|
|
|
|
|
delete_kind(root, "watershed")
|
|
|
|
|
assert [k["id"] for k in list_kinds(root)][-1] == "landuse"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_ip_table_two_lines_left_to_right_top_to_bottom() -> None:
|
|
|
|
|
"""한 줄 셋까지 들어가는 폭 · 묶음 넷 — 첫 줄(1 · 2 · 3) 맨 위 왼 → 오 · 넷째는 아랫줄 왼쪽."""
|
|
|
|
|
blocks = [{"name": str(i), "ia": 1.0} for i in range(1, 5)]
|
|
|
|
@@ -449,22 +384,23 @@ def test_ip_table_two_lines_left_to_right_top_to_bottom() -> None:
|
|
|
|
|
|
|
|
|
|
def test_reorder_kinds_order_and_release_renumbered(tmp_path: Path) -> None:
|
|
|
|
|
root = tmp_path / "project"
|
|
|
|
|
second, third = (add_kind(root, name, ["centerline"])["id"] for name in ("둘째", "셋째"))
|
|
|
|
|
manifest = _read_manifest(root)
|
|
|
|
|
manifest["drawings"] = {
|
|
|
|
|
"plan_terrain": {"confirmed": True},
|
|
|
|
|
"plan_route": {"confirmed": True},
|
|
|
|
|
"plan_layout": {"confirmed": True},
|
|
|
|
|
f"plan_{second}": {"confirmed": True},
|
|
|
|
|
f"plan_{third}": {"confirmed": True},
|
|
|
|
|
}
|
|
|
|
|
_write_manifest(root, manifest)
|
|
|
|
|
before = [k["id"] for k in list_kinds(root)]
|
|
|
|
|
assert before[:3] == ["terrain", "route", "layout"]
|
|
|
|
|
after = ["route", "terrain", *before[2:]] # 앞 둘만 바꿈
|
|
|
|
|
assert before == ["terrain", second, third]
|
|
|
|
|
after = [second, "terrain", third] # 앞 둘만 바꿈
|
|
|
|
|
reorder_kinds(root, after)
|
|
|
|
|
assert [k["id"] for k in list_kinds(root)] == after # 다시 읽어 같음
|
|
|
|
|
drawings = _read_manifest(root)["drawings"]
|
|
|
|
|
assert drawings["plan_terrain"]["confirmed"] is False # 번호 바뀜
|
|
|
|
|
assert drawings["plan_route"]["confirmed"] is False
|
|
|
|
|
assert drawings["plan_layout"]["confirmed"] is True # 앞선 종류 묶음 그대로 = 번호 그대로
|
|
|
|
|
assert drawings[f"plan_{second}"]["confirmed"] is False
|
|
|
|
|
assert drawings[f"plan_{third}"]["confirmed"] is True # 앞선 종류 묶음 그대로 = 번호 그대로
|
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
|
reorder_kinds(root, after[:-1]) # 빠진 종류
|
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
|