refactor: excel parse
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
# Copyright (c) 2019-2024 Manfred Moitzi
|
||||
# License: MIT License
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING, Iterator
|
||||
import math
|
||||
import numpy as np
|
||||
|
||||
from ezdxf.math import (
|
||||
Vec3,
|
||||
Matrix44,
|
||||
ConstructionArc,
|
||||
arc_angle_span_deg,
|
||||
)
|
||||
from ezdxf.math.transformtools import OCSTransform
|
||||
|
||||
from ezdxf.lldxf.attributes import (
|
||||
DXFAttr,
|
||||
DXFAttributes,
|
||||
DefSubclass,
|
||||
group_code_mapping,
|
||||
merge_group_code_mappings,
|
||||
)
|
||||
from ezdxf.lldxf.const import DXF12, SUBCLASS_MARKER
|
||||
from .dxfentity import base_class
|
||||
from .dxfgfx import acdb_entity
|
||||
from .circle import acdb_circle, Circle, merged_circle_group_codes
|
||||
from .factory import register_entity
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ezdxf.lldxf.tagwriter import AbstractTagWriter
|
||||
|
||||
__all__ = ["Arc"]
|
||||
|
||||
acdb_arc = DefSubclass(
|
||||
"AcDbArc",
|
||||
{
|
||||
"start_angle": DXFAttr(50, default=0),
|
||||
"end_angle": DXFAttr(51, default=360),
|
||||
},
|
||||
)
|
||||
|
||||
acdb_arc_group_codes = group_code_mapping(acdb_arc)
|
||||
merged_arc_group_codes = merge_group_code_mappings(
|
||||
merged_circle_group_codes, acdb_arc_group_codes
|
||||
)
|
||||
|
||||
|
||||
@register_entity
|
||||
class Arc(Circle):
|
||||
"""DXF ARC entity"""
|
||||
|
||||
DXFTYPE = "ARC"
|
||||
DXFATTRIBS = DXFAttributes(base_class, acdb_entity, acdb_circle, acdb_arc)
|
||||
MERGED_GROUP_CODES = merged_arc_group_codes
|
||||
|
||||
def export_entity(self, tagwriter: AbstractTagWriter) -> None:
|
||||
"""Export entity specific data as DXF tags."""
|
||||
super().export_entity(tagwriter)
|
||||
# AcDbEntity export is done by parent class
|
||||
# AcDbCircle export is done by parent class
|
||||
if tagwriter.dxfversion > DXF12:
|
||||
tagwriter.write_tag2(SUBCLASS_MARKER, acdb_arc.name)
|
||||
self.dxf.export_dxf_attribs(tagwriter, ["start_angle", "end_angle"])
|
||||
|
||||
@property
|
||||
def start_point(self) -> Vec3:
|
||||
"""Returns the start point of the arc in :ref:`WCS`, takes the :ref:`OCS` into
|
||||
account.
|
||||
"""
|
||||
v = list(self.vertices([self.dxf.start_angle]))
|
||||
return v[0]
|
||||
|
||||
@property
|
||||
def end_point(self) -> Vec3:
|
||||
"""Returns the end point of the arc in :ref:`WCS`, takes the :ref:`OCS` into
|
||||
account.
|
||||
"""
|
||||
v = list(self.vertices([self.dxf.end_angle]))
|
||||
return v[0]
|
||||
|
||||
def angles(self, num: int) -> Iterator[float]:
|
||||
"""Yields `num` angles from start- to end angle in degrees in counter-clockwise
|
||||
orientation. All angles are normalized in the range from [0, 360).
|
||||
"""
|
||||
if num < 2:
|
||||
raise ValueError("num >= 2")
|
||||
start = self.dxf.start_angle % 360
|
||||
stop = self.dxf.end_angle % 360
|
||||
if stop <= start:
|
||||
stop += 360
|
||||
for angle in np.linspace(start, stop, num=num, endpoint=True):
|
||||
yield angle % 360
|
||||
|
||||
def flattening(self, sagitta: float) -> Iterator[Vec3]:
|
||||
"""Approximate the arc by vertices in :ref:`WCS`, the argument `sagitta`_
|
||||
defines the maximum distance from the center of an arc segment to the center of
|
||||
its chord.
|
||||
|
||||
.. _sagitta: https://en.wikipedia.org/wiki/Sagitta_(geometry)
|
||||
"""
|
||||
arc = self.construction_tool()
|
||||
ocs = self.ocs()
|
||||
elevation = Vec3(self.dxf.center).z
|
||||
if ocs.transform:
|
||||
to_wcs = ocs.points_to_wcs
|
||||
else:
|
||||
to_wcs = Vec3.generate
|
||||
|
||||
yield from to_wcs(Vec3(p.x, p.y, elevation) for p in arc.flattening(sagitta))
|
||||
|
||||
def transform(self, m: Matrix44) -> Arc:
|
||||
"""Transform ARC entity by transformation matrix `m` inplace.
|
||||
Raises ``NonUniformScalingError()`` for non-uniform scaling.
|
||||
"""
|
||||
ocs = OCSTransform(self.dxf.extrusion, m)
|
||||
super()._transform(ocs)
|
||||
s: float = self.dxf.start_angle
|
||||
e: float = self.dxf.end_angle
|
||||
if not math.isclose(arc_angle_span_deg(s, e), 360.0):
|
||||
(
|
||||
self.dxf.start_angle,
|
||||
self.dxf.end_angle,
|
||||
) = ocs.transform_ccw_arc_angles_deg(s, e)
|
||||
self.post_transform(m)
|
||||
return self
|
||||
|
||||
def construction_tool(self) -> ConstructionArc:
|
||||
"""Returns the 2D construction tool :class:`ezdxf.math.ConstructionArc` but the
|
||||
extrusion vector is ignored.
|
||||
"""
|
||||
dxf = self.dxf
|
||||
return ConstructionArc(
|
||||
dxf.center,
|
||||
dxf.radius,
|
||||
dxf.start_angle,
|
||||
dxf.end_angle,
|
||||
)
|
||||
|
||||
def apply_construction_tool(self, arc: ConstructionArc) -> Arc:
|
||||
"""Set ARC data from the construction tool :class:`ezdxf.math.ConstructionArc`
|
||||
but the extrusion vector is ignored.
|
||||
"""
|
||||
dxf = self.dxf
|
||||
dxf.center = Vec3(arc.center)
|
||||
dxf.radius = arc.radius
|
||||
dxf.start_angle = arc.start_angle
|
||||
dxf.end_angle = arc.end_angle
|
||||
return self # floating interface
|
||||
Reference in New Issue
Block a user