various fixes

This commit is contained in:
Jan Petykiewicz 2020-08-12 21:43:46 -07:00
parent b98553a770
commit d14182998b
6 changed files with 33 additions and 26 deletions

View File

@ -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':
"""

View File

@ -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

View File

@ -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]:

View File

@ -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

View File

@ -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)

View File

@ -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)