simetri.graphics.core

Base class. This is the parent for Shape and Batch classes.

  1"""Base class. This is the parent for Shape and Batch classes."""
  2
  3__all__ = [
  4    "Base",
  5]
  6
  7from typing import Sequence, Any, Union
  8from typing_extensions import Self
  9
 10import numpy as np
 11from numpy import ndarray
 12
 13from .all_enums import Anchor, Side, get_enum_value, anchors
 14from .common import (
 15    Point,
 16    Line,
 17)
 18from .affine import (
 19    translation_matrix,
 20    rotation_matrix,
 21    mirror_matrix,
 22    glide_matrix,
 23    scale_in_place_matrix,
 24    shear_matrix,
 25)
 26from ..geometry.geometry import line_angle
 27
 28
 29class Base:
 30    """Base class for Shape and Batch objects."""
 31
 32    def __getattr__(self, name: str) -> Any:
 33        if name in anchors:
 34            res = getattr(self.b_box, name)
 35        else:
 36            try:
 37                res = self.__dict__[name]
 38            except KeyError as exc:
 39                try:
 40                    res = super().__getattr__(name)
 41                except AttributeError as exc:
 42                    msg = f"'{self.__class__.__name__}' object has no attribute '{name}'"
 43                    raise AttributeError(msg) from exc
 44
 45        return res
 46
 47
 48    def translate(self, dx: float = 0, dy: float = 0, reps: int = 0) -> Self:
 49        """
 50        Translates the object by dx and dy.
 51
 52        Args:
 53            dx (float): The translation distance along the x-axis.
 54            dy (float): The translation distance along the y-axis.
 55            reps (int, optional): The number of repetitions. Defaults to 0.
 56
 57        Returns:
 58            Self: The transformed object.
 59        """
 60        transform = translation_matrix(dx, dy)
 61        return self._update(transform, reps=reps)
 62
 63    def translate_along(
 64        self,
 65        path: Sequence[Point],
 66        step: int = 1,
 67        align_tangent: bool = False,
 68        scale: float = 1,  # scale factor
 69        rotate: float = 0,  # angle in radians
 70    ) -> Self:
 71        """
 72        Translates the object along the given curve.
 73        Every n-th point is used to calculate the translation vector.
 74        If align_tangent is True, the object is rotated to align with the tangent at each point.
 75        scale is the scale factor applied at each point.
 76        rotate is the angle in radians applied at each point.
 77
 78        Args:
 79            path (Sequence[Point]): The path to translate along.
 80            step (int, optional): The step size. Defaults to 1.
 81            align_tangent (bool, optional): Whether to align the object with the tangent. Defaults to False.
 82            scale (float, optional): The scale factor. Defaults to 1.
 83            rotate (float, optional): The rotation angle in radians. Defaults to 0.
 84
 85        Returns:
 86            Self: The transformed object.
 87        """
 88        x, y = path[0][:2]
 89        self.move_to((x, y))
 90        dup = self.copy()
 91        if align_tangent:
 92            tangent = line_angle(path[-1], path[0])
 93            self.rotate(tangent, about=path[0], reps=0)
 94        dup2 = dup.copy()
 95        for i, point in enumerate(path[1::step]):
 96            dup2 = dup2.copy()
 97            px, py = point[:2]
 98            dup2.move_to((px, py))
 99            if scale != 1:
