Assembly transformations

scadpy.core.assembly.transformations.color_assembly(assembly, color, get_assembly_parts, concat_parts)
scadpy.core.assembly.transformations.linear_pattern_assembly(assembly, counts, steps, translate, concat, dimensions)

Create a linear (grid) pattern of an assembly along one or more axes.

Uses dependency injection to remain type-agnostic and work with any assembly type (Shape, Solid, etc.).

Parameters:
assemblyA

The assembly to repeat.

countsint | Sequence[int]

Number of copies along each axis. A single int creates a 1D pattern. A sequence of ints creates a 2D or 3D grid pattern.

stepsNDArray[np.float64] | Sequence[NDArray[np.float64]]

Translation vector between consecutive copies along each axis. Must be a single vector when counts is an int, or a sequence of vectors matching the length of counts.

translateCallable[[A, NDArray[np.float64]], A]

Function that translates an assembly by a displacement vector.

concatCallable[[Sequence[A]], A]

Function that concatenates a sequence of assemblies into one.

dimensionsint

Number of spatial dimensions

Returns:
A

The patterned assembly containing prod(counts) copies of the original, including the copy at the origin.

scadpy.core.assembly.transformations.radial_pattern_assembly(assembly, count, angle, rotate, concat)

Create a radial pattern of an assembly around an axis.

Uses dependency injection to remain type-agnostic and work with any assembly type (Shape, Solid, etc.).

Parameters:
assemblyA

The assembly to repeat.

countint

Number of copies.

anglefloat

Total sweep angle in degrees.

rotateCallable[[A, float], A]

Function that rotates an assembly by a given angle.

concatCallable[[Sequence[A]], A]

Function that concatenates a sequence of assemblies into one.

Returns:
A

The patterned assembly containing count copies of the original.

scadpy.core.assembly.transformations.mirror_vertex_coordinates(vertex_coordinates, normal, pivot=0)

Mirror vertex coordinates across a line (2D) or plane (3D) defined by a normal vector and a pivot point.

Parameters:
vertex_coordinatesNDArray[np.float64]

2D array of shape (n_vertices, dimensions).

normalfloat | Iterable[float]

The normal vector of the mirror line (2D) or plane (3D). Does not need to be normalized. If a single float is provided, it will be broadcast to all coordinate dimensions.

pivotfloat | Iterable[float], default=0

The point through which the mirror line/plane passes. If a single float is provided, it will be broadcast to all coordinate dimensions. Defaults to 0 (the origin).

Returns:
NDArray[np.float64]

Array of shape (n_vertices, dimensions), one row per vertex.

Examples

>>> from shapely.geometry import Polygon
>>> from scadpy import mirror_vertex_coordinates, Shape
>>> polygon = Polygon([(0, 0), (2, 0), (2, 2), (0, 2)])
>>> shape = Shape.from_geometries([polygon])
>>> mirror_vertex_coordinates(
...     shape.vertex_coordinates,
...     normal=[1, 0],  # Mirror across y-axis
...     pivot=[1, 0]
... )
array([[2., 0.],
       [0., 0.],
       [0., 2.],
       [2., 2.]])
scadpy.core.assembly.transformations.pull_vertex_coordinates(vertex_coordinates, distance, pivot=0, vertex_filter=None)

Move selected vertices toward a pivot point by at most distance units.

Each selected vertex is translated in the direction of the pivot by at most distance. Vertices already closer than distance to the pivot are moved exactly to the pivot.

Parameters:
vertex_coordinatesNDArray[np.float64]

2D array of shape (n_vertices, dimensions).

distancefloat

The maximum distance each vertex is moved toward the pivot.

pivotfloat | Iterable[float], default=0

The point vertices are pulled toward. If a single float is provided, it is broadcast to all coordinate dimensions. Defaults to the origin.

vertex_filterNDArray[np.bool_] | None, default=None

Boolean array selecting which vertices are moved. If None, all vertices are moved.

Returns:
NDArray[np.float64]

Array of shape (n_vertices, dimensions), one row per vertex.

See also

push_vertex_coordinates

Move vertices away from a pivot point.

