- 기슭막이(돌쌓기형) — 돌쌓기 그림 그대로 · 기울기 판정 대상에 넣고 찰/메는 형태에서(표와 한 벌) - 골막이 — 정면 사다리꼴 · 방수로 관 · 바닥파기 띠 + 옆 단면 · 치수는 표와 같이 쓰는 erosion_check_section 한 벌로 뽑음(값 불변) - 떼흙막이 — 정본 평균 붙박이 치수(dims)로 · 그 치수로 표 두 줄(떼 1.39 · 바닥파기 0.17)이 다시 나오는지 시험 - 바닥막이 — 돌 켜 · 버림 · 기초잡석(산출 조건) · 터파기 · 표 사유에 새 한 줄 「터파기는 돌 두께만 — 버림·기초잡석은 판 깊이에 안 들어감」을 그림도 같이 씀 - 표가 안 선 장은 표 사유를 그대로 까닭으로 · 개거 둘은 원문끼리 치수가 달라서/단면 그림이 없어서 까닭 - 화면 확인: 검증 프로젝트 936be972 에 넷을 잠깐 놓았다 되돌림(구조물 5개 원본과 같음 · 단계 상태 그대로 · 내역 124,424,547 그대로) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016VBGFXB9AbJBwXP19z75Qq
214 lines
8.5 KiB
Python
214 lines
8.5 KiB
Python
"""구조물도 상단 그림 — **골막이 · 떼흙막이 · 바닥막이** (정본 개소당·㎡당 구조물, PLAN 12장).
|
||
|
||
⚠ 치수는 **표가 쓴 그 한 벌**에서 읽음 — 골막이 `erosion_check_section` ·
|
||
떼흙막이 `SOIL_GUARD_SOD.dims` · 바닥막이 `BED_SILL_FORMS` + 산출 조건 기초잡석 두께.
|
||
⚠ 사유 글자도 표 사유와 같은 상수(`BED_SILL_TRENCH_NOTE` 등).
|
||
⚠ 좌표는 m · 위가 +y · 모양 목록 규약은 `B08_Quantity_Engine_StructureFigure` 와 같음.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import math
|
||
from typing import Any
|
||
|
||
from B08_Quantity.B08_Quantity_Engine_StructureFigure import (
|
||
_LABEL_SIZE,
|
||
SCALE_MM_PER_M,
|
||
_path,
|
||
_text,
|
||
)
|
||
|
||
|
||
def _title(sheet: dict[str, Any], y: float) -> dict[str, Any]:
|
||
return _text(
|
||
f"{sheet.get('title') or ''} (축척 1/{int(1000 / SCALE_MM_PER_M)})",
|
||
(0.0, y),
|
||
"left",
|
||
_LABEL_SIZE,
|
||
)
|
||
|
||
|
||
def _front_with_trench(
|
||
top: float, bottom: float, height: float, depth: float, x0: float = 0.0
|
||
) -> list[dict[str, Any]]:
|
||
"""정면 사다리꼴(윗변 `top` · 밑변 `bottom` 가운데 정렬) + 사면 둘·밑변을 따라 판 띠(점선)."""
|
||
inset = (top - bottom) / 2
|
||
corners = [(x0, height), (x0 + inset, 0.0), (x0 + inset + bottom, 0.0), (x0 + top, height)]
|
||
shapes = [_path(corners + [corners[0]], "wall")]
|
||
if depth > 0:
|
||
# 사면 둘·밑변을 바깥으로 `depth` 만큼 민 선 — 이웃 변의 교점으로 잇음.
|
||
normals = []
|
||
for (ax, ay), (bx, by) in zip(corners[:3], corners[1:4]):
|
||
length = math.hypot(bx - ax, by - ay)
|
||
normals.append(((by - ay) / length, -(bx - ax) / length))
|
||
offset = []
|
||
for index, (px, py) in enumerate(corners):
|
||
used = [normals[i] for i in (index - 1, index) if 0 <= i < 3]
|
||
nx = sum(n[0] for n in used)
|
||
ny = sum(n[1] for n in used)
|
||
dot = used[0][0] * nx + used[0][1] * ny
|
||
offset.append((px + nx * depth / dot, py + ny * depth / dot))
|
||
shapes.append(_path(offset, "guide", dash=True))
|
||
return shapes
|
||
|
||
|
||
def _circle(cx: float, cy: float, r: float) -> list[tuple[float, float]]:
|
||
return [
|
||
(cx + r * math.cos(math.tau * i / 24), cy + r * math.sin(math.tau * i / 24))
|
||
for i in range(25)
|
||
]
|
||
|
||
|
||
def erosion_check_figure(sheet: dict[str, Any]) -> list[dict[str, Any]]:
|
||
"""골막이 — 정면(사다리꼴 · 방수로 관 · 바닥파기 띠) + 옆 단면(상부·하부 두께)."""
|
||
from B08_Quantity.B08_Quantity_Engine_UnitQuantity_Revetment import erosion_check_section
|
||
|
||
geo = erosion_check_section(float(sheet.get("height_m") or 0.0), sheet.get("options") or {})
|
||
top, bottom, height = geo["top_m"], geo["bottom_m"], geo["height_m"]
|
||
shapes = _front_with_trench(top, bottom, height, geo["trench_depth"])
|
||
if geo["spillway"]:
|
||
shapes.append(_path(_circle(top / 2, geo["pipe_r"], geo["pipe_r"]), "guide"))
|
||
# 옆 단면 — 뒷면 수직 · 앞면이 하부 두께에서 상부 두께로 좁아짐(표의 두께식 그대로).
|
||
x0 = top + 1.2
|
||
shapes.append(
|
||
_path(
|
||
[
|
||
(x0, 0.0),
|
||
(x0, height),
|
||
(x0 + geo["top_t"], height),
|
||
(x0 + geo["bottom_t"], 0.0),
|
||
(x0, 0.0),
|
||
],
|
||
"wall",
|
||
)
|
||
)
|
||
right = x0 + geo["bottom_t"] + 0.3
|
||
shapes += [
|
||
_title(sheet, height + 0.55),
|
||
_text(f"상장 ⓐ {top:g} m", (top / 2, height + 0.14), "center"),
|
||
_text(f"하장 ⓑ {bottom:g} m", (top / 2, -geo["trench_depth"] - 0.18), "center"),
|
||
_text(f"H = {height:g} m", (-0.3 - geo["trench_depth"], height / 2), "right"),
|
||
_text(
|
||
f"상부 {geo['top_t']:.2f} · 하부 {geo['bottom_t']:.2f} · 평균 {geo['thickness']:.2f} m"
|
||
f" (뒷길이 {geo['back_cm']}㎝ + 0.1H / 0.4H)",
|
||
(right, height * 0.85),
|
||
"left",
|
||
),
|
||
_text(f"반수면 1:{geo['slope']:g}", (right, height * 0.62), "left"),
|
||
_text(
|
||
f"바닥파기 폭 {geo['trench_width']:.2f} × 깊이 {geo['trench_depth']:g} m"
|
||
f" (사면장 {geo['slant']:g} × 2 + 하장)",
|
||
(right, height * 0.39),
|
||
"left",
|
||
),
|
||
]
|
||
if geo["spillway"]:
|
||
shapes.append(
|
||
_text(
|
||
f"방수로 파형강관 Ø{geo['pipe_r'] * 2:g} — 정면적에서 뺌",
|
||
(right, height * 0.16),
|
||
"left",
|
||
)
|
||
)
|
||
return shapes
|
||
|
||
|
||
def soil_guard_figure(sheet: dict[str, Any]) -> list[dict[str, Any]]:
|
||
"""떼흙막이 — 정본 평균 붙박이 치수의 정면(떼 두께 · 바닥파기 띠)."""
|
||
from B08_Quantity.B08_Quantity_Engine_UnitQuantity_Revetment import SOIL_GUARD_SOD
|
||
|
||
d = SOIL_GUARD_SOD["dims"]
|
||
top, bottom, height = d["top_m"], d["bottom_m"], d["height_m"]
|
||
shapes = _front_with_trench(top, bottom, height, d["trench_depth_m"])
|
||
# 머리떼 — 윗변 위 떼 한 켜(두께 = 떼 폭 0.2 로 보임).
|
||
shapes.append(
|
||
_path(
|
||
[(0.0, height), (0.0, height + d["sod_m"]), (top, height + d["sod_m"]), (top, height)],
|
||
"guide",
|
||
)
|
||
)
|
||
right = top + 0.4
|
||
shapes += [
|
||
_title(sheet, height + d["sod_m"] + 0.45),
|
||
_text(f"상단 {top:g} m", (top / 2, height + d["sod_m"] + 0.12), "center"),
|
||
_text(f"하단 {bottom:g} m", (top / 2, -d["trench_depth_m"] - 0.15), "center"),
|
||
_text(f"H = {height:g} m", (-0.3, height / 2), "right"),
|
||
_text(
|
||
f"떼 20×20㎝ · 폭 {d['sod_m']:g} · 기슭(사면장) {d['slant_m']:g} m",
|
||
(right, height * 0.9),
|
||
"left",
|
||
),
|
||
_text(
|
||
f"바닥파기 폭 {d['trench_width_m']:g} × 깊이 {d['trench_depth_m']:g} m"
|
||
" (기슭 × 2 + 하단)",
|
||
(right, height * 0.45),
|
||
"left",
|
||
),
|
||
_text("치수 — 정본 「떼흙막이」 평균 붙박이(개소 제원을 안 봄)", (right, 0.0), "left"),
|
||
]
|
||
return shapes
|
||
|
||
|
||
def bed_sill_figure(
|
||
sheet: dict[str, Any], rubble_thickness_m: float | None
|
||
) -> list[dict[str, Any]]:
|
||
"""바닥막이(돌붙임) — ㎡당 한 칸의 단면: 돌 켜 · (찰) 버림 · 기초잡석 · 터파기(돌 두께만)."""
|
||
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import RUBBLE_BASE_THICKNESS_M
|
||
from B08_Quantity.B08_Quantity_Engine_UnitQuantity_Revetment import (
|
||
BED_SILL_FORMS,
|
||
BED_SILL_TRENCH_NOTE,
|
||
)
|
||
|
||
form = str((sheet.get("options") or {}).get("form") or "").strip()
|
||
table = BED_SILL_FORMS[form]
|
||
back = table["back_len_m"]
|
||
blinding = table["blinding_m3_per_m2"] or 0.0 # ㎥/㎡ = 두께(m)
|
||
rubble = RUBBLE_BASE_THICKNESS_M if rubble_thickness_m is None else float(rubble_thickness_m)
|
||
rubble = rubble if blinding > 0 else 0.0 # 표도 버림이 선 곳에만 기초잡석을 세움
|
||
width = 1.0
|
||
shapes = [_path([(0.0, 0.0), (0.0, back), (width, back), (width, 0.0), (0.0, 0.0)], "wall")]
|
||
if blinding > 0:
|
||
shapes.append(
|
||
_path([(0.0, 0.0), (0.0, -blinding), (width, -blinding), (width, 0.0)], "guide")
|
||
)
|
||
if rubble > 0:
|
||
shapes.append(
|
||
_path(
|
||
[
|
||
(0.0, -blinding),
|
||
(0.0, -blinding - rubble),
|
||
(width, -blinding - rubble),
|
||
(width, -blinding),
|
||
],
|
||
"guide",
|
||
dash=True,
|
||
)
|
||
)
|
||
# 터파기 — 표 식 그대로 면적 × 돌 두께(윗면에서 돌 켜 밑까지).
|
||
shapes.append(
|
||
_path(
|
||
[(-0.15, back), (-0.15, 0.0), (width + 0.15, 0.0), (width + 0.15, back)],
|
||
"guide",
|
||
dash=True,
|
||
)
|
||
)
|
||
right = width + 0.4
|
||
shapes += [
|
||
_title(sheet, back + 0.4),
|
||
_text(
|
||
f"{form} — 두께(뒷길이) {back:g} m · {table['stone_spec']}",
|
||
(right, back * 0.75),
|
||
"left",
|
||
),
|
||
_text("폭 1 m 당(표는 ㎡당)", (width / 2, back + 0.12), "center"),
|
||
_text(f"터파기 깊이 {back:g} m (면적 × 두께)", (right, back * 0.3), "left"),
|
||
]
|
||
if blinding > 0:
|
||
shapes.append(_text(f"버림 T={blinding:g} m", (right, -blinding / 2), "left"))
|
||
if rubble > 0:
|
||
shapes.append(
|
||
_text(f"기초잡석 T={rubble:g} m — 산출 조건", (right, -blinding - rubble / 2), "left")
|
||
)
|
||
shapes.append(_text(BED_SILL_TRENCH_NOTE, (0.0, -blinding - rubble - 0.25), "left"))
|
||
return shapes
|