100                dup2.scale(scale, about=point)
101            if rotate != 0:
102                dup2.rotate(rotate, about=point)
103            self.append(dup2)
104            if align_tangent:
105                tangent = line_angle(path[i - 1], path[i])
106                dup2.rotate(tangent, about=point, reps=0)
107            # scale *= scale
108            # rotate += rotate
109        return self
110
111    def rotate(self, angle: float, about: Point = (0, 0), reps: int = 0) -> Self:
112        """
113        Rotates the object by the given angle (in radians) about the given point.
114
115        Args:
116            angle (float): The rotation angle in radians.
117            about (Point, optional): The point to rotate about. Defaults to (0, 0).
118            reps (int, optional): The number of repetitions. Defaults to 0.
119
120        Returns:
121            Self: The rotated object.
122        """
123        transform = rotation_matrix(angle, about)
124        return self._update(transform, reps=reps)
125
126    def mirror(self, about: Union[Line, Point], reps: int = 0) -> Self:
127        """
128        Mirrors the object about the given line or point.
129
130        Args:
131            about (Union[Line, Point]): The line or point to mirror about.
132            reps (int, optional): The number of repetitions. Defaults to 0.
133
134        Returns:
135            Self: The mirrored object.
136        """
137        transform = mirror_matrix(about)
138        return self._update(transform, reps=reps)
139
140    def glide(self, glide_line: Line, glide_dist: float, reps: int = 0) -> Self:
141        """
142        Glides (first mirror then translate) the object along the given line
143        by the given glide_dist.
144
145        Args:
146            glide_line (Line): The line to glide along.
147            glide_dist (float): The distance to glide.
148            reps (int, optional): The number of repetitions. Defaults to 0.
149
150        Returns:
151            Self: The glided object.
152        """
153        transform = glide_matrix(glide_line, glide_dist)
154        return self._update(transform, reps=reps)
155
156    def scale(
157        self,
158        scale_x: float,
159        scale_y: Union[float, None] = None,
160        about: Point = (0, 0),
161        reps: int = 0,
162    ) -> Self:
163        """
164        Scales the object by the given scale factors about the given point.
165
166        Args:
167            scale_x (float): The scale factor in the x direction.
168            scale_y (float, optional): The scale factor in the y direction. Defaults to None.
169            about (Point, optional): The point to scale about. Defaults to (0, 0).
170            reps (int, optional): The number of repetitions. Defaults to 0.
171
172        Returns:
173            Self: The scaled object.
174        """
175        if scale_y is None:
176            scale_y = scale_x
177        transform = scale_in_place_matrix(scale_x, scale_y, about)
178        return self._update(transform, reps=reps)
179
180    def shear(self, theta_x: float, theta_y: float, reps: int = 0) -> Self:
181        """
182        Shears the object by the given angles.
183
184        Args:
185            theta_x (float): The shear angle in the x direction.
186            theta_y (float): The shear angle in the y direction.
187            reps (int, optional): The number of repetitions. Defaults to 0.
188
189        Returns:
190            Self: The sheared object.
191        """
192        transform = shear_matrix(theta_x, theta_y)
193        return self._update(transform, reps=reps)
194
195    def reset_xform_matrix(self) -> Self:
196        """
197        Resets the transformation matrix to the identity matrix.
198
199        Returns:
200            Self: The object with the reset transformation matrix.
201        """
202        self.__dict__["xform_matrix"] = np.identity(3)
203        return self
204
205    def transform(self, transform_matrix: ndarray, reps: int = 0) -> Self:
206        """
207        Transforms the object by the given transformation matrix.
208
209        Args:
210            transform_matrix (ndarray): The transformation matrix.
211            reps (int, optional): The number of repetitions. Defaults to 0.
212
213        Returns:
214            Self: The transformed object.
215        """
216        return self._update(transform_matrix, reps=reps)
217
218    def move_to(self, pos: Point, anchor: Anchor = Anchor.CENTER) -> Self:
219        """
220        Moves the object to the given position by using its center point.
221
222        Args:
223            pos (Point): The position to move to.
224            anchor (Anchor, optional): The anchor point. Defaults to Anchor.CENTER.
225
226        Returns:
227            Self: The moved object.
228        """
229        x, y = pos[:2]
230        anchor = get_enum_value(Anchor, anchor)
231        x1, y1 = getattr(self.b_box, anchor)
232        transform = translation_matrix(x - x1, y - y1)
233        return self._update(transform, reps=0)
234
235    def offset_line(self, side: Side, offset: float) -> Line:
236        """
237        Offset the line by the given side and offset distance.
238        side can be Side.LEFT, Side.RIGHT, Side.TOP, or Side.BOTTOM.
239        offset is applied outwards.
240
241        Args:
242            side (Side): The side to offset.
243            offset (float): The offset distance.
244
245        Returns:
246            Line: The offset line.
247        """
248        side = get_enum_value(Side, side)
249        return self.b_box.offset_line(side, offset)
250
251    def offset_point(self, anchor: Anchor, dx: float, dy: float = 0) -> Point:
252        """
253        Offset the point by the given anchor and offset distances.
254        anchor can be Anchor.CENTER, Anchor.SOUTHWEST, Anchor.SOUTHEAST,
255        Anchor.NORTHWEST, Anchor.NORTHEAST, Anchor.SOUTH, Anchor.WEST,
256        Anchor.EAST, or Anchor.NORTH.
257
258        Args:
259            anchor (Anchor): The anchor point.
260            dx (float): The x offset.
261            dy (float, optional): The y offset. Defaults to 0.
262
263        Returns:
264            Point: The offset point.
265        """
266        anchor = get_enum_value(Anchor, anchor)
267        return self.b_box.offset_point(anchor, dx, dy)
268
269
270class StyleMixin:
271    """Mixin class for style attributes.
272    Shape class inherits from this.
273    Some Batch classes with different subtypes also inherit from this.
274    """
275    def __setattr__(self, name, value):
276        """Set an attribute of the shape.
277
278        Args:
279            name (str): The name of the attribute.
280            value (Any): The value to set.
281        """
282        obj, attrib = self.__dict__["_aliasses"].get(name, (None, None))
283        if obj:
284            setattr(obj, attrib, value)
285        else:
286            self.__dict__[name] = value
287
288    def __getattr__(self, name):
289        """Retrieve an attribute of the shape.
290
291        Args:
292            name (str): The attribute name to return.
293
294        Returns:
295            Any: The value of the attribute.
296
297        Raises:
298            AttributeError: If the attribute cannot be found.
299        """
300        obj, attrib = self.__dict__["_aliasses"].get(name, (None, None))
301        if obj:
302            res = getattr(obj, attrib)
303        else:
304            res = self.__dict__[name]
305        return res
306
307    def _set_aliases(self):
308        """Set aliases for style attributes based on the style map."""
309        _aliasses = {}
310        for alias, path_attrib in self._style_map.items():
311            style_path, attrib = path_attrib
312            obj = self
313            for attrib_name in style_path.split("."):
314                obj = obj.__dict__[attrib_name]
315            _aliasses[alias] = (obj, attrib)
316
317        self.__dict__["_aliasses"] = _aliasses
class Base:
 30class Base:
 31    """Base class for Shape and Batch objects."""
 32
 33    def __getattr__(self, name: str) -> Any:
 34        if name in anchors:
 35            res = getattr(self.b_box, name)
 36        else:
 37            try:
 38                res = self.__dict__[name]
 39            except KeyError as exc:
 40                try:
 41                    res = super().__getattr__(name)
 42                except AttributeError as exc:
 43                    msg = f"'{self.__class__.__name__}' object has no attribute '{name}'"
 44                    raise AttributeError(msg) from exc
 45
 46        return res
 47
 48
 49    def translate(self, dx: float = 0, dy: float = 0, reps: int = 0) -> Self:
 50        """
 51        Translates the object by dx and dy.
 52
 53        Args:
 54            dx (float): The translation distance along the x-axis.
 55            dy (float): The translation distance along the y-axis.
 56            reps (int, optional): The number of repetitions. Defaults to 0.
 57
 58        Returns:
 59            Self: The transformed object.
 60        """
 61        transform = translation_matrix(dx, dy)
 62        return self._update(transform, reps=reps)
 63
 64    def translate_along(
 65        self,
 66        path: Sequence[Point],
 67        step: int = 1,
 68        align_tangent: bool = False,
 69        scale: float = 1,  # scale factor
 70        rotate: float = 0,  # angle in radians
 71    ) -> Self:
 72        """
 73        Translates the object along the given curve.
 74        Every n-th point is used to calculate the translation vector.
 75        If align_tangent is True, the object is rotated to align with the tangent at each point.
 76        scale is the scale factor applied at each point.
 77        rotate is the angle in radians applied at each point.
 78
 79        Args:
 80            path (Sequence[Point]): The path to translate along.
 81            step (int, optional): The step size. Defaults to 1.
 82            align_tangent (bool, optional): Whether to align the object with the tangent. Defaults to False.
 83            scale (float, optional): The scale factor. Defaults to 1.
 84            rotate (float, optional): The rotation angle in radians. Defaults to 0.
 85
 86        Returns:
 87            Self: The transformed object.
 88        """
 89        x, y = path[0][:2]
 90        self.move_to((x, y))
 91        dup = self.copy()
 92        if align_tangent:
 93            tangent = line_angle(path[-1], path[0])
 94            self.rotate(tangent, about=path[0], reps=0)
 95        dup2 = dup.copy()
 96        for i, point in enumerate(path[1::step]):
 97            dup2 = dup2.copy()
 98            px, py = point[:2]
 99            dup2.move_to((px, py))