scadpy.core.assembly.transformations.push_vertex_coordinates(vertex_coordinates, distance, pivot=0, vertex_filter=None)

Move selected vertices away from a pivot point by distance units.

Each selected vertex is translated in the direction away from the pivot by exactly distance. Vertices located exactly at the pivot are not moved (undefined direction).

Parameters:
vertex_coordinatesNDArray[np.float64]

2D array of shape (n_vertices, dimensions).

distancefloat

The distance each vertex is moved away from the pivot.

pivotfloat | Iterable[float], default=0

The point vertices are pushed away from. If a single float is provided, it is broadcast to all coordinate dimensions. Defaults to the origin.

vertex_filterNDArray[np.bool_] | None, default=None

Boolean array selecting which vertices are moved. If None, all vertices are moved.

Returns:
NDArray[np.float64]

Array of shape (n_vertices, dimensions), one row per vertex.

See also

pull_vertex_coordinates

Move vertices toward a pivot point.

scadpy.core.assembly.transformations.resize_vertex_coordinates(vertex_coordinates, size, n_dims, auto=False, pivot=None, vertex_filter=None)

Resize vertex coordinates to fit target dimensions.

Computes per-axis scale factors from the bounding box of vertex_coordinates and size, then delegates to scale_vertex_coordinates().

None entries in size mark axes to leave unchanged. When auto=True, those axes are scaled proportionally to the average ratio of the defined axes instead.

Parameters:
vertex_coordinatesNDArray[np.float64]

2D array of shape (n_vertices, n_dims).

sizeIterable[float | None]

Target dimensions. None for an axis means “leave unchanged” (or “scale proportionally” when auto=True). Broadcast rules from resolve_vector() apply: a shorter iterable is padded with None (no resize on missing axes).

n_dimsint

Number of coordinate dimensions. Used to broadcast size and pivot to the correct length via resolve_vector().

autobool, default=False

If True, axes with None are scaled proportionally to the average ratio of the defined axes.

pivotfloat | Iterable[float] | None, default=None

The point relative to which scaling is applied. Defaults to the center of the bounding box of vertex_coordinates.

vertex_filterNDArray[np.bool_] | None, default=None

Boolean array selecting which vertices are resized. If None, all vertices are resized.

Returns:
NDArray[np.float64]

Array of shape (n_vertices, n_dims), one row per vertex.

Examples

>>> import numpy as np
>>> from scadpy import resize_vertex_coordinates

Resize a 4×2 rectangle to 6×6:

>>> coordinates = np.array(
...     [[0., 0.], [4., 0.], [4., 2.], [0., 2.]], dtype=np.float64
... )
>>> result = resize_vertex_coordinates(coordinates, size=[6, 6], n_dims=2)
>>> (result.max(axis=0) - result.min(axis=0)).tolist()
[6.0, 6.0]

Freeze the Y axis (None):

>>> result = resize_vertex_coordinates(coordinates, size=[6, None], n_dims=2)
>>> (result.max(axis=0) - result.min(axis=0)).tolist()
[6.0, 2.0]

Scale the Y axis proportionally with auto=True:

>>> result = resize_vertex_coordinates(
...     coordinates, size=[6, None], n_dims=2, auto=True
... )
>>> (result.max(axis=0) - result.min(axis=0)).tolist()
[6.0, 3.0]
scadpy.core.assembly.transformations.rotate_vertex_coordinates(vertex_coordinates, rotation_matrix, pivot=0, vertex_filter=None)

Rotate vertex coordinates using a precomputed rotation matrix and a pivot point.

Parameters:
vertex_coordinatesNDArray[np.float64]

2D array of shape (n_vertices, dimensions).

rotation_matrixNDArray[np.float64]

Square rotation matrix of shape (dimensions, dimensions).

pivotfloat | Iterable[float], default=0

The point around which rotation is applied. If a single float is provided, it will be broadcast to all coordinate dimensions. Defaults to the origin.

vertex_filterNDArray[np.bool_] | None, default=None

Boolean array selecting which vertices are rotated. If None, all vertices are rotated.

Returns:
NDArray[np.float64]

Array of shape (n_vertices, dimensions), one row per vertex.

