fix(B07): 유역 해칭·번호 배지를 넣고 토적도 balloon 숫자를 뺀다
화면 실측에서 나온 지적 세 가지를 반영했다. - 세부유역에 격자 해칭(Hatch style=cross, 유역색)을 넣는다. openwebcad Hatch 엔티티라 CAD에서 무늬·간격을 그대로 편집할 수 있다. - 유역 번호를 동그라미 배지로 바꾼다 — 흰 원판(solid 해치) + 유역색 테두리 + 검은 숫자. 해칭 위에서도 읽히고, 화면(어두운 배경)·인쇄(흰 배경) 양쪽에서 남는다. 배지는 엔티티 목록 맨 뒤에 몰아 그려 뒤따르는 해칭·정보표에 가리지 않는다. - 토적도 balloon의 장비명 뒤 숫자를 뺀다. 납품 도면에는 "도자 11"처럼 붙지만 그 숫자의 정체가 확인되지 않았다(2026-08-30 사용자 확정 — 확인되면 붙인다). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,9 +14,12 @@
|
||||
좌표 규약: 종이 mm = (사업지 좌표 m - 콘텐츠 최소점) x MM (1/6,000 -> 1 m = 1/6 mm).
|
||||
"""
|
||||
|
||||
import math
|
||||
from typing import Any
|
||||
from uuid import uuid5
|
||||
|
||||
from B07_DesignDetail.B07_DesignDetail_Engine_Cad import (
|
||||
_ENTITY_NS,
|
||||
DRAWING_FORMAT,
|
||||
FRAME_LAYER_ID,
|
||||
TABLE_LABEL_COLOR,
|
||||
@@ -61,8 +64,18 @@ BASIN_COLORS = (
|
||||
"#b794f6",
|
||||
)
|
||||
|
||||
# 유역 채칭 — 납품 도면은 유역마다 격자 해칭이 들어간다(2026-08-30 사용자 지적).
|
||||
HATCH_STYLE = "cross"
|
||||
HATCH_SPACING_MM = 2.5
|
||||
HATCH_ANGLE_RAD = math.pi / 4
|
||||
|
||||
_FONT_SIZE = 2.2
|
||||
_NUMBER_FONT_SIZE = 4.0
|
||||
# 유역 번호는 해칭 위에 얹히므로 흰 원판을 깔고 그 안에 적는다(2026-08-30 사용자 지시).
|
||||
_NUMBER_FONT_SIZE = 4.5
|
||||
_BADGE_RADIUS_MM = 3.6
|
||||
_BADGE_FILL = "#ffffff"
|
||||
_BADGE_TEXT_COLOR = "#111111"
|
||||
_BADGE_SEGMENTS = 24
|
||||
_TITLE_FONT_SIZE = 7.0
|
||||
|
||||
# 구역별 정보표 치수(mm).
|
||||
@@ -124,6 +137,76 @@ def _diameter_label(props: dict[str, Any]) -> str:
|
||||
return "-"
|
||||
|
||||
|
||||
def _hatch_entity(
|
||||
drawing_id: str, number: int, ring: list[tuple[float, float]], color: str
|
||||
) -> dict[str, Any]:
|
||||
"""유역 안쪽 격자 해칭. openwebcad Hatch 엔티티라 CAD에서 무늬·간격을 그대로 편집한다."""
|
||||
return {
|
||||
"id": str(uuid5(_ENTITY_NS, f"{drawing_id}:basin:hatch:{number}")),
|
||||
"type": "Hatch",
|
||||
"lineColor": color,
|
||||
"lineWidth": 1,
|
||||
"layerId": BASIN_LAYER_ID,
|
||||
"shapeData": {
|
||||
"points": [{"x": x, "y": y} for x, y in ring],
|
||||
"options": {
|
||||
"style": HATCH_STYLE,
|
||||
"color": color,
|
||||
"spacing": HATCH_SPACING_MM,
|
||||
"angle": HATCH_ANGLE_RAD,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _number_badge_entities(
|
||||
drawing_id: str, number: int, center: tuple[float, float], color: str
|
||||
) -> list[dict[str, Any]]:
|
||||
"""유역 번호를 동그라미 배지로 그린다 — 흰 원판 + 유역색 테두리 + 검은 숫자.
|
||||
|
||||
해칭 위에 그냥 문자만 올리면 무늬에 묻혀 읽히지 않는다. 원판은 solid 해치라
|
||||
화면(어두운 배경)과 인쇄(흰 배경) 어느 쪽에서도 숫자가 남는다.
|
||||
"""
|
||||
cx, cy = center
|
||||
disc = [
|
||||
(
|
||||
cx + _BADGE_RADIUS_MM * math.cos(2 * math.pi * i / _BADGE_SEGMENTS),
|
||||
cy + _BADGE_RADIUS_MM * math.sin(2 * math.pi * i / _BADGE_SEGMENTS),
|
||||
)
|
||||
for i in range(_BADGE_SEGMENTS)
|
||||
]
|
||||
return [
|
||||
{
|
||||
"id": str(uuid5(_ENTITY_NS, f"{drawing_id}:basin:badge:fill:{number}")),
|
||||
"type": "Hatch",
|
||||
"lineColor": _BADGE_FILL,
|
||||
"lineWidth": 1,
|
||||
"layerId": BASIN_LAYER_ID,
|
||||
"shapeData": {
|
||||
"points": [{"x": x, "y": y} for x, y in disc],
|
||||
"options": {"style": "solid", "color": _BADGE_FILL, "spacing": 1, "angle": 0},
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": str(uuid5(_ENTITY_NS, f"{drawing_id}:basin:badge:ring:{number}")),
|
||||
"type": "Circle",
|
||||
"lineColor": color,
|
||||
"lineWidth": 1,
|
||||
"layerId": BASIN_LAYER_ID,
|
||||
"shapeData": {"center": {"x": cx, "y": cy}, "radius": _BADGE_RADIUS_MM},
|
||||
},
|
||||
_text_entity(
|
||||
f"{drawing_id}:basin:number:{number}",
|
||||
str(number),
|
||||
cx,
|
||||
cy,
|
||||
BASIN_LAYER_ID,
|
||||
_NUMBER_FONT_SIZE,
|
||||
_BADGE_TEXT_COLOR,
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def _info_box_entities(
|
||||
drawing_id: str,
|
||||
number: int,
|
||||
@@ -277,6 +360,7 @@ def build_watershed_drawing(
|
||||
entities.append(route)
|
||||
|
||||
map_bbox = entities_bbox(entities)
|
||||
badges: list[dict[str, Any]] = []
|
||||
for order, basin in enumerate(basins):
|
||||
ring = [paper(point) for point in basin.get("ring") or []]
|
||||
if len(ring) < 3:
|
||||
@@ -284,23 +368,14 @@ def build_watershed_drawing(
|
||||
props = basin.get("props") or {}
|
||||
number = int(props.get("index") or order + 1)
|
||||
color = BASIN_COLORS[(number - 1) % len(BASIN_COLORS)]
|
||||
entities.append(_hatch_entity(drawing_id, number, ring, color))
|
||||
outline = polyline_entity(
|
||||
drawing_id, [*ring, ring[0]], BASIN_LAYER_ID, color, suffix=f":basin:{number}"
|
||||
)
|
||||
if outline:
|
||||
entities.append(outline)
|
||||
center = _centroid(ring)
|
||||
entities.append(
|
||||
_text_entity(
|
||||
f"{drawing_id}:basin:number:{number}",
|
||||
f"({number})",
|
||||
center[0],
|
||||
center[1],
|
||||
BASIN_LAYER_ID,
|
||||
_NUMBER_FONT_SIZE,
|
||||
color,
|
||||
)
|
||||
)
|
||||
# 번호 배지는 맨 마지막에 몰아 그린다 — 뒤에 오는 유역 해칭·정보표에 가리면 안 된다.
|
||||
badges.extend(_number_badge_entities(drawing_id, number, _centroid(ring), color))
|
||||
|
||||
# 정보표는 지형 콘텐츠 오른쪽에 위에서부터 쌓는다.
|
||||
if map_bbox:
|
||||
@@ -323,6 +398,8 @@ def build_watershed_drawing(
|
||||
)
|
||||
)
|
||||
|
||||
entities.extend(badges) # 그리기 순서상 가장 위
|
||||
|
||||
bbox = entities_bbox(entities)
|
||||
if bbox:
|
||||
min_bx, _min_by, max_bx, max_by = bbox
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
- 제목 「유 토 곡 선」, 우측 상단 척도 표기(H=1:2,000 / V=1:50,000).
|
||||
- 좌측 세로축(빨강) + 5,000㎥ 눈금·라벨, 누가토량 0 기준선.
|
||||
- 유토곡선(자홍) + 블록 평형선(흰색) + 띠 경계현(노랑).
|
||||
- 띠마다 balloon(장비별 육각/타원/사각) — `장비 번호 / Q= / L= / EA= / RR= / BR=`.
|
||||
- 띠마다 balloon(장비별 육각/타원/사각) — `장비 / Q= / L= / EA= / RR= / BR=`.
|
||||
(납품 도면은 장비명 뒤에 숫자가 붙지만 정체 미확인이라 적지 않는다.)
|
||||
- 사토·토취 balloon — `사토 번호 / Q= / M.N= / EA= / RR= / BR=`.
|
||||
- 하단 2행 테이블: 누가토량(세로쓰기) / 측점(No. 표기).
|
||||
|
||||
@@ -279,8 +280,10 @@ def _band_entities(
|
||||
)
|
||||
equipment = str(band.get("equipment") or "")
|
||||
label = EQUIPMENT_LABEL.get(equipment, "운반")
|
||||
# 납품 도면은 장비명 뒤에 숫자가 붙지만(도자 11 등) 그 숫자의 정체가 확인되지
|
||||
# 않아 적지 않는다 (2026-08-30 사용자 확정 — 확인되면 그때 붙인다).
|
||||
lines = [
|
||||
f"{label} {index}",
|
||||
label,
|
||||
f"Q={_format(_number(band.get('volume_m3')))}M3",
|
||||
f"L={_format(_number(band.get('haul_distance_m')))}M",
|
||||
f"EA={_format(_number(band.get('ea_m3')))}M3",
|
||||
|
||||
Reference in New Issue
Block a user