100            if scale != 1:
101                dup2.scale(scale, about=point)
102            if rotate != 0:
103                dup2.rotate(rotate, about=point)
104            self.append(dup2)
105            if align_tangent:
106                tangent = line_angle(path[i - 1], path[i])
107                dup2.rotate(tangent, about=point, reps=0)
108            # scale *= scale
109            # rotate += rotate
110        return self
111
112    def rotate(self, angle: float, about: Point = (0, 0), reps: int = 0) -> Self:
113        """
114        Rotates the object by the given angle (in radians) about the given point.
115
116        Args:
117            angle (float): The rotation angle in radians.
118            about (Point, optional): The point to rotate about. Defaults to (0, 0).
119            reps (int, optional): The number of repetitions. Defaults to 0.
120
121        Returns:
122            Self: The rotated object.
123        """
124        transform = rotation_matrix(angle, about)
125        return self._update(transform, reps=reps)
126
127    def mirror(self, about: Union[Line, Point], reps: int = 0) -> Self:
128        """
129        Mirrors the object about the given line or point.
130
131        Args:
132            about (Union[Line, Point]): The line or point to mirror about.
133            reps (int, optional): The number of repetitions. Defaults to 0.
134
135        Returns:
136            Self: The mirrored object.
137        """
138        transform = mirror_matrix(about)
139        return self._update(transform, reps=reps)
140
141    def glide(self, glide_line: Line, glide_dist: float, reps: int = 0) -> Self:
142        """
143        Glides (first mirror then translate) the object along the given line
144        by the given glide_dist.
145
146        Args:
147            glide_line (Line): The line to glide along.
148            glide_dist (float): The distance to glide.
149            reps (int, optional): The number of repetitions. Defaults to 0.
150
151        Returns:
152            Self: The glided object.
153        """
154        transform = glide_matrix(glide_line, glide_dist)
155        return self._update(transform, reps=reps)
156
157    def scale(
158        self,
159        scale_x: float,
160        scale_y: Union[float, None] = None,
161        about: Point = (0, 0),
162        reps: int = 0,
163    ) -> Self:
164        """
165        Scales the object by the given scale factors about the given point.
166
167        Args:
168            scale_x (float): The scale factor in the x direction.
169            scale_y (float, optional): The scale factor in the y direction. Defaults to None.
170            about (Point, optional): The point to scale about. Defaults to (0, 0).
171            reps (int, optional): The number of repetitions. Defaults to 0.
172
173        Returns:
174            Self: The scaled object.
175        """
176        if scale_y is None:
177            scale_y = scale_x
178        transform = scale_in_place_matrix(scale_x, scale_y, about)
179        return self._update(transform, reps=reps)
180
181    def shear(self, theta_x: float, theta_y: float, reps: int = 0) -> Self:
182        """
183        Shears the object by the given angles.
184
185        Args:
186            theta_x (float): The shear angle in the x direction.
187            theta_y (float): The shear angle in the y direction.
188            reps (int, optional): The number of repetitions. Defaults to 0.
189
190        Returns:
191            Self: The sheared object.
192        """
193        transform = shear_matrix(theta_x, theta_y)
194        return self._update(transform, reps=reps)
195
196    def reset_xform_matrix(self) -> Self:
197        """
198        Resets the transformation matrix to the identity matrix.
199
200        Returns:
201            Self: The object with the reset transformation matrix.
202        """
203        self.__dict__["xform_matrix"] = np.identity(3)
204        return self
205
206    def transform(self, transform_matrix: ndarray, reps: int = 0) -> Self:
207        """
208        Transforms the object by the given transformation matrix.
209
210        Args:
211            transform_matrix (ndarray): The transformation matrix.
212            reps (int, optional): The number of repetitions. Defaults to 0.
213
214        Returns:
215            Self: The transformed object.
216        """
217        return self._update(transform_matrix, reps=reps)
218
219    def move_to(self, pos: Point, anchor: Anchor = Anchor.CENTER) -> Self:
220        """
221        Moves the object to the given position by using its center point.
222
223        Args:
224            pos (Point): The position to move to.
225            anchor (Anchor, optional): The anchor point. Defaults to Anchor.CENTER.
226
227        Returns:
228            Self: The moved object.
229        """
230        x, y = pos[:2]
231        anchor = get_enum_value(Anchor, anchor)
232        x1, y1 = getattr(self.b_box, anchor)
233        transform = translation_matrix(x - x1, y - y1)
234        return self._update(transform, reps=0)
235
236    def offset_line(self, side: Side, offset: float) -> Line:
237        """
238        Offset the line by the given side and offset distance.
239        side can be Side.LEFT, Side.RIGHT, Side.TOP, or Side.BOTTOM.
240        offset is applied outwards.
241
242        Args:
243            side (Side): The side to offset.
244            offset (float): The offset distance.
245
246        Returns:
247            Line: The offset line.
248        """
249        side = get_enum_value(Side, side)
250        return self.b_box.offset_line(side, offset)
251
252    def offset_point(self, anchor: Anchor, dx: float, dy: float = 0) -> Point:
253        """
254        Offset the point by the given anchor and offset distances.
255        anchor can be Anchor.CENTER, Anchor.SOUTHWEST, Anchor.SOUTHEAST,
256        Anchor.NORTHWEST, Anchor.NORTHEAST, Anchor.SOUTH, Anchor.WEST,
257        Anchor.EAST, or Anchor.NORTH.
258
259        Args:
260            anchor (Anchor): The anchor point.
261            dx (float): The x offset.
262            dy (float, optional): The y offset. Defaults to 0.
263
264        Returns:
265            Point: The offset point.
266        """
267        anchor = get_enum_value(Anchor, anchor)
268        return self.b_box.offset_point(anchor, dx, dy)