Examples

>>> import numpy as np
>>> from shapely.geometry import Polygon
>>> from scadpy import rotate_vertex_coordinates, Shape
>>> polygon = Polygon([(0, 0), (2, 0), (2, 2), (0, 2)])
>>> shape = Shape.from_geometries([polygon])
>>> angle = np.deg2rad(90)
>>> R = np.array([
...     [np.cos(angle), -np.sin(angle)],
...     [np.sin(angle), np.cos(angle)],
... ])
>>> rotate_vertex_coordinates(
...     shape.vertex_coordinates,
...     R,
...     pivot=[1, 1],
... ).round(10)
array([[2., 0.],
       [2., 2.],
       [0., 2.],
       [0., 0.]])
scadpy.core.assembly.transformations.scale_vertex_coordinates(vertex_coordinates, scale, pivot=0, vertex_filter=None)

Scale vertex coordinates by a given factor or vector, relative to a pivot.

Parameters:
vertex_coordinatesNDArray[np.float64]

2D array of shape (n_vertices, dimensions).

scalefloat | Iterable[float]

The scaling factor(s) to apply. Its length should match the number of coordinate dimensions. If a single float is provided, it will be broadcast to all coordinate dimensions.

pivotfloat | Iterable[float], default=0

The point relative to which scaling is performed. If a single float is provided, it will be broadcast to all coordinate dimensions. Defaults to 0 (the origin).

vertex_filterNDArray[np.bool_] | None, default=None

Boolean array selecting which vertices are scaled. If None, all vertices are scaled.

Returns:
NDArray[np.float64]

Array of shape (n_vertices, dimensions), one row per vertex.

Examples

>>> from shapely.geometry import Polygon
>>> from scadpy import scale_vertex_coordinates, Shape
>>> polygon1 = Polygon(
...     shell=[(0, 0), (2, 0), (2, 2), (0, 2)],
...     holes=[[(0.5, 0.5), (1.5, 0.5), (1.5, 1.5), (0.5, 1.5)]]
... )
>>> polygon2 = Polygon(
...     shell=[(10, 10), (12, 10), (12, 12), (10, 12)]
... )
>>> shape = Shape.from_geometries([polygon1, polygon2])
>>> scale_vertex_coordinates(
...     shape.vertex_coordinates,
...     scale=[10, 0.5],
...     pivot=[1, 2]
... )
array([[ -9.  ,   1.  ],
       [ 11.  ,   1.  ],
       [ 11.  ,   2.  ],
       ...
       [111.  ,   6.  ],
       [111.  ,   7.  ],
       [ 91.  ,   7.  ]])
scadpy.core.assembly.transformations.translate_vertex_coordinates(vertex_coordinates, translation, vertex_filter=None)

Translate vertex coordinates by a given vector.

Parameters:
vertex_coordinatesNDArray[np.float64]

2D array of shape (n_vertices, dimensions).

translationfloat | Iterable[float]

The translation vector to apply. Its length should match the number of coordinate dimensions. If a single float is provided, it will be broadcast to all coordinate dimensions.

vertex_filterNDArray[np.bool_] | None, default=None

Boolean array selecting which vertices are translated. If None, all vertices are translated.

Returns:
NDArray[np.float64]

Array of shape (n_vertices, dimensions), one row per vertex.

Examples

>>> from shapely.geometry import Polygon
>>> from scadpy import translate_vertex_coordinates, Shape
>>> polygon1 = Polygon(
...     shell=[(0, 0), (2, 0), (2, 2), (0, 2)],
...     holes=[[(0.5, 0.5), (1.5, 0.5), (1.5, 1.5), (0.5, 1.5)]]
... )
>>> polygon2 = Polygon(
...     shell=[(10, 10), (12, 10), (12, 12), (10, 12)]
... )
>>> shape = Shape.from_geometries([polygon1, polygon2])
>>> translate_vertex_coordinates(
...     shape.vertex_coordinates,
...     translation=[10, 20]
... )
array([[10. , 20. ],
       [12. , 20. ],
       [12. , 22. ],
       ...
       [22. , 30. ],
       [22. , 32. ],
       [20. , 32. ]])