refactor: excel parse
This commit is contained in:
@@ -0,0 +1,626 @@
|
||||
# Copyright (c) 2019-2022 Manfred Moitzi
|
||||
# License: MIT License
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING, Iterable, Iterator
|
||||
from ezdxf.math import Vec2, Shape2d, NULLVEC, UVec
|
||||
from .forms import open_arrow, arrow2
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ezdxf.entities import DXFGraphic
|
||||
from ezdxf.sections.blocks import BlocksSection
|
||||
from ezdxf.eztypes import GenericLayoutType
|
||||
|
||||
DEFAULT_ARROW_ANGLE = 18.924644
|
||||
DEFAULT_BETA = 45.0
|
||||
|
||||
|
||||
# The base arrow is oriented for the right hand side ->| of the dimension line,
|
||||
# reverse is the left hand side |<-.
|
||||
class BaseArrow:
|
||||
def __init__(self, vertices: Iterable[UVec]):
|
||||
self.shape = Shape2d(vertices)
|
||||
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
pass
|
||||
|
||||
def place(self, insert: UVec, angle: float):
|
||||
self.shape.rotate(angle)
|
||||
self.shape.translate(insert)
|
||||
|
||||
|
||||
class NoneStroke(BaseArrow):
|
||||
def __init__(self, insert: UVec, size: float = 1.0, angle: float = 0):
|
||||
super().__init__([Vec2(insert)])
|
||||
|
||||
|
||||
class ObliqueStroke(BaseArrow):
|
||||
def __init__(self, insert: UVec, size: float = 1.0, angle: float = 0):
|
||||
self.size = size
|
||||
s2 = size / 2
|
||||
# shape = [center, lower left, upper right]
|
||||
super().__init__([Vec2((-s2, -s2)), Vec2((s2, s2))])
|
||||
self.place(insert, angle)
|
||||
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
layout.add_line(
|
||||
start=self.shape[0], end=self.shape[1], dxfattribs=dxfattribs
|
||||
)
|
||||
|
||||
|
||||
class ArchTick(ObliqueStroke):
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
width = self.size * 0.15
|
||||
dxfattribs = dxfattribs or {}
|
||||
if layout.dxfversion > "AC1009":
|
||||
dxfattribs["const_width"] = width
|
||||
layout.add_lwpolyline(
|
||||
self.shape, format="xy", dxfattribs=dxfattribs # type: ignore
|
||||
)
|
||||
else:
|
||||
dxfattribs["default_start_width"] = width
|
||||
dxfattribs["default_end_width"] = width
|
||||
layout.add_polyline2d(self.shape, dxfattribs=dxfattribs) # type: ignore
|
||||
|
||||
|
||||
class ClosedArrowBlank(BaseArrow):
|
||||
def __init__(self, insert: UVec, size: float = 1.0, angle: float = 0):
|
||||
super().__init__(open_arrow(size, angle=DEFAULT_ARROW_ANGLE))
|
||||
self.place(insert, angle)
|
||||
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
if layout.dxfversion > "AC1009":
|
||||
polyline = layout.add_lwpolyline(
|
||||
points=self.shape, dxfattribs=dxfattribs # type: ignore
|
||||
)
|
||||
else:
|
||||
polyline = layout.add_polyline2d( # type: ignore
|
||||
points=self.shape, dxfattribs=dxfattribs # type: ignore
|
||||
)
|
||||
polyline.close(True)
|
||||
|
||||
|
||||
class ClosedArrow(ClosedArrowBlank):
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
super().render(layout, dxfattribs)
|
||||
end_point = self.shape[0].lerp(self.shape[2])
|
||||
|
||||
layout.add_line(
|
||||
start=self.shape[1], end=end_point, dxfattribs=dxfattribs
|
||||
)
|
||||
|
||||
|
||||
class ClosedArrowFilled(ClosedArrow):
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
layout.add_solid(
|
||||
points=self.shape, # type: ignore
|
||||
dxfattribs=dxfattribs,
|
||||
)
|
||||
|
||||
|
||||
class _OpenArrow(BaseArrow):
|
||||
def __init__(
|
||||
self,
|
||||
arrow_angle: float,
|
||||
insert: UVec,
|
||||
size: float = 1.0,
|
||||
angle: float = 0,
|
||||
):
|
||||
points = list(open_arrow(size, angle=arrow_angle))
|
||||
points.append((-1, 0))
|
||||
super().__init__(points)
|
||||
self.place(insert, angle)
|
||||
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
if layout.dxfversion > "AC1009":
|
||||
layout.add_lwpolyline(points=self.shape[:-1], dxfattribs=dxfattribs)
|
||||
else:
|
||||
layout.add_polyline2d(points=self.shape[:-1], dxfattribs=dxfattribs)
|
||||
layout.add_line(
|
||||
start=self.shape[1], end=self.shape[-1], dxfattribs=dxfattribs
|
||||
)
|
||||
|
||||
|
||||
class OpenArrow(_OpenArrow):
|
||||
def __init__(self, insert: UVec, size: float = 1.0, angle: float = 0):
|
||||
super().__init__(DEFAULT_ARROW_ANGLE, insert, size, angle)
|
||||
|
||||
|
||||
class OpenArrow30(_OpenArrow):
|
||||
def __init__(self, insert: UVec, size: float = 1.0, angle: float = 0):
|
||||
super().__init__(30, insert, size, angle)
|
||||
|
||||
|
||||
class OpenArrow90(_OpenArrow):
|
||||
def __init__(self, insert: UVec, size: float = 1.0, angle: float = 0):
|
||||
super().__init__(90, insert, size, angle)
|
||||
|
||||
|
||||
class Circle(BaseArrow):
|
||||
def __init__(self, insert: UVec, size: float = 1.0, angle: float = 0):
|
||||
self.radius = size / 2
|
||||
# shape = [center point, connection point]
|
||||
super().__init__(
|
||||
[
|
||||
Vec2((0, 0)),
|
||||
Vec2((-self.radius, 0)),
|
||||
Vec2((-size, 0)),
|
||||
]
|
||||
)
|
||||
self.place(insert, angle)
|
||||
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
layout.add_circle(
|
||||
center=self.shape[0], radius=self.radius, dxfattribs=dxfattribs
|
||||
)
|
||||
|
||||
|
||||
class Origin(Circle):
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
super().render(layout, dxfattribs)
|
||||
layout.add_line(
|
||||
start=self.shape[0], end=self.shape[2], dxfattribs=dxfattribs
|
||||
)
|
||||
|
||||
|
||||
class CircleBlank(Circle):
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
super().render(layout, dxfattribs)
|
||||
layout.add_line(
|
||||
start=self.shape[1], end=self.shape[2], dxfattribs=dxfattribs
|
||||
)
|
||||
|
||||
|
||||
class Origin2(Circle):
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
layout.add_circle(
|
||||
center=self.shape[0], radius=self.radius, dxfattribs=dxfattribs
|
||||
)
|
||||
layout.add_circle(
|
||||
center=self.shape[0], radius=self.radius / 2, dxfattribs=dxfattribs
|
||||
)
|
||||
layout.add_line(
|
||||
start=self.shape[1], end=self.shape[2], dxfattribs=dxfattribs
|
||||
)
|
||||
|
||||
|
||||
class DotSmall(Circle):
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
center = self.shape[0]
|
||||
d = Vec2((self.radius / 2, 0))
|
||||
p1 = center - d
|
||||
p2 = center + d
|
||||
dxfattribs = dxfattribs or {}
|
||||
if layout.dxfversion > "AC1009":
|
||||
dxfattribs["const_width"] = self.radius
|
||||
layout.add_lwpolyline(
|
||||
[(p1, 1), (p2, 1)],
|
||||
format="vb",
|
||||
close=True,
|
||||
dxfattribs=dxfattribs,
|
||||
)
|
||||
else:
|
||||
dxfattribs["default_start_width"] = self.radius
|
||||
dxfattribs["default_end_width"] = self.radius
|
||||
polyline = layout.add_polyline2d(
|
||||
points=[p1, p2], close=True, dxfattribs=dxfattribs
|
||||
)
|
||||
polyline[0].dxf.bulge = 1
|
||||
polyline[1].dxf.bulge = 1
|
||||
|
||||
|
||||
class Dot(DotSmall):
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
layout.add_line(
|
||||
start=self.shape[1], end=self.shape[2], dxfattribs=dxfattribs
|
||||
)
|
||||
super().render(layout, dxfattribs)
|
||||
|
||||
|
||||
class Box(BaseArrow):
|
||||
def __init__(self, insert: UVec, size: float = 1.0, angle: float = 0):
|
||||
# shape = [lower_left, lower_right, upper_right, upper_left, connection point]
|
||||
s2 = size / 2
|
||||
super().__init__(
|
||||
[
|
||||
Vec2((-s2, -s2)),
|
||||
Vec2((+s2, -s2)),
|
||||
Vec2((+s2, +s2)),
|
||||
Vec2((-s2, +s2)),
|
||||
Vec2((-s2, 0)),
|
||||
Vec2((-size, 0)),
|
||||
]
|
||||
)
|
||||
self.place(insert, angle)
|
||||
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
if layout.dxfversion > "AC1009":
|
||||
polyline = layout.add_lwpolyline(
|
||||
points=self.shape[0:4], dxfattribs=dxfattribs
|
||||
)
|
||||
else:
|
||||
polyline = layout.add_polyline2d( # type: ignore
|
||||
points=self.shape[0:4], dxfattribs=dxfattribs
|
||||
)
|
||||
polyline.close(True)
|
||||
layout.add_line(
|
||||
start=self.shape[4], end=self.shape[5], dxfattribs=dxfattribs
|
||||
)
|
||||
|
||||
|
||||
class BoxFilled(Box):
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
def solid_order():
|
||||
v = self.shape.vertices
|
||||
return [v[0], v[1], v[3], v[2]]
|
||||
|
||||
layout.add_solid(points=solid_order(), dxfattribs=dxfattribs)
|
||||
layout.add_line(
|
||||
start=self.shape[4], end=self.shape[5], dxfattribs=dxfattribs
|
||||
)
|
||||
|
||||
|
||||
class Integral(BaseArrow):
|
||||
def __init__(self, insert: UVec, size: float = 1.0, angle: float = 0):
|
||||
self.radius = size * 0.3535534
|
||||
self.angle = angle
|
||||
# shape = [center, left_center, right_center]
|
||||
super().__init__(
|
||||
[
|
||||
Vec2((0, 0)),
|
||||
Vec2((-self.radius, 0)),
|
||||
Vec2((self.radius, 0)),
|
||||
]
|
||||
)
|
||||
self.place(insert, angle)
|
||||
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
angle = self.angle
|
||||
layout.add_arc(
|
||||
center=self.shape[1],
|
||||
radius=self.radius,
|
||||
start_angle=-90 + angle,
|
||||
end_angle=angle,
|
||||
dxfattribs=dxfattribs,
|
||||
)
|
||||
layout.add_arc(
|
||||
center=self.shape[2],
|
||||
radius=self.radius,
|
||||
start_angle=90 + angle,
|
||||
end_angle=180 + angle,
|
||||
dxfattribs=dxfattribs,
|
||||
)
|
||||
|
||||
|
||||
class DatumTriangle(BaseArrow):
|
||||
REVERSE_ANGLE = 180
|
||||
|
||||
def __init__(self, insert: UVec, size: float = 1.0, angle: float = 0):
|
||||
d = 0.577350269 * size # tan(30)
|
||||
# shape = [upper_corner, lower_corner, connection_point]
|
||||
super().__init__(
|
||||
[
|
||||
Vec2((0, d)),
|
||||
Vec2((0, -d)),
|
||||
Vec2((-size, 0)),
|
||||
]
|
||||
)
|
||||
self.place(insert, angle)
|
||||
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
if layout.dxfversion > "AC1009":
|
||||
polyline = layout.add_lwpolyline(
|
||||
points=self.shape, dxfattribs=dxfattribs # type: ignore
|
||||
)
|
||||
else:
|
||||
polyline = layout.add_polyline2d( # type: ignore
|
||||
points=self.shape, dxfattribs=dxfattribs # type: ignore
|
||||
)
|
||||
polyline.close(True)
|
||||
|
||||
|
||||
class DatumTriangleFilled(DatumTriangle):
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
layout.add_solid(points=self.shape, dxfattribs=dxfattribs) # type: ignore
|
||||
|
||||
|
||||
class _EzArrow(BaseArrow):
|
||||
def __init__(self, insert: UVec, size: float = 1.0, angle: float = 0):
|
||||
points = list(arrow2(size, angle=DEFAULT_ARROW_ANGLE))
|
||||
points.append((-1, 0))
|
||||
super().__init__(points)
|
||||
self.place(insert, angle)
|
||||
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
if layout.dxfversion > "AC1009":
|
||||
polyline = layout.add_lwpolyline(
|
||||
self.shape[:-1], dxfattribs=dxfattribs
|
||||
)
|
||||
else:
|
||||
polyline = layout.add_polyline2d( # type: ignore
|
||||
self.shape[:-1], dxfattribs=dxfattribs
|
||||
)
|
||||
polyline.close(True)
|
||||
|
||||
|
||||
class EzArrowBlank(_EzArrow):
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
super().render(layout, dxfattribs)
|
||||
layout.add_line(
|
||||
start=self.shape[-2], end=self.shape[-1], dxfattribs=dxfattribs
|
||||
)
|
||||
|
||||
|
||||
class EzArrow(_EzArrow):
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
super().render(layout, dxfattribs)
|
||||
layout.add_line(
|
||||
start=self.shape[1], end=self.shape[-1], dxfattribs=dxfattribs
|
||||
)
|
||||
|
||||
|
||||
class EzArrowFilled(_EzArrow):
|
||||
def render(self, layout: GenericLayoutType, dxfattribs=None):
|
||||
points = self.shape.vertices
|
||||
layout.add_solid(
|
||||
[points[0], points[1], points[3], points[2]], dxfattribs=dxfattribs
|
||||
)
|
||||
layout.add_line(
|
||||
start=self.shape[-2], end=self.shape[-1], dxfattribs=dxfattribs
|
||||
)
|
||||
|
||||
|
||||
class _Arrows:
|
||||
closed_filled = ""
|
||||
dot = "DOT"
|
||||
dot_small = "DOTSMALL"
|
||||
dot_blank = "DOTBLANK"
|
||||
origin_indicator = "ORIGIN"
|
||||
origin_indicator_2 = "ORIGIN2"
|
||||
open = "OPEN"
|
||||
right_angle = "OPEN90"
|
||||
open_30 = "OPEN30"
|
||||
closed = "CLOSED"
|
||||
dot_smallblank = "SMALL"
|
||||
none = "NONE"
|
||||
oblique = "OBLIQUE"
|
||||
box_filled = "BOXFILLED"
|
||||
box = "BOXBLANK"
|
||||
closed_blank = "CLOSEDBLANK"
|
||||
datum_triangle_filled = "DATUMFILLED"
|
||||
datum_triangle = "DATUMBLANK"
|
||||
integral = "INTEGRAL"
|
||||
architectural_tick = "ARCHTICK"
|
||||
# ezdxf special arrows
|
||||
ez_arrow = "EZ_ARROW"
|
||||
ez_arrow_blank = "EZ_ARROW_BLANK"
|
||||
ez_arrow_filled = "EZ_ARROW_FILLED"
|
||||
|
||||
CLASSES = {
|
||||
closed_filled: ClosedArrowFilled,
|
||||
dot: Dot,
|
||||
dot_small: DotSmall,
|
||||
dot_blank: CircleBlank,
|
||||
origin_indicator: Origin,
|
||||
origin_indicator_2: Origin2,
|
||||
open: OpenArrow,
|
||||
right_angle: OpenArrow90,
|
||||
open_30: OpenArrow30,
|
||||
closed: ClosedArrow,
|
||||
dot_smallblank: Circle,
|
||||
none: NoneStroke,
|
||||
oblique: ObliqueStroke,
|
||||
box_filled: BoxFilled,
|
||||
box: Box,
|
||||
closed_blank: ClosedArrowBlank,
|
||||
datum_triangle: DatumTriangle,
|
||||
datum_triangle_filled: DatumTriangleFilled,
|
||||
integral: Integral,
|
||||
architectural_tick: ArchTick,
|
||||
ez_arrow: EzArrow,
|
||||
ez_arrow_blank: EzArrowBlank,
|
||||
ez_arrow_filled: EzArrowFilled,
|
||||
}
|
||||
# arrows with origin at dimension line start/end
|
||||
ORIGIN_ZERO = {
|
||||
architectural_tick,
|
||||
oblique,
|
||||
dot_small,
|
||||
dot_smallblank,
|
||||
integral,
|
||||
none,
|
||||
}
|
||||
|
||||
__acad__ = {
|
||||
closed_filled,
|
||||
dot,
|
||||
dot_small,
|
||||
dot_blank,
|
||||
origin_indicator,
|
||||
origin_indicator_2,
|
||||
open,
|
||||
right_angle,
|
||||
open_30,
|
||||
closed,
|
||||
dot_smallblank,
|
||||
none,
|
||||
oblique,
|
||||
box_filled,
|
||||
box,
|
||||
closed_blank,
|
||||
datum_triangle,
|
||||
datum_triangle_filled,
|
||||
integral,
|
||||
architectural_tick,
|
||||
}
|
||||
__ezdxf__ = {
|
||||
ez_arrow,
|
||||
ez_arrow_blank,
|
||||
ez_arrow_filled,
|
||||
}
|
||||
__all_arrows__ = __acad__ | __ezdxf__
|
||||
|
||||
EXTENSIONS_ALLOWED = {
|
||||
architectural_tick,
|
||||
oblique,
|
||||
none,
|
||||
dot_smallblank,
|
||||
integral,
|
||||
dot_small,
|
||||
}
|
||||
|
||||
def is_acad_arrow(self, item: str) -> bool:
|
||||
"""Returns ``True`` if `item` is a standard AutoCAD arrow."""
|
||||
return item.upper() in self.__acad__
|
||||
|
||||
def is_ezdxf_arrow(self, item: str) -> bool:
|
||||
"""Returns ``True`` if `item` is a special `ezdxf` arrow."""
|
||||
return item.upper() in self.__ezdxf__
|
||||
|
||||
def has_extension_line(self, name):
|
||||
"""Returns ``True`` if the arrow `name` supports extension lines."""
|
||||
return name in self.EXTENSIONS_ALLOWED
|
||||
|
||||
def __contains__(self, item: str) -> bool:
|
||||
"""Returns `True` if `item` is an arrow managed by this class."""
|
||||
if item is None:
|
||||
return False
|
||||
return item.upper() in self.__all_arrows__
|
||||
|
||||
def create_block(self, blocks: BlocksSection, name: str) -> str:
|
||||
"""Creates the BLOCK definition for arrow `name`."""
|
||||
block_name = self.block_name(name)
|
||||
if block_name not in blocks:
|
||||
block = blocks.new(block_name)
|
||||
arrow = self.arrow_shape(name, insert=(0, 0), size=1, rotation=0)
|
||||
arrow.render(block, dxfattribs={"color": 0, "linetype": "BYBLOCK"})
|
||||
return block_name
|
||||
|
||||
def arrow_handle(self, blocks: BlocksSection, name: str) -> str:
|
||||
"""Returns the BLOCK_RECORD handle for arrow `name`."""
|
||||
arrow_name = self.arrow_name(name)
|
||||
block_name = self.create_block(blocks, arrow_name)
|
||||
block = blocks.get(block_name)
|
||||
return block.block_record_handle
|
||||
|
||||
def block_name(self, name: str) -> str:
|
||||
"""Returns the block name."""
|
||||
if not self.is_acad_arrow(name): # common BLOCK definition
|
||||
# e.g. Dimension.dxf.bkl = 'EZ_ARROW' == Insert.dxf.name
|
||||
return name.upper()
|
||||
elif name == "":
|
||||
# special AutoCAD arrow symbol 'CLOSED_FILLED' has no name
|
||||
# ezdxf uses blocks for ALL arrows, but '_' (closed filled) as block name?
|
||||
return "_CLOSEDFILLED" # Dimension.dxf.bkl = '' != Insert.dxf.name = '_CLOSED_FILLED'
|
||||
else:
|
||||
# add preceding '_' to AutoCAD arrow symbol names
|
||||
# Dimension.dxf.bkl = 'DOT' != Insert.dxf.name = '_DOT'
|
||||
return "_" + name.upper()
|
||||
|
||||
def arrow_name(self, block_name: str) -> str:
|
||||
"""Returns the arrow name."""
|
||||
if block_name.startswith("_"):
|
||||
name = block_name[1:].upper()
|
||||
if name == "CLOSEDFILLED":
|
||||
return ""
|
||||
elif self.is_acad_arrow(name):
|
||||
return name
|
||||
return block_name
|
||||
|
||||
def insert_arrow(
|
||||
self,
|
||||
layout: GenericLayoutType,
|
||||
name: str,
|
||||
insert: UVec = NULLVEC,
|
||||
size: float = 1.0,
|
||||
rotation: float = 0,
|
||||
*,
|
||||
dxfattribs=None,
|
||||
) -> Vec2:
|
||||
"""Insert arrow as block reference into `layout`."""
|
||||
block_name = self.create_block(layout.doc.blocks, name)
|
||||
|
||||
dxfattribs = dict(dxfattribs or {})
|
||||
dxfattribs["rotation"] = rotation
|
||||
dxfattribs["xscale"] = size
|
||||
dxfattribs["yscale"] = size
|
||||
layout.add_blockref(block_name, insert=insert, dxfattribs=dxfattribs)
|
||||
return connection_point(
|
||||
name, insert=insert, scale=size, rotation=rotation
|
||||
)
|
||||
|
||||
def render_arrow(
|
||||
self,
|
||||
layout: GenericLayoutType,
|
||||
name: str,
|
||||
insert: UVec = NULLVEC,
|
||||
size: float = 1.0,
|
||||
rotation: float = 0,
|
||||
*,
|
||||
dxfattribs=None,
|
||||
) -> Vec2:
|
||||
"""Render arrow as basic DXF entities into `layout`."""
|
||||
dxfattribs = dict(dxfattribs or {})
|
||||
arrow = self.arrow_shape(name, insert, size, rotation)
|
||||
arrow.render(layout, dxfattribs)
|
||||
return connection_point(
|
||||
name, insert=insert, scale=size, rotation=rotation
|
||||
)
|
||||
|
||||
def virtual_entities(
|
||||
self,
|
||||
name: str,
|
||||
insert: UVec = NULLVEC,
|
||||
size: float = 0.625,
|
||||
rotation: float = 0,
|
||||
*,
|
||||
dxfattribs=None,
|
||||
) -> Iterator[DXFGraphic]:
|
||||
"""Returns all arrow components as virtual DXF entities."""
|
||||
from ezdxf.layouts import VirtualLayout
|
||||
|
||||
if name in self:
|
||||
layout = VirtualLayout()
|
||||
ARROWS.render_arrow(
|
||||
layout,
|
||||
name,
|
||||
insert=insert,
|
||||
size=size,
|
||||
rotation=rotation,
|
||||
dxfattribs=dxfattribs,
|
||||
)
|
||||
yield from iter(layout)
|
||||
|
||||
def arrow_shape(
|
||||
self, name: str, insert: UVec, size: float, rotation: float
|
||||
) -> BaseArrow:
|
||||
"""Returns an instance of the shape management class for arrow `name`."""
|
||||
# size depending shapes
|
||||
name = name.upper()
|
||||
if name == self.dot_small:
|
||||
size *= 0.25
|
||||
elif name == self.dot_smallblank:
|
||||
size *= 0.5
|
||||
cls = self.CLASSES[name]
|
||||
return cls(insert, size, rotation)
|
||||
|
||||
|
||||
def connection_point(
|
||||
arrow_name: str, insert: UVec, scale: float = 1.0, rotation: float = 0.0
|
||||
) -> Vec2:
|
||||
"""Returns the connection point for `arrow_name`."""
|
||||
insert = Vec2(insert)
|
||||
if ARROWS.arrow_name(arrow_name) in _Arrows.ORIGIN_ZERO:
|
||||
return insert
|
||||
else:
|
||||
return insert - Vec2.from_deg_angle(rotation, scale)
|
||||
|
||||
|
||||
def arrow_length(arrow_name: str, scale: float = 1.0) -> float:
|
||||
"""Returns the scaled arrow length of `arrow_name`."""
|
||||
if ARROWS.arrow_name(arrow_name) in _Arrows.ORIGIN_ZERO:
|
||||
return 0.0
|
||||
else:
|
||||
return scale
|
||||
|
||||
|
||||
ARROWS: _Arrows = _Arrows()
|
||||
Reference in New Issue
Block a user