Base class for Shape and Batch objects.

def translate( self, dx: float = 0, dy: float = 0, reps: int = 0) -> typing_extensions.Self:
49    def translate(self, dx: float = 0, dy: float = 0, reps: int = 0) -> Self:
50        """
51        Translates the object by dx and dy.
52
53        Args:
54            dx (float): The translation distance along the x-axis.
55            dy (float): The translation distance along the y-axis.
56            reps (int, optional): The number of repetitions. Defaults to 0.
57
58        Returns:
59            Self: The transformed object.
60        """
61        transform = translation_matrix(dx, dy)
62        return self._update(transform, reps=reps)

Translates the object by dx and dy.

Arguments:
  • dx (float): The translation distance along the x-axis.
  • dy (float): The translation distance along the y-axis.
  • reps (int, optional): The number of repetitions. Defaults to 0.
Returns:

Self: The transformed object.

def translate_along( self, path: Sequence[Sequence[float]], step: int = 1, align_tangent: bool = False, scale: float = 1, rotate: float = 0) -> typing_extensions.Self:
 64    def translate_along(
 65        self,
 66        path: Sequence[Point],
 67        step: int = 1,
 68        align_tangent: bool = False,
 69        scale: float = 1,  # scale factor
 70        rotate: float = 0,  # angle in radians
 71    ) -> Self:
 72        """
 73        Translates the object along the given curve.
 74        Every n-th point is used to calculate the translation vector.
 75        If align_tangent is True, the object is rotated to align with the tangent at each point.
 76        scale is the scale factor applied at each point.
 77        rotate is the angle in radians applied at each point.
 78
 79        Args:
 80            path (Sequence[Point]): The path to translate along.
 81            step (int, optional): The step size. Defaults to 1.
 82            align_tangent (bool, optional): Whether to align the object with the tangent. Defaults to False.
 83            scale (float, optional): The scale factor. Defaults to 1.
 84            rotate (float, optional): The rotation angle in radians. Defaults to 0.
 85
 86        Returns:
 87            Self: The transformed object.
 88        """
 89        x, y = path[0][:2]
 90        self.move_to((x, y))
 91        dup = self.copy()
 92        if align_tangent:
 93            tangent = line_angle(path[-1], path[0])
 94            self.rotate(tangent, about=path[0], reps=0)
 95        dup2 = dup.copy()
 96        for i, point in enumerate(path[1::step]):
 97            dup2 = dup2.copy()
 98            px, py = point[:2]
 99            dup2.move_to((px, py))
