refactor: excel parse
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
# Copyright (c) 2024, Manfred Moitzi
|
||||
# License: MIT License
|
||||
from __future__ import annotations
|
||||
from typing import Sequence, TYPE_CHECKING, Iterable, Any
|
||||
import math
|
||||
from ezdxf.math import UVec, Vec2, has_clockwise_orientation
|
||||
from ezdxf.entities import LWPolyline, DXFEntity
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ezdxf.layouts import BaseLayout
|
||||
|
||||
|
||||
REVCLOUD_PROPS = "RevcloudProps"
|
||||
REQUIRED_BULGE = 0.520567050552
|
||||
|
||||
|
||||
def points(
|
||||
vertices: Iterable[UVec],
|
||||
segment_length: float,
|
||||
*,
|
||||
bulge: float = REQUIRED_BULGE, # required to be recognized as REVCLOUD
|
||||
start_width: float = 0.0,
|
||||
end_width: float = 0.0,
|
||||
) -> list[Sequence[float]]:
|
||||
"""Returns the points for a :class:`~ezdxf.entities.LWPolyline` entity to render a
|
||||
revision cloud, similar to the REVCLOUD command in CAD applications.
|
||||
|
||||
Args:
|
||||
vertices: corner points of a polygon
|
||||
segment_length: approximate segment length
|
||||
bulge: LWPOLYLINE bulge value
|
||||
start_width: start width of the segment arc
|
||||
end_width: end width of the segment arc, CAD applications use 0.1 * segment_length
|
||||
for a calligraphy effect
|
||||
|
||||
"""
|
||||
if segment_length < 1e-6:
|
||||
raise ValueError("segment length too small.")
|
||||
_vertices = _to_vec2_list(vertices)
|
||||
lw_points: list[Sequence[float]] = []
|
||||
|
||||
for s, e in zip(_vertices, _vertices[1:]):
|
||||
lw_points.append((s.x, s.y, start_width, end_width, bulge))
|
||||
diff = e - s
|
||||
length = diff.magnitude
|
||||
if length <= segment_length:
|
||||
continue
|
||||
|
||||
count = math.ceil(length / segment_length)
|
||||
_segment_length = length / count
|
||||
offset = diff.normalize(_segment_length)
|
||||
for _ in range(count - 1):
|
||||
s += offset
|
||||
lw_points.append((s.x, s.y, start_width, end_width, bulge))
|
||||
return lw_points
|
||||
|
||||
|
||||
def add_entity(
|
||||
layout: BaseLayout,
|
||||
vertices: Iterable[UVec],
|
||||
segment_length: float,
|
||||
*,
|
||||
calligraphy=True,
|
||||
dxfattribs: Any = None,
|
||||
) -> LWPolyline:
|
||||
"""Adds a revision cloud as :class:`~ezdxf.entities.LWPolyline` entity to `layout`,
|
||||
similar to the REVCLOUD command in CAD applications.
|
||||
|
||||
Args:
|
||||
layout: target layout
|
||||
vertices: corner points of a polygon
|
||||
segment_length: approximate segment length
|
||||
calligraphy: ``True`` for a calligraphy effect
|
||||
dxfattribs: additional DXF attributes
|
||||
|
||||
"""
|
||||
_vertices = _to_vec2_list(vertices)
|
||||
bulge = REQUIRED_BULGE
|
||||
if has_clockwise_orientation(_vertices):
|
||||
bulge = -bulge
|
||||
|
||||
end_width = segment_length * 0.1 if calligraphy else 0.0
|
||||
lw_points = points(_vertices, segment_length, bulge=bulge, end_width=end_width)
|
||||
lwp = layout.add_lwpolyline(lw_points, close=True, dxfattribs=dxfattribs)
|
||||
lwp.set_xdata(REVCLOUD_PROPS, [(1070, 0), (1040, segment_length)])
|
||||
doc = layout.doc
|
||||
if doc is not None and not doc.appids.has_entry(REVCLOUD_PROPS):
|
||||
doc.appids.add(REVCLOUD_PROPS)
|
||||
return lwp
|
||||
|
||||
|
||||
def is_revcloud(entity: DXFEntity) -> bool:
|
||||
"""Returns ``True`` when the given entity represents a revision cloud."""
|
||||
if not isinstance(entity, LWPolyline):
|
||||
return False
|
||||
lwpolyline: LWPolyline = entity
|
||||
if not lwpolyline.is_closed:
|
||||
return False
|
||||
if not lwpolyline.has_xdata(REVCLOUD_PROPS):
|
||||
return False
|
||||
return all(
|
||||
abs(REQUIRED_BULGE - abs(p[0])) < 0.02
|
||||
for p in lwpolyline.get_points(format="b")
|
||||
)
|
||||
|
||||
|
||||
def _to_vec2_list(vertices: Iterable[UVec]) -> list[Vec2]:
|
||||
_vertices: list[Vec2] = Vec2.list(vertices)
|
||||
if len(_vertices) < 3:
|
||||
raise ValueError("3 or more points required.")
|
||||
if not _vertices[0].isclose(_vertices[-1]):
|
||||
_vertices.append(_vertices[0])
|
||||
if len(_vertices) < 4:
|
||||
raise ValueError("3 or more points required.")
|
||||
return _vertices
|
||||
Reference in New Issue
Block a user