various fixes
This commit is contained in:
parent
b98553a770
commit
d14182998b
@ -170,8 +170,8 @@ class Grid(LockableImpl, Repetition, metaclass=AutoSlots):
|
||||
@property
|
||||
def displacements(self) -> numpy.ndarray:
|
||||
aa, bb = numpy.meshgrid(numpy.arange(self.a_count), numpy.arange(self.b_count), indexing='ij')
|
||||
return (aa.flat[:, None] * self.a_vector[None, :] +
|
||||
bb.flat[:, None] * self.b_vector[None, :])
|
||||
return (aa.flatten()[:, None] * self.a_vector[None, :] +
|
||||
bb.flatten()[:, None] * self.b_vector[None, :])
|
||||
|
||||
def rotate(self, rotation: float) -> 'Grid':
|
||||
"""
|
||||
|
@ -31,16 +31,17 @@ class Shape(PositionableImpl, LayerableImpl, DoseableImpl, Rotatable, Mirrorable
|
||||
"""
|
||||
Abstract class specifying functions common to all shapes.
|
||||
"""
|
||||
__slots__ = () # Children should use AutoSlots
|
||||
|
||||
identifier: Tuple
|
||||
""" An arbitrary identifier for the shape, usually empty but used by `Pattern.flatten()` """
|
||||
|
||||
# def __copy__(self) -> 'Shape':
|
||||
# cls = self.__class__
|
||||
# new = cls.__new__(cls)
|
||||
# for name in Shape.__slots__ + self.__slots__:
|
||||
# object.__setattr__(new, name, getattr(self, name))
|
||||
# return new
|
||||
def __copy__(self) -> 'Shape':
|
||||
cls = self.__class__
|
||||
new = cls.__new__(cls)
|
||||
for name in self.__slots__:
|
||||
object.__setattr__(new, name, getattr(self, name))
|
||||
return new
|
||||
|
||||
'''
|
||||
--- Abstract methods
|
||||
|
@ -22,7 +22,7 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
class SubPattern(PositionableImpl, DoseableImpl, RotatableImpl, ScalableImpl, Mirrorable,
|
||||
Pivotable, Copyable, RepeatableImpl, LockableImpl, metaclass=AutoSlots):
|
||||
PivotableImpl, Copyable, RepeatableImpl, LockableImpl, metaclass=AutoSlots):
|
||||
"""
|
||||
SubPattern provides basic support for nesting Pattern objects within each other, by adding
|
||||
offset, rotation, scaling, and associated methods.
|
||||
@ -83,6 +83,7 @@ class SubPattern(PositionableImpl, DoseableImpl, RotatableImpl, ScalableImpl, Mi
|
||||
dose=self.dose,
|
||||
scale=self.scale,
|
||||
mirrored=self.mirrored.copy(),
|
||||
repetition=copy.deepcopy(self.repetition),
|
||||
locked=self.locked)
|
||||
return new
|
||||
|
||||
@ -90,6 +91,7 @@ class SubPattern(PositionableImpl, DoseableImpl, RotatableImpl, ScalableImpl, Mi
|
||||
memo = {} if memo is None else memo
|
||||
new = copy.copy(self).unlock()
|
||||
new.pattern = copy.deepcopy(self.pattern, memo)
|
||||
new.repetition = copy.deepcopy(self.repetition, memo)
|
||||
new.locked = self.locked
|
||||
return new
|
||||
|
||||
@ -140,18 +142,17 @@ class SubPattern(PositionableImpl, DoseableImpl, RotatableImpl, ScalableImpl, Mi
|
||||
|
||||
return pattern
|
||||
|
||||
def rotate(self, rotation: float) -> 'SubPattern':
|
||||
self.rotation += rotation
|
||||
if self.repetition is not None:
|
||||
self.repetition.rotate(rotation)
|
||||
return self
|
||||
|
||||
def mirror(self, axis: int) -> 'SubPattern':
|
||||
"""
|
||||
Mirror the subpattern across an axis.
|
||||
|
||||
Args:
|
||||
axis: Axis to mirror across.
|
||||
|
||||
Returns:
|
||||
self
|
||||
"""
|
||||
self.mirrored[axis] = not self.mirrored[axis]
|
||||
self.rotation *= -1
|
||||
if self.repetition is not None:
|
||||
self.repetiton.mirror(axis)
|
||||
return self
|
||||
|
||||
def get_bounds(self) -> Optional[numpy.ndarray]:
|
||||
|
@ -94,7 +94,7 @@ class PositionableImpl(Positionable, metaclass=ABCMeta):
|
||||
|
||||
@offset.setter
|
||||
def offset(self, val: vector2):
|
||||
if not isinstance(val, numpy.ndarray):
|
||||
if not isinstance(val, numpy.ndarray) or val.dtype != numpy.float64:
|
||||
val = numpy.array(val, dtype=float)
|
||||
|
||||
if val.size != 2:
|
||||
@ -109,7 +109,6 @@ class PositionableImpl(Positionable, metaclass=ABCMeta):
|
||||
self.offset = offset
|
||||
return self
|
||||
|
||||
|
||||
def translate(self: I, offset: vector2) -> I:
|
||||
self._offset += offset
|
||||
return self
|
||||
|
@ -109,6 +109,7 @@ class PivotableImpl(Pivotable, metaclass=ABCMeta):
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
@abstractmethod
|
||||
def rotate_around(self: J, pivot: vector2, rotation: float) -> J:
|
||||
pivot = numpy.array(pivot, dtype=float)
|
||||
self.translate(-pivot)
|
||||
|
@ -148,11 +148,16 @@ class AutoSlots(ABCMeta):
|
||||
can be used to generate a full `__slots__` for the concrete class.
|
||||
"""
|
||||
def __new__(cls, name, bases, dctn):
|
||||
slots = tuple(dctn.get('__slots__', tuple()))
|
||||
parents = set()
|
||||
for base in bases:
|
||||
if not hasattr(base, '__annotations__'):
|
||||
continue
|
||||
slots += tuple(getattr(base, '__annotations__').keys())
|
||||
dctn['__slots__'] = slots
|
||||
return super().__new__(cls,name,bases,dctn)
|
||||
parents |= set(base.mro())
|
||||
|
||||
slots = tuple(dctn.get('__slots__', tuple()))
|
||||
for parent in parents:
|
||||
if not hasattr(parent, '__annotations__'):
|
||||
continue
|
||||
slots += tuple(getattr(parent, '__annotations__').keys())
|
||||
|
||||
dctn['__slots__'] = slots
|
||||
return super().__new__(cls, name, bases, dctn)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user