Add mirroring functions to patterns/subpatterns
This commit is contained in:
parent
d5a255a9d7
commit
f580e784f7
@ -351,6 +351,40 @@ class Pattern:
|
|||||||
entry.rotate(rotation)
|
entry.rotate(rotation)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def mirror_element_centers(self, axis: int) -> 'Pattern':
|
||||||
|
"""
|
||||||
|
Mirror the offsets of all shapes and subpatterns across an axis
|
||||||
|
|
||||||
|
:param axis: Axis to mirror across
|
||||||
|
:return: self
|
||||||
|
"""
|
||||||
|
for entry in self.shapes + self.subpatterns:
|
||||||
|
entry.offset[axis] *= -1
|
||||||
|
return self
|
||||||
|
|
||||||
|
def mirror_elements(self, axis: int) -> 'Pattern':
|
||||||
|
"""
|
||||||
|
Mirror each shape and subpattern across an axis, relative to its
|
||||||
|
center (offset)
|
||||||
|
|
||||||
|
:param axis: Axis to mirror across
|
||||||
|
:return: self
|
||||||
|
"""
|
||||||
|
for entry in self.shapes + self.subpatterns:
|
||||||
|
entry.mirror(axis)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def mirror(self, axis: int) -> 'Pattern':
|
||||||
|
"""
|
||||||
|
Mirror the Pattern across an axis
|
||||||
|
|
||||||
|
:param axis: Axis to mirror across
|
||||||
|
:return: self
|
||||||
|
"""
|
||||||
|
self.mirror_elements(axis)
|
||||||
|
self.mirror_element_centers(axis)
|
||||||
|
return self
|
||||||
|
|
||||||
def scale_element_doses(self, factor: float) -> 'Pattern':
|
def scale_element_doses(self, factor: float) -> 'Pattern':
|
||||||
"""
|
"""
|
||||||
Multiply all shape and subpattern doses by a factor
|
Multiply all shape and subpattern doses by a factor
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
offset, rotation, scaling, and other such properties to the reference.
|
offset, rotation, scaling, and other such properties to the reference.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Union
|
from typing import Union, List
|
||||||
|
|
||||||
import numpy
|
import numpy
|
||||||
from numpy import pi
|
from numpy import pi
|
||||||
@ -26,11 +26,13 @@ class SubPattern:
|
|||||||
_rotation = 0.0 # type: float
|
_rotation = 0.0 # type: float
|
||||||
_dose = 1.0 # type: float
|
_dose = 1.0 # type: float
|
||||||
_scale = 1.0 # type: float
|
_scale = 1.0 # type: float
|
||||||
|
_mirrored = None # type: List[bool]
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
pattern: 'Pattern',
|
pattern: 'Pattern',
|
||||||
offset: vector2=(0.0, 0.0),
|
offset: vector2=(0.0, 0.0),
|
||||||
rotation: float=0.0,
|
rotation: float=0.0,
|
||||||
|
mirrored: List[bool]=None,
|
||||||
dose: float=1.0,
|
dose: float=1.0,
|
||||||
scale: float=1.0):
|
scale: float=1.0):
|
||||||
self.pattern = pattern
|
self.pattern = pattern
|
||||||
@ -38,6 +40,9 @@ class SubPattern:
|
|||||||
self.rotation = rotation
|
self.rotation = rotation
|
||||||
self.dose = dose
|
self.dose = dose
|
||||||
self.scale = scale
|
self.scale = scale
|
||||||
|
if mirrored is None:
|
||||||
|
mirrored = [False, False]
|
||||||
|
self.mirrored = mirrored
|
||||||
|
|
||||||
# offset property
|
# offset property
|
||||||
@property
|
@property
|
||||||
@ -90,6 +95,17 @@ class SubPattern:
|
|||||||
raise PatternError('Rotation must be a scalar')
|
raise PatternError('Rotation must be a scalar')
|
||||||
self._rotation = val % (2 * pi)
|
self._rotation = val % (2 * pi)
|
||||||
|
|
||||||
|
# Mirrored property
|
||||||
|
@property
|
||||||
|
def mirrored(self) -> List[bool]:
|
||||||
|
return self._mirrored
|
||||||
|
|
||||||
|
@mirrored.setter
|
||||||
|
def mirrored(self, val: List[bool]):
|
||||||
|
if is_scalar(val):
|
||||||
|
raise PatternError('Mirrored must be a 2-element list of booleans')
|
||||||
|
self._mirrored = val
|
||||||
|
|
||||||
def as_pattern(self) -> 'Pattern':
|
def as_pattern(self) -> 'Pattern':
|
||||||
"""
|
"""
|
||||||
Returns a copy of self.pattern which has been scaled, rotated, etc. according to this
|
Returns a copy of self.pattern which has been scaled, rotated, etc. according to this
|
||||||
@ -98,6 +114,7 @@ class SubPattern:
|
|||||||
"""
|
"""
|
||||||
pattern = self.pattern.copy()
|
pattern = self.pattern.copy()
|
||||||
pattern.scale_by(self.scale)
|
pattern.scale_by(self.scale)
|
||||||
|
[pattern.mirror(ax) for ax, do in enumerate(self.mirrored) if do]
|
||||||
pattern.rotate_around((0.0, 0.0), self.rotation)
|
pattern.rotate_around((0.0, 0.0), self.rotation)
|
||||||
pattern.translate_elements(self.offset)
|
pattern.translate_elements(self.offset)
|
||||||
pattern.scale_element_doses(self.dose)
|
pattern.scale_element_doses(self.dose)
|
||||||
@ -138,6 +155,16 @@ class SubPattern:
|
|||||||
self.rotation += rotation
|
self.rotation += rotation
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def mirror(self, axis: int) -> 'SubPattern':
|
||||||
|
"""
|
||||||
|
Mirror the subpattern across an axis.
|
||||||
|
|
||||||
|
:param axis: Axis to mirror across.
|
||||||
|
:return: self
|
||||||
|
"""
|
||||||
|
self.mirrored[axis] = not self.mirrored[axis]
|
||||||
|
return self
|
||||||
|
|
||||||
def get_bounds(self) -> numpy.ndarray or None:
|
def get_bounds(self) -> numpy.ndarray or None:
|
||||||
"""
|
"""
|
||||||
Return a numpy.ndarray containing [[x_min, y_min], [x_max, y_max]], corresponding to the
|
Return a numpy.ndarray containing [[x_min, y_min], [x_max, y_max]], corresponding to the
|
||||||
|
Loading…
Reference in New Issue
Block a user