100            if scale != 1:
101                dup2.scale(scale, about=point)
102            if rotate != 0:
103                dup2.rotate(rotate, about=point)
104            self.append(dup2)
105            if align_tangent:
106                tangent = line_angle(path[i - 1], path[i])
107                dup2.rotate(tangent, about=point, reps=0)
108            # scale *= scale
109            # rotate += rotate
110        return self

Translates the object along the given curve. Every n-th point is used to calculate the translation vector. If align_tangent is True, the object is rotated to align with the tangent at each point. scale is the scale factor applied at each point. rotate is the angle in radians applied at each point.

Arguments:
  • path (Sequence[Point]): The path to translate along.
  • step (int, optional): The step size. Defaults to 1.
  • align_tangent (bool, optional): Whether to align the object with the tangent. Defaults to False.
  • scale (float, optional): The scale factor. Defaults to 1.
  • rotate (float, optional): The rotation angle in radians. Defaults to 0.
Returns:

Self: The transformed object.

def rotate( self, angle: float, about: Sequence[float] = (0, 0), reps: int = 0) -> typing_extensions.Self:
112    def rotate(self, angle: float, about: Point = (0, 0), reps: int = 0) -> Self:
113        """
114        Rotates the object by the given angle (in radians) about the given point.
115
116        Args:
117            angle (float): The rotation angle in radians.
118            about (Point, optional): The point to rotate about. Defaults to (0, 0).
119            reps (int, optional): The number of repetitions. Defaults to 0.
120
121        Returns:
122            Self: The rotated object.
123        """
124        transform = rotation_matrix(angle, about)
125        return self._update(transform, reps=reps)

