remove per-shape polygonization state
This commit is contained in:
parent
7befe89af3
commit
9d42df831e
@ -9,7 +9,7 @@ from numpy.typing import ArrayLike
|
|||||||
|
|
||||||
from ..pattern import Pattern, NamedPattern
|
from ..pattern import Pattern, NamedPattern
|
||||||
from ..ref import Ref
|
from ..ref import Ref
|
||||||
from ..library import MutableLibrary
|
from ..library import MutableLibrary, Tree
|
||||||
from ..error import PortError, BuildError
|
from ..error import PortError, BuildError
|
||||||
from ..ports import PortList, Port
|
from ..ports import PortList, Port
|
||||||
from ..abstract import Abstract
|
from ..abstract import Abstract
|
||||||
@ -492,7 +492,6 @@ class Builder(PortList):
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Pather(Builder):
|
class Pather(Builder):
|
||||||
"""
|
"""
|
||||||
TODO DOCUMENT Builder
|
TODO DOCUMENT Builder
|
||||||
@ -657,7 +656,8 @@ class Pather(Builder):
|
|||||||
if tools is None and hasattr(source, 'tools') and isinstance(source.tools, dict):
|
if tools is None and hasattr(source, 'tools') and isinstance(source.tools, dict):
|
||||||
tools = source.tools
|
tools = source.tools
|
||||||
|
|
||||||
new = Pather.from_builder(Builder.interface(
|
new = Pather.from_builder(
|
||||||
|
Builder.interface(
|
||||||
source=source,
|
source=source,
|
||||||
library=library,
|
library=library,
|
||||||
in_prefix=in_prefix,
|
in_prefix=in_prefix,
|
||||||
|
@ -214,18 +214,18 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
|
|||||||
|
|
||||||
def polygonize(
|
def polygonize(
|
||||||
self: P,
|
self: P,
|
||||||
poly_num_points: Optional[int] = None,
|
num_points: Optional[int] = None,
|
||||||
poly_max_arclen: Optional[float] = None,
|
max_arclen: Optional[float] = None,
|
||||||
) -> P:
|
) -> P:
|
||||||
"""
|
"""
|
||||||
Calls `.to_polygons(...)` on all the shapes in this Pattern, replacing them with the returned polygons.
|
Calls `.to_polygons(...)` on all the shapes in this Pattern, replacing them with the returned polygons.
|
||||||
Arguments are passed directly to `shape.to_polygons(...)`.
|
Arguments are passed directly to `shape.to_polygons(...)`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
poly_num_points: Number of points to use for each polygon. Can be overridden by
|
num_points: Number of points to use for each polygon. Can be overridden by
|
||||||
`poly_max_arclen` if that results in more points. Optional, defaults to shapes'
|
`max_arclen` if that results in more points. Optional, defaults to shapes'
|
||||||
internal defaults.
|
internal defaults.
|
||||||
poly_max_arclen: Maximum arclength which can be approximated by a single line
|
max_arclen: Maximum arclength which can be approximated by a single line
|
||||||
segment. Optional, defaults to shapes' internal defaults.
|
segment. Optional, defaults to shapes' internal defaults.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@ -233,7 +233,7 @@ class Pattern(PortList, AnnotatableImpl, Mirrorable):
|
|||||||
"""
|
"""
|
||||||
old_shapes = self.shapes
|
old_shapes = self.shapes
|
||||||
self.shapes = list(chain.from_iterable((
|
self.shapes = list(chain.from_iterable((
|
||||||
shape.to_polygons(poly_num_points, poly_max_arclen)
|
shape.to_polygons(num_points, max_arclen)
|
||||||
for shape in old_shapes)))
|
for shape in old_shapes)))
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ Shapes for use with the Pattern class, as well as the Shape abstract class from
|
|||||||
which they are derived.
|
which they are derived.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from .shape import Shape, normalized_shape_tuple, DEFAULT_POLY_NUM_POINTS
|
from .shape import Shape, normalized_shape_tuple, DEFAULT_POLY_NUM_VERTICES
|
||||||
|
|
||||||
from .polygon import Polygon
|
from .polygon import Polygon
|
||||||
from .circle import Circle
|
from .circle import Circle
|
||||||
|
@ -6,7 +6,7 @@ import numpy
|
|||||||
from numpy import pi
|
from numpy import pi
|
||||||
from numpy.typing import NDArray, ArrayLike
|
from numpy.typing import NDArray, ArrayLike
|
||||||
|
|
||||||
from . import Shape, Polygon, normalized_shape_tuple, DEFAULT_POLY_NUM_POINTS
|
from . import Shape, Polygon, normalized_shape_tuple, DEFAULT_POLY_NUM_VERTICES
|
||||||
from ..error import PatternError
|
from ..error import PatternError
|
||||||
from ..repetition import Repetition
|
from ..repetition import Repetition
|
||||||
from ..utils import is_scalar, layer_t, annotations_t
|
from ..utils import is_scalar, layer_t, annotations_t
|
||||||
@ -23,7 +23,6 @@ class Arc(Shape):
|
|||||||
"""
|
"""
|
||||||
__slots__ = (
|
__slots__ = (
|
||||||
'_radii', '_angles', '_width', '_rotation',
|
'_radii', '_angles', '_width', '_rotation',
|
||||||
'poly_num_points', 'poly_max_arclen',
|
|
||||||
# Inherited
|
# Inherited
|
||||||
'_offset', '_layer', '_repetition', '_annotations',
|
'_offset', '_layer', '_repetition', '_annotations',
|
||||||
)
|
)
|
||||||
@ -40,12 +39,6 @@ class Arc(Shape):
|
|||||||
_width: float
|
_width: float
|
||||||
""" Width of the arc """
|
""" Width of the arc """
|
||||||
|
|
||||||
poly_num_points: Optional[int]
|
|
||||||
""" Sets the default number of points for `.polygonize()` """
|
|
||||||
|
|
||||||
poly_max_arclen: Optional[float]
|
|
||||||
""" Sets the default max segement length for `.polygonize()` """
|
|
||||||
|
|
||||||
# radius properties
|
# radius properties
|
||||||
@property
|
@property
|
||||||
def radii(self) -> Any: # TODO mypy#3004 NDArray[numpy.float64]:
|
def radii(self) -> Any: # TODO mypy#3004 NDArray[numpy.float64]:
|
||||||
@ -160,8 +153,6 @@ class Arc(Shape):
|
|||||||
angles: ArrayLike,
|
angles: ArrayLike,
|
||||||
width: float,
|
width: float,
|
||||||
*,
|
*,
|
||||||
poly_num_points: Optional[int] = DEFAULT_POLY_NUM_POINTS,
|
|
||||||
poly_max_arclen: Optional[float] = None,
|
|
||||||
offset: ArrayLike = (0.0, 0.0),
|
offset: ArrayLike = (0.0, 0.0),
|
||||||
rotation: float = 0,
|
rotation: float = 0,
|
||||||
mirrored: Sequence[bool] = (False, False),
|
mirrored: Sequence[bool] = (False, False),
|
||||||
@ -191,8 +182,6 @@ class Arc(Shape):
|
|||||||
self.repetition = repetition
|
self.repetition = repetition
|
||||||
self.annotations = annotations if annotations is not None else {}
|
self.annotations = annotations if annotations is not None else {}
|
||||||
self.layer = layer
|
self.layer = layer
|
||||||
self.poly_num_points = poly_num_points
|
|
||||||
self.poly_max_arclen = poly_max_arclen
|
|
||||||
[self.mirror(a) for a, do in enumerate(mirrored) if do]
|
[self.mirror(a) for a, do in enumerate(mirrored) if do]
|
||||||
|
|
||||||
def __deepcopy__(self, memo: Optional[Dict] = None) -> 'Arc':
|
def __deepcopy__(self, memo: Optional[Dict] = None) -> 'Arc':
|
||||||
@ -206,15 +195,10 @@ class Arc(Shape):
|
|||||||
|
|
||||||
def to_polygons(
|
def to_polygons(
|
||||||
self,
|
self,
|
||||||
poly_num_points: Optional[int] = None,
|
num_vertices: Optional[int] = DEFAULT_POLY_NUM_VERTICES,
|
||||||
poly_max_arclen: Optional[float] = None,
|
max_arclen: Optional[float] = None,
|
||||||
) -> List[Polygon]:
|
) -> List[Polygon]:
|
||||||
if poly_num_points is None:
|
if (num_vertices is None) and (max_arclen is None):
|
||||||
poly_num_points = self.poly_num_points
|
|
||||||
if poly_max_arclen is None:
|
|
||||||
poly_max_arclen = self.poly_max_arclen
|
|
||||||
|
|
||||||
if (poly_num_points is None) and (poly_max_arclen is None):
|
|
||||||
raise PatternError('Max number of points and arclength left unspecified'
|
raise PatternError('Max number of points and arclength left unspecified'
|
||||||
+ ' (default was also overridden)')
|
+ ' (default was also overridden)')
|
||||||
|
|
||||||
@ -232,18 +216,18 @@ class Arc(Shape):
|
|||||||
perimeter = abs(a0 - a1) / (2 * pi) * ellipse_perimeter # TODO: make this more accurate
|
perimeter = abs(a0 - a1) / (2 * pi) * ellipse_perimeter # TODO: make this more accurate
|
||||||
|
|
||||||
n = []
|
n = []
|
||||||
if poly_num_points is not None:
|
if num_vertices is not None:
|
||||||
n += [poly_num_points]
|
n += [num_vertices]
|
||||||
if poly_max_arclen is not None:
|
if max_arclen is not None:
|
||||||
n += [perimeter / poly_max_arclen]
|
n += [perimeter / max_arclen]
|
||||||
num_points = int(round(max(n)))
|
num_vertices = int(round(max(n)))
|
||||||
|
|
||||||
wh = self.width / 2.0
|
wh = self.width / 2.0
|
||||||
if wh == r0 or wh == r1:
|
if wh == r0 or wh == r1:
|
||||||
thetas_inner = numpy.zeros(1) # Don't generate multiple vertices if we're at the origin
|
thetas_inner = numpy.zeros(1) # Don't generate multiple vertices if we're at the origin
|
||||||
else:
|
else:
|
||||||
thetas_inner = numpy.linspace(a_ranges[0][1], a_ranges[0][0], num_points, endpoint=True)
|
thetas_inner = numpy.linspace(a_ranges[0][1], a_ranges[0][0], num_vertices, endpoint=True)
|
||||||
thetas_outer = numpy.linspace(a_ranges[1][0], a_ranges[1][1], num_points, endpoint=True)
|
thetas_outer = numpy.linspace(a_ranges[1][0], a_ranges[1][1], num_vertices, endpoint=True)
|
||||||
|
|
||||||
sin_th_i, cos_th_i = (numpy.sin(thetas_inner), numpy.cos(thetas_inner))
|
sin_th_i, cos_th_i = (numpy.sin(thetas_inner), numpy.cos(thetas_inner))
|
||||||
sin_th_o, cos_th_o = (numpy.sin(thetas_outer), numpy.cos(thetas_outer))
|
sin_th_o, cos_th_o = (numpy.sin(thetas_outer), numpy.cos(thetas_outer))
|
||||||
@ -370,7 +354,12 @@ class Arc(Shape):
|
|||||||
|
|
||||||
return ((type(self), radii, angles, width / norm_value, self.layer),
|
return ((type(self), radii, angles, width / norm_value, self.layer),
|
||||||
(self.offset, scale / norm_value, rotation, False),
|
(self.offset, scale / norm_value, rotation, False),
|
||||||
lambda: Arc(radii=radii * norm_value, angles=angles, width=width * norm_value, layer=self.layer))
|
lambda: Arc(
|
||||||
|
radii=radii * norm_value,
|
||||||
|
angles=angles,
|
||||||
|
width=width * norm_value,
|
||||||
|
layer=self.layer,
|
||||||
|
))
|
||||||
|
|
||||||
def get_cap_edges(self) -> NDArray[numpy.float64]:
|
def get_cap_edges(self) -> NDArray[numpy.float64]:
|
||||||
'''
|
'''
|
||||||
|
@ -5,7 +5,7 @@ import numpy
|
|||||||
from numpy import pi
|
from numpy import pi
|
||||||
from numpy.typing import NDArray, ArrayLike
|
from numpy.typing import NDArray, ArrayLike
|
||||||
|
|
||||||
from . import Shape, Polygon, normalized_shape_tuple, DEFAULT_POLY_NUM_POINTS
|
from . import Shape, Polygon, normalized_shape_tuple, DEFAULT_POLY_NUM_VERTICES
|
||||||
from ..error import PatternError
|
from ..error import PatternError
|
||||||
from ..repetition import Repetition
|
from ..repetition import Repetition
|
||||||
from ..utils import is_scalar, layer_t, annotations_t
|
from ..utils import is_scalar, layer_t, annotations_t
|
||||||
@ -16,7 +16,7 @@ class Circle(Shape):
|
|||||||
A circle, which has a position and radius.
|
A circle, which has a position and radius.
|
||||||
"""
|
"""
|
||||||
__slots__ = (
|
__slots__ = (
|
||||||
'_radius', 'poly_num_points', 'poly_max_arclen',
|
'_radius',
|
||||||
# Inherited
|
# Inherited
|
||||||
'_offset', '_layer', '_repetition', '_annotations',
|
'_offset', '_layer', '_repetition', '_annotations',
|
||||||
)
|
)
|
||||||
@ -24,12 +24,6 @@ class Circle(Shape):
|
|||||||
_radius: float
|
_radius: float
|
||||||
""" Circle radius """
|
""" Circle radius """
|
||||||
|
|
||||||
poly_num_points: Optional[int]
|
|
||||||
""" Sets the default number of points for `.polygonize()` """
|
|
||||||
|
|
||||||
poly_max_arclen: Optional[float]
|
|
||||||
""" Sets the default max segement length for `.polygonize()` """
|
|
||||||
|
|
||||||
# radius property
|
# radius property
|
||||||
@property
|
@property
|
||||||
def radius(self) -> float:
|
def radius(self) -> float:
|
||||||
@ -50,8 +44,6 @@ class Circle(Shape):
|
|||||||
self,
|
self,
|
||||||
radius: float,
|
radius: float,
|
||||||
*,
|
*,
|
||||||
poly_num_points: Optional[int] = DEFAULT_POLY_NUM_POINTS,
|
|
||||||
poly_max_arclen: Optional[float] = None,
|
|
||||||
offset: ArrayLike = (0.0, 0.0),
|
offset: ArrayLike = (0.0, 0.0),
|
||||||
layer: layer_t = 0,
|
layer: layer_t = 0,
|
||||||
repetition: Optional[Repetition] = None,
|
repetition: Optional[Repetition] = None,
|
||||||
@ -71,8 +63,6 @@ class Circle(Shape):
|
|||||||
self.repetition = repetition
|
self.repetition = repetition
|
||||||
self.annotations = annotations if annotations is not None else {}
|
self.annotations = annotations if annotations is not None else {}
|
||||||
self.layer = layer
|
self.layer = layer
|
||||||
self.poly_num_points = poly_num_points
|
|
||||||
self.poly_max_arclen = poly_max_arclen
|
|
||||||
|
|
||||||
def __deepcopy__(self, memo: Optional[Dict] = None) -> 'Circle':
|
def __deepcopy__(self, memo: Optional[Dict] = None) -> 'Circle':
|
||||||
memo = {} if memo is None else memo
|
memo = {} if memo is None else memo
|
||||||
@ -83,25 +73,20 @@ class Circle(Shape):
|
|||||||
|
|
||||||
def to_polygons(
|
def to_polygons(
|
||||||
self,
|
self,
|
||||||
poly_num_points: Optional[int] = None,
|
num_vertices: Optional[int] = DEFAULT_POLY_NUM_VERTICES,
|
||||||
poly_max_arclen: Optional[float] = None,
|
max_arclen: Optional[float] = None,
|
||||||
) -> List[Polygon]:
|
) -> List[Polygon]:
|
||||||
if poly_num_points is None:
|
if (num_vertices is None) and (max_arclen is None):
|
||||||
poly_num_points = self.poly_num_points
|
|
||||||
if poly_max_arclen is None:
|
|
||||||
poly_max_arclen = self.poly_max_arclen
|
|
||||||
|
|
||||||
if (poly_num_points is None) and (poly_max_arclen is None):
|
|
||||||
raise PatternError('Number of points and arclength left '
|
raise PatternError('Number of points and arclength left '
|
||||||
'unspecified (default was also overridden)')
|
'unspecified (default was also overridden)')
|
||||||
|
|
||||||
n: List[float] = []
|
n: List[float] = []
|
||||||
if poly_num_points is not None:
|
if num_vertices is not None:
|
||||||
n += [poly_num_points]
|
n += [num_vertices]
|
||||||
if poly_max_arclen is not None:
|
if max_arclen is not None:
|
||||||
n += [2 * pi * self.radius / poly_max_arclen]
|
n += [2 * pi * self.radius / max_arclen]
|
||||||
num_points = int(round(max(n)))
|
num_vertices = int(round(max(n)))
|
||||||
thetas = numpy.linspace(2 * pi, 0, num_points, endpoint=False)
|
thetas = numpy.linspace(2 * pi, 0, num_vertices, endpoint=False)
|
||||||
xs = numpy.cos(thetas) * self.radius
|
xs = numpy.cos(thetas) * self.radius
|
||||||
ys = numpy.sin(thetas) * self.radius
|
ys = numpy.sin(thetas) * self.radius
|
||||||
xys = numpy.vstack((xs, ys)).T
|
xys = numpy.vstack((xs, ys)).T
|
||||||
|
@ -6,7 +6,7 @@ import numpy
|
|||||||
from numpy import pi
|
from numpy import pi
|
||||||
from numpy.typing import ArrayLike, NDArray
|
from numpy.typing import ArrayLike, NDArray
|
||||||
|
|
||||||
from . import Shape, Polygon, normalized_shape_tuple, DEFAULT_POLY_NUM_POINTS
|
from . import Shape, Polygon, normalized_shape_tuple, DEFAULT_POLY_NUM_VERTICES
|
||||||
from ..error import PatternError
|
from ..error import PatternError
|
||||||
from ..repetition import Repetition
|
from ..repetition import Repetition
|
||||||
from ..utils import is_scalar, rotation_matrix_2d, layer_t, annotations_t
|
from ..utils import is_scalar, rotation_matrix_2d, layer_t, annotations_t
|
||||||
@ -19,7 +19,6 @@ class Ellipse(Shape):
|
|||||||
"""
|
"""
|
||||||
__slots__ = (
|
__slots__ = (
|
||||||
'_radii', '_rotation',
|
'_radii', '_rotation',
|
||||||
'poly_num_points', 'poly_max_arclen',
|
|
||||||
# Inherited
|
# Inherited
|
||||||
'_offset', '_layer', '_repetition', '_annotations',
|
'_offset', '_layer', '_repetition', '_annotations',
|
||||||
)
|
)
|
||||||
@ -30,12 +29,6 @@ class Ellipse(Shape):
|
|||||||
_rotation: float
|
_rotation: float
|
||||||
""" Angle from x-axis to first radius (ccw, radians) """
|
""" Angle from x-axis to first radius (ccw, radians) """
|
||||||
|
|
||||||
poly_num_points: Optional[int]
|
|
||||||
""" Sets the default number of points for `.polygonize()` """
|
|
||||||
|
|
||||||
poly_max_arclen: Optional[float]
|
|
||||||
""" Sets the default max segement length for `.polygonize()` """
|
|
||||||
|
|
||||||
# radius properties
|
# radius properties
|
||||||
@property
|
@property
|
||||||
def radii(self) -> Any: # TODO mypy#3004 NDArray[numpy.float64]:
|
def radii(self) -> Any: # TODO mypy#3004 NDArray[numpy.float64]:
|
||||||
@ -95,8 +88,6 @@ class Ellipse(Shape):
|
|||||||
self,
|
self,
|
||||||
radii: ArrayLike,
|
radii: ArrayLike,
|
||||||
*,
|
*,
|
||||||
poly_num_points: Optional[int] = DEFAULT_POLY_NUM_POINTS,
|
|
||||||
poly_max_arclen: Optional[float] = None,
|
|
||||||
offset: ArrayLike = (0.0, 0.0),
|
offset: ArrayLike = (0.0, 0.0),
|
||||||
rotation: float = 0,
|
rotation: float = 0,
|
||||||
mirrored: Sequence[bool] = (False, False),
|
mirrored: Sequence[bool] = (False, False),
|
||||||
@ -122,8 +113,6 @@ class Ellipse(Shape):
|
|||||||
self.annotations = annotations if annotations is not None else {}
|
self.annotations = annotations if annotations is not None else {}
|
||||||
self.layer = layer
|
self.layer = layer
|
||||||
[self.mirror(a) for a, do in enumerate(mirrored) if do]
|
[self.mirror(a) for a, do in enumerate(mirrored) if do]
|
||||||
self.poly_num_points = poly_num_points
|
|
||||||
self.poly_max_arclen = poly_max_arclen
|
|
||||||
|
|
||||||
def __deepcopy__(self, memo: Optional[Dict] = None) -> 'Ellipse':
|
def __deepcopy__(self, memo: Optional[Dict] = None) -> 'Ellipse':
|
||||||
memo = {} if memo is None else memo
|
memo = {} if memo is None else memo
|
||||||
@ -135,15 +124,10 @@ class Ellipse(Shape):
|
|||||||
|
|
||||||
def to_polygons(
|
def to_polygons(
|
||||||
self,
|
self,
|
||||||
poly_num_points: Optional[int] = None,
|
num_vertices: Optional[int] = DEFAULT_POLY_NUM_VERTICES,
|
||||||
poly_max_arclen: Optional[float] = None,
|
max_arclen: Optional[float] = None,
|
||||||
) -> List[Polygon]:
|
) -> List[Polygon]:
|
||||||
if poly_num_points is None:
|
if (num_vertices is None) and (max_arclen is None):
|
||||||
poly_num_points = self.poly_num_points
|
|
||||||
if poly_max_arclen is None:
|
|
||||||
poly_max_arclen = self.poly_max_arclen
|
|
||||||
|
|
||||||
if (poly_num_points is None) and (poly_max_arclen is None):
|
|
||||||
raise PatternError('Number of points and arclength left unspecified'
|
raise PatternError('Number of points and arclength left unspecified'
|
||||||
' (default was also overridden)')
|
' (default was also overridden)')
|
||||||
|
|
||||||
@ -156,12 +140,12 @@ class Ellipse(Shape):
|
|||||||
perimeter = pi * (r1 + r0) * (1 + 3 * h / (10 + math.sqrt(4 - 3 * h)))
|
perimeter = pi * (r1 + r0) * (1 + 3 * h / (10 + math.sqrt(4 - 3 * h)))
|
||||||
|
|
||||||
n = []
|
n = []
|
||||||
if poly_num_points is not None:
|
if num_vertices is not None:
|
||||||
n += [poly_num_points]
|
n += [num_vertices]
|
||||||
if poly_max_arclen is not None:
|
if max_arclen is not None:
|
||||||
n += [perimeter / poly_max_arclen]
|
n += [perimeter / max_arclen]
|
||||||
num_points = int(round(max(n)))
|
num_vertices = int(round(max(n)))
|
||||||
thetas = numpy.linspace(2 * pi, 0, num_points, endpoint=False)
|
thetas = numpy.linspace(2 * pi, 0, num_vertices, endpoint=False)
|
||||||
|
|
||||||
sin_th, cos_th = (numpy.sin(thetas), numpy.cos(thetas))
|
sin_th, cos_th = (numpy.sin(thetas), numpy.cos(thetas))
|
||||||
xs = r0 * cos_th
|
xs = r0 * cos_th
|
||||||
|
@ -243,8 +243,8 @@ class Path(Shape):
|
|||||||
|
|
||||||
def to_polygons(
|
def to_polygons(
|
||||||
self,
|
self,
|
||||||
poly_num_points: Optional[int] = None,
|
num_vertices: Optional[int] = None,
|
||||||
poly_max_arclen: Optional[float] = None,
|
max_arclen: Optional[float] = None,
|
||||||
) -> List['Polygon']:
|
) -> List['Polygon']:
|
||||||
extensions = self._calculate_cap_extensions()
|
extensions = self._calculate_cap_extensions()
|
||||||
|
|
||||||
@ -311,7 +311,7 @@ class Path(Shape):
|
|||||||
#for vert in v: # not sure if every vertex, or just ends?
|
#for vert in v: # not sure if every vertex, or just ends?
|
||||||
for vert in [v[0], v[-1]]:
|
for vert in [v[0], v[-1]]:
|
||||||
circ = Circle(offset=vert, radius=self.width / 2, layer=self.layer)
|
circ = Circle(offset=vert, radius=self.width / 2, layer=self.layer)
|
||||||
polys += circ.to_polygons(poly_num_points=poly_num_points, poly_max_arclen=poly_max_arclen)
|
polys += circ.to_polygons(num_vertices=num_vertices, max_arclen=max_arclen)
|
||||||
|
|
||||||
return polys
|
return polys
|
||||||
|
|
||||||
@ -372,8 +372,12 @@ class Path(Shape):
|
|||||||
|
|
||||||
return ((type(self), reordered_vertices.data.tobytes(), width0, self.cap, self.layer),
|
return ((type(self), reordered_vertices.data.tobytes(), width0, self.cap, self.layer),
|
||||||
(offset, scale / norm_value, rotation, False),
|
(offset, scale / norm_value, rotation, False),
|
||||||
lambda: Path(reordered_vertices * norm_value, width=self.width * norm_value,
|
lambda: Path(
|
||||||
cap=self.cap, layer=self.layer))
|
reordered_vertices * norm_value,
|
||||||
|
width=self.width * norm_value,
|
||||||
|
cap=self.cap,
|
||||||
|
layer=self.layer,
|
||||||
|
))
|
||||||
|
|
||||||
def clean_vertices(self) -> 'Path':
|
def clean_vertices(self) -> 'Path':
|
||||||
"""
|
"""
|
||||||
|
@ -333,8 +333,8 @@ class Polygon(Shape):
|
|||||||
|
|
||||||
def to_polygons(
|
def to_polygons(
|
||||||
self,
|
self,
|
||||||
poly_num_points: Optional[int] = None, # unused
|
num_vertices: Optional[int] = None, # unused
|
||||||
poly_max_arclen: Optional[float] = None, # unused
|
max_arclen: Optional[float] = None, # unused
|
||||||
) -> List['Polygon']:
|
) -> List['Polygon']:
|
||||||
return [copy.deepcopy(self)]
|
return [copy.deepcopy(self)]
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ normalized_shape_tuple = Tuple[
|
|||||||
|
|
||||||
# ## Module-wide defaults
|
# ## Module-wide defaults
|
||||||
# Default number of points per polygon for shapes
|
# Default number of points per polygon for shapes
|
||||||
DEFAULT_POLY_NUM_POINTS = 24
|
DEFAULT_POLY_NUM_VERTICES = 24
|
||||||
|
|
||||||
|
|
||||||
T = TypeVar('T', bound='Shape')
|
T = TypeVar('T', bound='Shape')
|
||||||
|
@ -110,8 +110,8 @@ class Text(RotatableImpl, Shape):
|
|||||||
|
|
||||||
def to_polygons(
|
def to_polygons(
|
||||||
self,
|
self,
|
||||||
poly_num_points: Optional[int] = None, # unused
|
num_vertices: Optional[int] = None, # unused
|
||||||
poly_max_arclen: Optional[float] = None, # unused
|
max_arclen: Optional[float] = None, # unused
|
||||||
) -> List[Polygon]:
|
) -> List[Polygon]:
|
||||||
all_polygons = []
|
all_polygons = []
|
||||||
total_advance = 0.0
|
total_advance = 0.0
|
||||||
@ -146,12 +146,14 @@ class Text(RotatableImpl, Shape):
|
|||||||
rotation %= 2 * pi
|
rotation %= 2 * pi
|
||||||
return ((type(self), self.string, self.font_path, self.layer),
|
return ((type(self), self.string, self.font_path, self.layer),
|
||||||
(self.offset, self.height / norm_value, rotation, mirror_x),
|
(self.offset, self.height / norm_value, rotation, mirror_x),
|
||||||
lambda: Text(string=self.string,
|
lambda: Text(
|
||||||
|
string=self.string,
|
||||||
height=self.height * norm_value,
|
height=self.height * norm_value,
|
||||||
font_path=self.font_path,
|
font_path=self.font_path,
|
||||||
rotation=rotation,
|
rotation=rotation,
|
||||||
mirrored=(mirror_x, False),
|
mirrored=(mirror_x, False),
|
||||||
layer=self.layer))
|
layer=self.layer,
|
||||||
|
))
|
||||||
|
|
||||||
def get_bounds(self) -> NDArray[numpy.float64]:
|
def get_bounds(self) -> NDArray[numpy.float64]:
|
||||||
# rotation makes this a huge pain when using slot.advance and glyph.bbox(), so
|
# rotation makes this a huge pain when using slot.advance and glyph.bbox(), so
|
||||||
|
Loading…
Reference in New Issue
Block a user