Merge remote-tracking branch 'origin/sub_desktop_1' into main_laptop_1
This commit is contained in:
@@ -39,6 +39,8 @@ _IMPORT_NS = uuid5(NAMESPACE_URL, "aislo/b07/frame-import")
|
||||
_DEFAULT_COLOR = "#f5f7fa"
|
||||
# 곡선을 선분으로 풀 때 허용 오차(mm) — 도각 크기(840x594mm)에서 눈에 띄지 않는다.
|
||||
_FLATTEN_MM = 0.2
|
||||
# 곡선 한 토막(90° 이하)을 적어도 이만큼 나눔 — 단위가 m 인 도면의 작은 원 · 호가 점 · 삼각형 · 직선으로 뭉개지지 않게.
|
||||
_CURVE_SEGMENTS = 8
|
||||
_MAX_ENTITIES = 20000
|
||||
# 블록 속 블록을 풀 깊이 — 자기를 품는 깨진 블록에서 끝없이 돌지 않게.
|
||||
_MAX_BLOCK_DEPTH = 16
|
||||
@@ -149,10 +151,19 @@ def _text(
|
||||
}
|
||||
|
||||
|
||||
def _flatten(entity: Any) -> list[Any] | None:
|
||||
"""원·호·타원·스플라인을 선분 점열로 편다. 못 펴면 None."""
|
||||
def _path_points(entity: Any) -> list[Any]:
|
||||
"""도형 → WCS 경로 점열 — 곡선 토막마다 `_CURVE_SEGMENTS` 이상으로 나눔."""
|
||||
return list(ezdxf_path.make_path(entity).flattening(_FLATTEN_MM, segments=_CURVE_SEGMENTS))
|
||||
|
||||
|
||||
def _flatten(entity: Any) -> tuple[list[Any], bool] | None:
|
||||
"""원·호·타원·스플라인 → (선분 점열, 닫힘). 경로는 닫는 마디까지 넣음 · 못 펴면 None."""
|
||||
try:
|
||||
return list(entity.flattening(_FLATTEN_MM))
|
||||
return _path_points(entity), False
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
return list(entity.flattening(_FLATTEN_MM)), entity.dxftype() == "CIRCLE"
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
@@ -164,7 +175,7 @@ def _polyline_points(entity: Any) -> tuple[list[Any], bool]:
|
||||
면 · 메시 POLYLINE 처럼 경로로 못 바꾸면 꼭짓점을 그대로 잇는다.
|
||||
"""
|
||||
try:
|
||||
return list(ezdxf_path.make_path(entity).flattening(_FLATTEN_MM)), False
|
||||
return _path_points(entity), False
|
||||
except Exception:
|
||||
if entity.dxftype() == "LWPOLYLINE":
|
||||
return list(entity.get_points("xy")), bool(entity.closed)
|
||||
@@ -203,10 +214,10 @@ def _convert_entity(index: int, entity: Any) -> list[dict[str, Any]]:
|
||||
shape = _polyline(index, entity, points, closed)
|
||||
return [shape] if shape else []
|
||||
if kind in ("CIRCLE", "ARC", "ELLIPSE", "SPLINE"):
|
||||
points = _flatten(entity)
|
||||
if not points:
|
||||
flat = _flatten(entity)
|
||||
if not flat:
|
||||
return []
|
||||
shape = _polyline(index, entity, points, kind in ("CIRCLE", "ELLIPSE"))
|
||||
shape = _polyline(index, entity, *flat)
|
||||
return [shape] if shape else []
|
||||
if kind == "POINT":
|
||||
location = entity.dxf.location
|
||||
|
||||
@@ -133,3 +133,24 @@ def test_내보내기_시계방향_작은_호(tmp_path):
|
||||
(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)
|
||||
|
||||
|
||||
def test_작은_원_호는_뭉개지지_않음():
|
||||
"""m 단위 도면(99-3 중력식사방댐) — 반지름 0.071 원 · 0.36 호 · bulge 0.4 폭 반원이 점 · 직선이 되지 않음."""
|
||||
doc = ezdxf.new()
|
||||
space = doc.modelspace()
|
||||
space.add_circle((0, 0), 0.071)
|
||||
space.add_arc((5, 0), 0.361, 10, 96)
|
||||
space.add_lwpolyline([(10, 0, 0, 0, 1), (10.4, 0)], format="xyseb")
|
||||
circle, arc, half = _read(doc)
|
||||
circle_points = _points(circle)
|
||||
assert len(circle_points) >= 33 and circle_points[0] == circle_points[-1]
|
||||
assert _on_circle(circle_points, 0, 0, 0.071)
|
||||
assert max(x for x, _y in circle_points) > 0.07 and min(x for x, _y in circle_points) < -0.07
|
||||
arc_points = _points(arc)
|
||||
assert len(arc_points) >= 9
|
||||
for x, y in arc_points: # 10°~96° 안 · 큰 호로 뒤집히지 않음
|
||||
assert abs(math.hypot(x - 5, y) - 0.361) < 0.003
|
||||
assert 10 - 0.01 <= math.degrees(math.atan2(y, x - 5)) <= 96 + 0.01
|
||||
half_points = _points(half)
|
||||
assert len(half_points) >= 9 and min(y for _x, y in half_points) < -0.19
|
||||
|
||||
Reference in New Issue
Block a user