Rotates the object by the given angle (in radians) about the given point.

Arguments:
  • angle (float): The rotation angle in radians.
  • about (Point, optional): The point to rotate about. Defaults to (0, 0).
  • reps (int, optional): The number of repetitions. Defaults to 0.
Returns:

Self: The rotated object.

def mirror( self, about: Union[Sequence[Sequence], Sequence[float]], reps: int = 0) -> typing_extensions.Self:
127    def mirror(self, about: Union[Line, Point], reps: int = 0) -> Self:
128        """
129        Mirrors the object about the given line or point.
130
131        Args:
132            about (Union[Line, Point]): The line or point to mirror about.
133            reps (int, optional): The number of repetitions. Defaults to 0.
134
135        Returns:
136            Self: The mirrored object.
137        """
138        transform = mirror_matrix(about)
139        return self._update(transform, reps=reps)

Mirrors the object about the given line or point.

Arguments:
  • about (Union[Line, Point]): The line or point to mirror about.
  • reps (int, optional): The number of repetitions. Defaults to 0.
Returns:

Self: The mirrored object.

def glide( self, glide_line: Sequence[Sequence], glide_dist: float, reps: int = 0) -> typing_extensions.Self:
141    def glide(self, glide_line: Line, glide_dist: float, reps: int = 0) -> Self:
142        """
143        Glides (first mirror then translate) the object along the given line
144        by the given glide_dist.
145
146        Args:
147            glide_line (Line): The line to glide along.
148            glide_dist (float): The distance to glide.
149            reps (int, optional): The number of repetitions. Defaults to 0.
150
151        Returns:
152            Self: The glided object.
153        """
154        transform = glide_matrix(glide_line, glide_dist)
155        return self._update(transform, reps=reps)

