From 93f7786c629e651443e8cb0d98d17025682acc5d Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 30 Aug 2026 13:31:44 +0900 Subject: [PATCH] =?UTF-8?q?fix(B07):=20=EC=9C=A0=EC=97=AD=20=ED=95=B4?= =?UTF-8?q?=EC=B9=AD=C2=B7=EB=B2=88=ED=98=B8=20=EB=B0=B0=EC=A7=80=EB=A5=BC?= =?UTF-8?q?=20=EB=84=A3=EA=B3=A0=20=ED=86=A0=EC=A0=81=EB=8F=84=20balloon?= =?UTF-8?q?=20=EC=88=AB=EC=9E=90=EB=A5=BC=20=EB=BA=80=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 화면 실측에서 나온 지적 세 가지를 반영했다. - 세부유역에 격자 해칭(Hatch style=cross, 유역색)을 넣는다. openwebcad Hatch 엔티티라 CAD에서 무늬·간격을 그대로 편집할 수 있다. - 유역 번호를 동그라미 배지로 바꾼다 — 흰 원판(solid 해치) + 유역색 테두리 + 검은 숫자. 해칭 위에서도 읽히고, 화면(어두운 배경)·인쇄(흰 배경) 양쪽에서 남는다. 배지는 엔티티 목록 맨 뒤에 몰아 그려 뒤따르는 해칭·정보표에 가리지 않는다. - 토적도 balloon의 장비명 뒤 숫자를 뺀다. 납품 도면에는 "도자 11"처럼 붙지만 그 숫자의 정체가 확인되지 않았다(2026-08-30 사용자 확정 — 확인되면 붙인다). Co-Authored-By: Claude Opus 5 (1M context) --- .../B07_DesignDetail_Engine_Cad_Basin.py | 103 +++++++++++++++--- .../B07_DesignDetail_Engine_Cad_MassHaul.py | 7 +- 2 files changed, 95 insertions(+), 15 deletions(-) diff --git a/B07_DesignDetail/B07_DesignDetail_Engine_Cad_Basin.py b/B07_DesignDetail/B07_DesignDetail_Engine_Cad_Basin.py index 5992b806..c1e63af0 100644 --- a/B07_DesignDetail/B07_DesignDetail_Engine_Cad_Basin.py +++ b/B07_DesignDetail/B07_DesignDetail_Engine_Cad_Basin.py @@ -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 diff --git a/B07_DesignDetail/B07_DesignDetail_Engine_Cad_MassHaul.py b/B07_DesignDetail/B07_DesignDetail_Engine_Cad_MassHaul.py index 84df1723..327cc2c8 100644 --- a/B07_DesignDetail/B07_DesignDetail_Engine_Cad_MassHaul.py +++ b/B07_DesignDetail/B07_DesignDetail_Engine_Cad_MassHaul.py @@ -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",