⚠ **뿌리** — `tmp/` 는 창 사이에 안 건너감(실측 확인: 상대 창이 놓은 `tmp/_sync_probe.txt` 가 시간을 두고 두 번 봐도 안 보임). 그래서 **정본(등록부 스키마)만 건너가고 그것을 읽는 시험은 안 건너가** 오늘 두 번, 같은 시험이 **연 창은 통과·받은 창은 실패**가 됐음. - `tmp/tests/*` 를 `resources/tester/` 로 **복사**(127 파일). 내용은 **한 줄도 안 고침** - `tmp/tests` 는 **남겨 둠** — 되돌릴 자리(사용자 지시) - 실행: `./venv/Scripts/python.exe -m pytest resources/tester/ -q` 옮기기 전과 **같은 수**: 617 통과 / 22 건너뜀 / 실패 0 ⇒ 이제 시험·예외·까닭이 **정본과 함께** 움직임. 오늘 세운 「예외는 정본 스키마에」와 짝임. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
74 lines
2.6 KiB
Python
74 lines
2.6 KiB
Python
"""표제란 SVG 서명을 CAD 폴리선으로 바꾸는 경로 검사 (2026-09-03 사용자 결정).
|
|
|
|
종전에는 `ImageEntity`(data URL)로 들어가 DXF 로 나가면 래스터가 됐다. SVG 만 벡터로
|
|
바꾸고 PNG·JPG 는 그대로 그림으로 둔다.
|
|
"""
|
|
|
|
from base64 import b64encode
|
|
|
|
from B07_DesignDetail.B07_DesignDetail_Engine_Cad_Svg import fit_polylines, svg_polylines
|
|
from B07_DesignDetail.B07_DesignDetail_Engine_Template import _vectorize_svg_image
|
|
|
|
SIGN_SVG = (
|
|
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 50">'
|
|
'<path d="M 10 40 L 30 10 L 50 40"/>'
|
|
'<polyline points="60,10 90,10 90,40"/>'
|
|
"</svg>"
|
|
)
|
|
|
|
|
|
def _image_entity(payload: str, mime: str = "image/svg+xml") -> dict:
|
|
return {
|
|
"id": "sign-1",
|
|
"type": "Image",
|
|
"lineColor": "#101010",
|
|
"lineWidth": 1,
|
|
"layerId": "title",
|
|
"shapeData": {
|
|
"points": [
|
|
{"x": 10.0, "y": 20.0},
|
|
{"x": 50.0, "y": 20.0},
|
|
{"x": 50.0, "y": 40.0},
|
|
{"x": 10.0, "y": 40.0},
|
|
],
|
|
"imageData": f"data:{mime};base64,{b64encode(payload.encode()).decode()}",
|
|
},
|
|
}
|
|
|
|
|
|
def test_svg_polylines_reads_path_and_polyline():
|
|
view_box, runs = svg_polylines(SIGN_SVG)
|
|
assert view_box == (0.0, 0.0, 100.0, 50.0)
|
|
assert len(runs) == 2
|
|
assert runs[0][0] == (10.0, 40.0) and runs[0][-1] == (50.0, 40.0)
|
|
|
|
|
|
def test_fit_keeps_aspect_and_flips_y():
|
|
"""비율을 지키고 세로를 뒤집는다 — SVG 는 y 가 아래로, 도면은 위로 자란다."""
|
|
view_box, runs = svg_polylines(SIGN_SVG)
|
|
fitted = fit_polylines(runs, view_box, (10.0, 20.0, 50.0, 40.0))
|
|
xs = [x for run in fitted for x, _y in run]
|
|
ys = [y for run in fitted for _x, y in run]
|
|
assert 10.0 - 1e-9 <= min(xs) and max(xs) <= 50.0 + 1e-9
|
|
assert 20.0 - 1e-9 <= min(ys) and max(ys) <= 40.0 + 1e-9
|
|
# SVG 에서 y=10(위)이던 꼭짓점이 도면에서는 가장 높은 y 가 된다.
|
|
assert fitted[0][1][1] > fitted[0][0][1]
|
|
|
|
|
|
def test_image_entity_becomes_polylines():
|
|
result = _vectorize_svg_image(_image_entity(SIGN_SVG))
|
|
assert all(entity["type"] == "PolyLine" for entity in result)
|
|
assert len(result) == 2
|
|
assert all(entity["layerId"] == "title" for entity in result)
|
|
assert result[0]["children"], "폴리선에 선분이 없다"
|
|
|
|
|
|
def test_raster_image_is_left_alone():
|
|
raster = _image_entity("not-svg", mime="image/png")
|
|
assert _vectorize_svg_image(raster) == [raster]
|
|
|
|
|
|
def test_broken_svg_keeps_image():
|
|
broken = _image_entity("<svg><path d=")
|
|
assert _vectorize_svg_image(broken) == [broken]
|