Glides (first mirror then translate) the object along the given line by the given glide_dist.

Arguments:
  • glide_line (Line): The line to glide along.
  • glide_dist (float): The distance to glide.
  • reps (int, optional): The number of repetitions. Defaults to 0.
Returns:

Self: The glided object.

def scale( self, scale_x: float, scale_y: Optional[float] = None, about: Sequence[float] = (0, 0), reps: int = 0) -> typing_extensions.Self:
157    def scale(
158        self,
159        scale_x: float,
160        scale_y: Union[float, None] = None,
161        about: Point = (0, 0),
162        reps: int = 0,
163    ) -> Self:
164        """
165        Scales the object by the given scale factors about the given point.
166
167        Args:
168            scale_x (float): The scale factor in the x direction.
169            scale_y (float, optional): The scale factor in the y direction. Defaults to None.
170            about (Point, optional): The point to scale about. Defaults to (0, 0).
171            reps (int, optional): The number of repetitions. Defaults to 0.
172
173        Returns:
174            Self: The scaled object.
175        """
176        if scale_y is None:
177            scale_y = scale_x
178        transform = scale_in_place_matrix(scale_x, scale_y, about)
179        return self._update(transform, reps=reps)

Scales the object by the given scale factors about the given point.

Arguments:
  • scale_x (float): The scale factor in the x direction.
  • scale_y (float, optional): The scale factor in the y direction. Defaults to None.
  • about (Point, optional): The point to scale about. Defaults to (0, 0).
  • reps (int, optional): The number of repetitions. Defaults to 0.
Returns:

Self: The scaled object.

def shear( self, theta_x: float, theta_y: float, reps: int = 0) -> typing_extensions.Self:
181    def shear(self, theta_x: float, theta_y: float, reps: int = 0) -> Self:
182        """
183        Shears the object by the given angles.
184
185        Args:
186            theta_x (float): The shear angle in the x direction.
187            theta_y (float): The shear angle in the y direction.
188            reps (int, optional): The number of repetitions. Defaults to 0.
189
190        Returns:
191            Self: The sheared object.
192        """
193        transform = shear_matrix(theta_x, theta_y)
194        return self._update(transform, reps=reps)

Shears the object by the given angles.

Arguments:
  • theta_x (float): The shear angle in the x direction.
  • theta_y (float): The shear angle in the y direction.
  • reps (int, optional): The number of repetitions. Defaults to 0.
Returns:

Self: The sheared object.

def reset_xform_matrix(self) -> typing_extensions.Self:
196    def reset_xform_matrix(self) -> Self:
197        """
198        Resets the transformation matrix to the identity matrix.
199
200        Returns:
201            Self: The object with the reset transformation matrix.
202        """
203        self.__dict__["xform_matrix"] = np.identity(3)
204        return self

Resets the transformation matrix to the identity matrix.

Returns:

Self: The object with the reset transformation matrix.

