Files
Aislo/resources/tester/test_b07_frame_import_shapes.py
T
eomsangdonandClaude Opus 5.5 04dd8cd012 fix(B07): 도면 불러오기 — bulge 호 · OCS 거울 블록 · TEXT 정렬점 · 겹 블록 풂(84-2)
- LWPOLYLINE/POLYLINE 은 ezdxf path.make_path().flattening(0.2) 로 — bulge 호 마디 펴짐 · 압출 −Z 는 WCS 로
- TEXT 는 get_placement 정렬점 · OCS → WCS · 가로 정렬(왼 · 가운데 · 오른) · MTEXT 붙임점 가로 정렬
- INSERT 속 INSERT 까지 풂(16 겹 한도)
- 견본 DXF 시험(호 · bulge · 거울 블록 · 겹 블록 · TEXT 정렬) — 옛 코드에선 넷 실패

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UoSr2sqvYtBf1dtQdus88s
2026-10-08 12:07:53 +09:00

136 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""B07 도면 불러오기 — 호 · bulge 폴리선 · 거울 블록 · 겹 블록 견본 DXF(84-2) · 내보내기 시계방향 호(84-3).
견본은 ezdxf 로 그 자리에서 만들어 끌어다 놓기 길(`drawing_file_to_entities`)로 읽는다.
"""
from __future__ import annotations
import io
import math
import ezdxf
from ezdxf.enums import TextEntityAlignment
from B07_DesignDetail import B07_DesignDetail_Engine_Frame_Export as export
from B07_DesignDetail.B07_DesignDetail_Engine_Frame_Import import drawing_file_to_entities
def _read(doc: ezdxf.document.Drawing) -> list[dict]:
stream = io.StringIO()
doc.write(stream)
entities, _layers = drawing_file_to_entities("견본.dxf", stream.getvalue().encode("utf-8"))
return entities
def _points(polyline: dict) -> list[tuple[float, float]]:
children = polyline["children"]
points = [
(c["shapeData"]["startPoint"]["x"], c["shapeData"]["startPoint"]["y"]) for c in children
]
last = children[-1]["shapeData"]["endPoint"]
return [*points, (last["x"], last["y"])]
def _on_circle(points, cx: float, cy: float, r: float) -> bool:
return all(abs(math.hypot(x - cx, y - cy) - r) < 0.21 for x, y in points)
def test_호는_1사분면_작은_호():
doc = ezdxf.new()
doc.modelspace().add_arc((0, 0), 10, 0, 90)
(arc,) = _read(doc)
points = _points(arc)
assert _on_circle(points, 0, 0, 10)
assert points[0] == (10.0, 0.0) and math.isclose(points[-1][0], 0, abs_tol=1e-9)
assert all(x >= -1e-9 and y >= -1e-9 for x, y in points) # 큰 호(270°)로 뒤집히지 않음
def test_bulge_폴리선은_호로_펴짐():
doc = ezdxf.new()
space = doc.modelspace()
# 반원(bulge 1 · 반시계 → 아래로) · 작은 호(bulge −0.2 · 시계 → 위로 1)
space.add_lwpolyline([(0, 0, 0, 0, 1), (10, 0)], format="xyseb")
space.add_lwpolyline([(0, 20, 0, 0, -0.2), (10, 20)], format="xyseb")
half, small = _read(doc)
half_points = _points(half)
assert len(half_points) > 3 and _on_circle(half_points, 5, 0, 5)
assert min(y for _x, y in half_points) < -4.9
small_points = _points(small)
assert len(small_points) > 3
assert math.isclose(max(y for _x, y in small_points), 21.0, abs_tol=0.01) # 처짐 = 0.2 × 10 / 2
assert min(y for _x, y in small_points) >= 20 - 1e-9
def test_거울_블록은_WCS_자리():
doc = ezdxf.new()
block = doc.blocks.new("거울")
block.add_lwpolyline([(0, 0, 0, 0, -0.2), (10, 0)], format="xyseb")
block.add_arc((20, 0), 2, 0, 90)
block.add_text("가", dxfattribs={"height": 2.5}).set_placement((2, 3))
doc.modelspace().add_blockref("거울", (100, 0), dxfattribs={"xscale": -1})
by_type: dict[str, list[dict]] = {}
for entity in _read(doc):
by_type.setdefault(entity["type"], []).append(entity)
bulge, arc = by_type["PolyLine"]
bulge_points = _points(bulge)
assert (
min(x for x, _y in bulge_points) >= 90 - 1e-9
and max(x for x, _y in bulge_points) <= 100 + 1e-9
)
assert math.isclose(max(y for _x, y in bulge_points), 1.0, abs_tol=0.01) # 위로 그대로
arc_points = _points(arc)
assert _on_circle(arc_points, 80, 0, 2)
assert all(x <= 80 + 1e-9 and y >= -1e-9 for x, y in arc_points) # 2사분면으로 대칭
(text,) = by_type["Text"]
assert text["shapeData"]["basePoint"] == {"x": 98.0, "y": 3.0}
def test_겹_블록도_풀림():
doc = ezdxf.new()
doc.blocks.new("속").add_line((0, 0), (1, 0))
doc.blocks.new("겉").add_blockref("속", (5, 0))
doc.modelspace().add_blockref("겉", (10, 0))
(line,) = _read(doc)
assert line["type"] == "Line"
assert line["shapeData"] == {
"startPoint": {"x": 15.0, "y": 0.0},
"endPoint": {"x": 16.0, "y": 0.0},
}
def test_TEXT_정렬점_자리():
doc = ezdxf.new()
space = doc.modelspace()
space.add_text("가운데", dxfattribs={"height": 2}).set_placement(
(50, 5), align=TextEntityAlignment.MIDDLE_CENTER
)
space.add_text("오른", dxfattribs={"height": 2}).set_placement(
(80, 5), align=TextEntityAlignment.BOTTOM_RIGHT
)
center, right = _read(doc)
assert center["shapeData"]["basePoint"] == {"x": 50.0, "y": 5.0}
assert center["shapeData"]["options"]["textAlign"] == "center"
assert right["shapeData"]["basePoint"] == {"x": 80.0, "y": 5.0}
assert right["shapeData"]["options"]["textAlign"] == "right"
def test_내보내기_시계방향_작은_호(tmp_path):
arc = {
"type": "Arc",
"layerId": "기본",
"shapeData": {
"center": {"x": 0, "y": 0},
"radius": 1,
"startAngle": math.pi / 2,
"endAngle": 0,
"counterClockwise": False,
},
}
raw, skipped = export.drawing_to_dxf({"entities": [arc], "layers": []})
assert skipped == {}
path = tmp_path / "out.dxf"
path.write_bytes(raw)
(out,) = ezdxf.readfile(path).modelspace().query("ARC")
span = (out.dxf.end_angle - out.dxf.start_angle) % 360
assert math.isclose(span, 90) and math.isclose(out.dxf.start_angle % 360, 0, abs_tol=1e-9)