def transform( self, transform_matrix: numpy.ndarray, reps: int = 0) -> typing_extensions.Self:
206    def transform(self, transform_matrix: ndarray, reps: int = 0) -> Self:
207        """
208        Transforms the object by the given transformation matrix.
209
210        Args:
211            transform_matrix (ndarray): The transformation matrix.
212            reps (int, optional): The number of repetitions. Defaults to 0.
213
214        Returns:
215            Self: The transformed object.
216        """
217        return self._update(transform_matrix, reps=reps)

Transforms the object by the given transformation matrix.

Arguments:
  • transform_matrix (ndarray): The transformation matrix.
  • reps (int, optional): The number of repetitions. Defaults to 0.
Returns:

Self: The transformed object.

def move_to( self, pos: Sequence[float], anchor: simetri.graphics.all_enums.Anchor = <Anchor.CENTER: 'center'>) -> typing_extensions.Self:
219    def move_to(self, pos: Point, anchor: Anchor = Anchor.CENTER) -> Self:
220        """
221        Moves the object to the given position by using its center point.
222
223        Args:
224            pos (Point): The position to move to.
225            anchor (Anchor, optional): The anchor point. Defaults to Anchor.CENTER.
226
227        Returns:
228            Self: The moved object.
229        """
230        x, y = pos[:2]
231        anchor = get_enum_value(Anchor, anchor)
232        x1, y1 = getattr(self.b_box, anchor)
233        transform = translation_matrix(x - x1, y - y1)
234        return self._update(transform, reps=0)

Moves the object to the given position by using its center point.

Arguments:
  • pos (Point): The position to move to.
  • anchor (Anchor, optional): The anchor point. Defaults to Anchor.CENTER.
Returns:

Self: The moved object.

def offset_line( self, side: simetri.graphics.all_enums.Side, offset: float) -> Sequence[Sequence]:
236    def offset_line(self, side: Side, offset: float) -> Line:
237        """
238        Offset the line by the given side and offset distance.
239        side can be Side.LEFT, Side.RIGHT, Side.TOP, or Side.BOTTOM.
240        offset is applied outwards.
241
242        Args:
243            side (Side): The side to offset.
244            offset (float): The offset distance.
245
246        Returns:
247            Line: The offset line.
248        """
249        side = get_enum_value(Side, side)
250        return self.b_box.offset_line(side, offset)

Offset the line by the given side and offset distance. side can be Side.LEFT, Side.RIGHT, Side.TOP, or Side.BOTTOM. offset is applied outwards.

Arguments:
  • side (Side): The side to offset.
  • offset (float): The offset distance.
Returns:

Line: The offset line.

def offset_point( self, anchor: simetri.graphics.all_enums.Anchor, dx: float, dy: float = 0) -> Sequence[float]:
252    def offset_point(self, anchor: Anchor, dx: float, dy: float = 0) -> Point:
253        """
254        Offset the point by the given anchor and offset distances.
255        anchor can be Anchor.CENTER, Anchor.SOUTHWEST, Anchor.SOUTHEAST,
256        Anchor.NORTHWEST, Anchor.NORTHEAST, Anchor.SOUTH, Anchor.WEST,
257        Anchor.EAST, or Anchor.NORTH.
258
259        Args:
260            anchor (Anchor): The anchor point.
261            dx (float): The x offset.
262            dy (float, optional): The y offset. Defaults to 0.
263
264        Returns:
265            Point: The offset point.
266        """
267        anchor = get_enum_value(Anchor, anchor)
268        return self.b_box.offset_point(anchor, dx, dy)

Offset the point by the given anchor and offset distances. anchor can be Anchor.CENTER, Anchor.SOUTHWEST, Anchor.SOUTHEAST, Anchor.NORTHWEST, Anchor.NORTHEAST, Anchor.SOUTH, Anchor.WEST, Anchor.EAST, or Anchor.NORTH.

Arguments:
  • anchor (Anchor): The anchor point.
  • dx (float): The x offset.
  • dy (float, optional): The y offset. Defaults to 0.
Returns:

Point: The offset point.