ScadPy 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scadpy/__init__.py +5 -0
- scadpy/color/__init__.py +3 -0
- scadpy/color/constants/BEIGE.py +3 -0
- scadpy/color/constants/BLACK.py +3 -0
- scadpy/color/constants/BLUE.py +3 -0
- scadpy/color/constants/BROWN.py +3 -0
- scadpy/color/constants/DARK_GRAY.py +3 -0
- scadpy/color/constants/DEFAULT_COLOR.py +3 -0
- scadpy/color/constants/DEFAULT_OPACITY.py +1 -0
- scadpy/color/constants/GRAY.py +3 -0
- scadpy/color/constants/GREEN.py +3 -0
- scadpy/color/constants/ORANGE.py +3 -0
- scadpy/color/constants/RED.py +3 -0
- scadpy/color/constants/WHITE.py +3 -0
- scadpy/color/constants/YELLOW.py +3 -0
- scadpy/color/constants/__init__.py +29 -0
- scadpy/color/type/__init__.py +3 -0
- scadpy/color/type/color.py +3 -0
- scadpy/color/utils/__init__.py +3 -0
- scadpy/color/utils/get_random_color.py +36 -0
- scadpy/core/__init__.py +3 -0
- scadpy/core/assembly/__init__.py +5 -0
- scadpy/core/assembly/combinations/__init__.py +13 -0
- scadpy/core/assembly/combinations/concat_assemblies.py +50 -0
- scadpy/core/assembly/combinations/exclude_assemblies.py +135 -0
- scadpy/core/assembly/combinations/intersect_assemblies.py +128 -0
- scadpy/core/assembly/combinations/subtract_assemblies.py +151 -0
- scadpy/core/assembly/combinations/unify_assemblies.py +59 -0
- scadpy/core/assembly/topologies/__init__.py +41 -0
- scadpy/core/assembly/topologies/directed_edge/__init__.py +9 -0
- scadpy/core/assembly/topologies/directed_edge/get_assembly_directed_edge_directions.py +70 -0
- scadpy/core/assembly/topologies/directed_edge/get_assembly_directed_edge_to_edge.py +49 -0
- scadpy/core/assembly/topologies/directed_edge/get_assembly_directed_edge_to_vertex.py +54 -0
- scadpy/core/assembly/topologies/edge/__init__.py +9 -0
- scadpy/core/assembly/topologies/edge/get_assembly_edge_lengths.py +46 -0
- scadpy/core/assembly/topologies/edge/get_assembly_edge_midpoints.py +51 -0
- scadpy/core/assembly/topologies/edge/get_assembly_edge_normals.py +67 -0
- scadpy/core/assembly/topologies/face_corner/__init__.py +13 -0
- scadpy/core/assembly/topologies/face_corner/get_assembly_face_corner_angles.py +72 -0
- scadpy/core/assembly/topologies/face_corner/get_assembly_face_corner_normals.py +103 -0
- scadpy/core/assembly/topologies/face_corner/get_assembly_face_corner_to_incoming_directed_edge.py +65 -0
- scadpy/core/assembly/topologies/face_corner/get_assembly_face_corner_to_outgoing_directed_edge.py +65 -0
- scadpy/core/assembly/topologies/face_corner/get_assembly_face_directed_edge_to_corner.py +79 -0
- scadpy/core/assembly/topologies/part/__init__.py +5 -0
- scadpy/core/assembly/topologies/part/get_assembly_part_colors.py +55 -0
- scadpy/core/assembly/topologies/vertex/__init__.py +7 -0
- scadpy/core/assembly/topologies/vertex/get_assembly_vertex_coordinates.py +70 -0
- scadpy/core/assembly/topologies/vertex/get_assembly_vertex_to_part.py +62 -0
- scadpy/core/assembly/transformations/__init__.py +19 -0
- scadpy/core/assembly/transformations/color_assembly.py +24 -0
- scadpy/core/assembly/transformations/mirror_vertex_coordinates.py +68 -0
- scadpy/core/assembly/transformations/pull_vertex_coordinates.py +64 -0
- scadpy/core/assembly/transformations/push_vertex_coordinates.py +64 -0
- scadpy/core/assembly/transformations/resize_vertex_coordinates.py +121 -0
- scadpy/core/assembly/transformations/rotate_vertex_coordinates.py +73 -0
- scadpy/core/assembly/transformations/scale_vertex_coordinates.py +76 -0
- scadpy/core/assembly/transformations/translate_vertex_coordinates.py +70 -0
- scadpy/core/assembly/types/__init__.py +7 -0
- scadpy/core/assembly/types/assembly.py +14 -0
- scadpy/core/assembly/types/topology_filter.py +6 -0
- scadpy/core/assembly/utils/__init__.py +9 -0
- scadpy/core/assembly/utils/lookup_pairs.py +56 -0
- scadpy/core/assembly/utils/resolve_topology_filter.py +84 -0
- scadpy/core/assembly/utils/transform_filtered_parts.py +55 -0
- scadpy/core/component/__init__.py +3 -0
- scadpy/core/component/exporters/__init__.py +7 -0
- scadpy/core/component/exporters/map_component_to_html_file.py +47 -0
- scadpy/core/component/exporters/map_component_to_screen.py +63 -0
- scadpy/core/component/features/__init__.py +5 -0
- scadpy/core/component/features/get_component_bounds.py +38 -0
- scadpy/core/component/utils/__init__.py +9 -0
- scadpy/core/component/utils/blend_component_colors.py +77 -0
- scadpy/core/component/utils/get_intersecting_component_index_groups.py +108 -0
- scadpy/core/part/__init__.py +3 -0
- scadpy/core/part/combinations/__init__.py +11 -0
- scadpy/core/part/combinations/concat_parts.py +48 -0
- scadpy/core/part/combinations/intersect_parts.py +147 -0
- scadpy/core/part/combinations/subtract_parts.py +94 -0
- scadpy/core/part/combinations/unify_parts.py +143 -0
- scadpy/core/part/types/__init__.py +5 -0
- scadpy/core/part/types/part.py +34 -0
- scadpy/core/part/utils/__init__.py +5 -0
- scadpy/core/part/utils/blend_part_colors.py +32 -0
- scadpy/d2/__init__.py +2 -0
- scadpy/d2/shape/__init__.py +9 -0
- scadpy/d2/shape/combinations/__init__.py +21 -0
- scadpy/d2/shape/combinations/are_shape_parts_intersecting.py +49 -0
- scadpy/d2/shape/combinations/concat_shape.py +48 -0
- scadpy/d2/shape/combinations/exclude_shape.py +71 -0
- scadpy/d2/shape/combinations/intersect_shape.py +64 -0
- scadpy/d2/shape/combinations/intersect_shape_parts.py +71 -0
- scadpy/d2/shape/combinations/subtract_shape.py +72 -0
- scadpy/d2/shape/combinations/subtract_shape_parts.py +66 -0
- scadpy/d2/shape/combinations/unify_shape.py +51 -0
- scadpy/d2/shape/combinations/unify_shape_parts.py +74 -0
- scadpy/d2/shape/exporters/__init__.py +17 -0
- scadpy/d2/shape/exporters/map_shape_to_dxf.py +43 -0
- scadpy/d2/shape/exporters/map_shape_to_dxf_file.py +38 -0
- scadpy/d2/shape/exporters/map_shape_to_html.py +117 -0
- scadpy/d2/shape/exporters/map_shape_to_html_file.py +58 -0
- scadpy/d2/shape/exporters/map_shape_to_screen.py +51 -0
- scadpy/d2/shape/exporters/map_shape_to_svg.py +40 -0
- scadpy/d2/shape/exporters/map_shape_to_svg_file.py +38 -0
- scadpy/d2/shape/features/__init__.py +9 -0
- scadpy/d2/shape/features/get_shape_bounds.py +40 -0
- scadpy/d2/shape/features/get_shape_part_bounds.py +37 -0
- scadpy/d2/shape/features/is_shape_empty.py +38 -0
- scadpy/d2/shape/importers/__init__.py +13 -0
- scadpy/d2/shape/importers/map_dxf_to_shape.py +55 -0
- scadpy/d2/shape/importers/map_geometries_to_shape.py +45 -0
- scadpy/d2/shape/importers/map_geometry_to_shape.py +43 -0
- scadpy/d2/shape/importers/map_parts_to_shape.py +62 -0
- scadpy/d2/shape/importers/map_svg_to_shape.py +55 -0
- scadpy/d2/shape/primitives/__init__.py +6 -0
- scadpy/d2/shape/primitives/circle.py +68 -0
- scadpy/d2/shape/primitives/polygon.py +86 -0
- scadpy/d2/shape/primitives/rectangle.py +85 -0
- scadpy/d2/shape/primitives/square.py +57 -0
- scadpy/d2/shape/topologies/__init__.py +53 -0
- scadpy/d2/shape/topologies/corner/__init__.py +15 -0
- scadpy/d2/shape/topologies/corner/are_shape_corners_convex.py +75 -0
- scadpy/d2/shape/topologies/corner/get_shape_corner_angles.py +58 -0
- scadpy/d2/shape/topologies/corner/get_shape_corner_normals.py +82 -0
- scadpy/d2/shape/topologies/corner/get_shape_corner_to_incoming_directed_edge.py +39 -0
- scadpy/d2/shape/topologies/corner/get_shape_corner_to_outgoing_directed_edge.py +39 -0
- scadpy/d2/shape/topologies/corner/get_shape_corner_to_vertex.py +65 -0
- scadpy/d2/shape/topologies/directed_edge/__init__.py +11 -0
- scadpy/d2/shape/topologies/directed_edge/get_shape_directed_edge_directions.py +44 -0
- scadpy/d2/shape/topologies/directed_edge/get_shape_directed_edge_to_corner.py +41 -0
- scadpy/d2/shape/topologies/directed_edge/get_shape_directed_edge_to_edge.py +51 -0
- scadpy/d2/shape/topologies/directed_edge/get_shape_directed_edge_to_vertex.py +63 -0
- scadpy/d2/shape/topologies/edge/__init__.py +11 -0
- scadpy/d2/shape/topologies/edge/get_shape_edge_lengths.py +43 -0
- scadpy/d2/shape/topologies/edge/get_shape_edge_midpoints.py +46 -0
- scadpy/d2/shape/topologies/edge/get_shape_edge_normals.py +40 -0
- scadpy/d2/shape/topologies/edge/get_shape_edge_to_vertex.py +71 -0
- scadpy/d2/shape/topologies/ring/__init__.py +7 -0
- scadpy/d2/shape/topologies/ring/get_shape_ring_to_part.py +46 -0
- scadpy/d2/shape/topologies/ring/get_shape_ring_types.py +46 -0
- scadpy/d2/shape/topologies/vertex/__init__.py +11 -0
- scadpy/d2/shape/topologies/vertex/get_shape_part_vertex_coordinates.py +62 -0
- scadpy/d2/shape/topologies/vertex/get_shape_vertex_coordinates.py +44 -0
- scadpy/d2/shape/topologies/vertex/get_shape_vertex_to_part.py +42 -0
- scadpy/d2/shape/topologies/vertex/get_shape_vertex_to_ring.py +63 -0
- scadpy/d2/shape/transformations/__init__.py +43 -0
- scadpy/d2/shape/transformations/chamfer_shape.py +259 -0
- scadpy/d2/shape/transformations/color_shape.py +46 -0
- scadpy/d2/shape/transformations/convexify_shape.py +79 -0
- scadpy/d2/shape/transformations/fill_shape.py +68 -0
- scadpy/d2/shape/transformations/fillet_shape.py +289 -0
- scadpy/d2/shape/transformations/grow_shape.py +82 -0
- scadpy/d2/shape/transformations/linear_cut_shape.py +116 -0
- scadpy/d2/shape/transformations/linear_extrude_shape.py +60 -0
- scadpy/d2/shape/transformations/linear_slice_shape.py +144 -0
- scadpy/d2/shape/transformations/mirror_shape.py +53 -0
- scadpy/d2/shape/transformations/pull_shape.py +67 -0
- scadpy/d2/shape/transformations/push_shape.py +67 -0
- scadpy/d2/shape/transformations/radial_extrude_shape.py +285 -0
- scadpy/d2/shape/transformations/radial_slice_shape.py +132 -0
- scadpy/d2/shape/transformations/recoordinate_shape.py +82 -0
- scadpy/d2/shape/transformations/resize_shape.py +91 -0
- scadpy/d2/shape/transformations/rotate_shape.py +63 -0
- scadpy/d2/shape/transformations/scale_shape.py +58 -0
- scadpy/d2/shape/transformations/shrink_shape.py +69 -0
- scadpy/d2/shape/transformations/translate_shape.py +54 -0
- scadpy/d2/shape/types/__init__.py +3 -0
- scadpy/d2/shape/types/shape.py +792 -0
- scadpy/d2/shape/types/utils/__init__.py +5 -0
- scadpy/d2/shape/types/utils/shapely_base_geometry_to_shapely_polygons.py +25 -0
- scadpy/d2/shape/utils/__init__.py +5 -0
- scadpy/d2/shape/utils/shapely_base_geometry_to_shapely_polygons.py +55 -0
- scadpy/d2/utils/__init__.py +3 -0
- scadpy/d2/utils/resolve_vector_2d.py +50 -0
- scadpy/d3/__init__.py +2 -0
- scadpy/d3/solid/__init__.py +8 -0
- scadpy/d3/solid/combinations/__init__.py +21 -0
- scadpy/d3/solid/combinations/are_solid_parts_intersecting.py +51 -0
- scadpy/d3/solid/combinations/concat_solid.py +48 -0
- scadpy/d3/solid/combinations/exclude_solid.py +71 -0
- scadpy/d3/solid/combinations/intersect_solid.py +64 -0
- scadpy/d3/solid/combinations/intersect_solid_parts.py +73 -0
- scadpy/d3/solid/combinations/subtract_solid.py +72 -0
- scadpy/d3/solid/combinations/subtract_solid_parts.py +68 -0
- scadpy/d3/solid/combinations/unify_solid.py +51 -0
- scadpy/d3/solid/combinations/unify_solid_parts.py +73 -0
- scadpy/d3/solid/exporters/__init__.py +11 -0
- scadpy/d3/solid/exporters/map_solid_to_html.py +318 -0
- scadpy/d3/solid/exporters/map_solid_to_html_file.py +58 -0
- scadpy/d3/solid/exporters/map_solid_to_screen.py +51 -0
- scadpy/d3/solid/exporters/map_solid_to_stl_file.py +48 -0
- scadpy/d3/solid/features/__init__.py +11 -0
- scadpy/d3/solid/features/get_solid_bounds.py +37 -0
- scadpy/d3/solid/features/get_solid_part_bounds.py +37 -0
- scadpy/d3/solid/features/get_solid_part_colors.py +39 -0
- scadpy/d3/solid/features/is_solid_empty.py +36 -0
- scadpy/d3/solid/importers/__init__.py +11 -0
- scadpy/d3/solid/importers/map_geometries_to_solid.py +42 -0
- scadpy/d3/solid/importers/map_geometry_to_solid.py +42 -0
- scadpy/d3/solid/importers/map_parts_to_solid.py +66 -0
- scadpy/d3/solid/importers/map_stl_to_solid.py +37 -0
- scadpy/d3/solid/primitives/__init__.py +7 -0
- scadpy/d3/solid/primitives/cone.py +70 -0
- scadpy/d3/solid/primitives/cuboid.py +75 -0
- scadpy/d3/solid/primitives/cylinder.py +73 -0
- scadpy/d3/solid/primitives/polyhedron.py +60 -0
- scadpy/d3/solid/primitives/sphere.py +58 -0
- scadpy/d3/solid/topologies/__init__.py +8 -0
- scadpy/d3/solid/topologies/triangle/__init__.py +5 -0
- scadpy/d3/solid/topologies/triangle/get_solid_triangle_to_vertex.py +49 -0
- scadpy/d3/solid/topologies/vertex/__init__.py +7 -0
- scadpy/d3/solid/topologies/vertex/get_solid_vertex_coordinates.py +39 -0
- scadpy/d3/solid/topologies/vertex/get_solid_vertex_to_part.py +37 -0
- scadpy/d3/solid/transformations/__init__.py +23 -0
- scadpy/d3/solid/transformations/color_solid.py +46 -0
- scadpy/d3/solid/transformations/convexify_solid.py +64 -0
- scadpy/d3/solid/transformations/mirror_solid.py +53 -0
- scadpy/d3/solid/transformations/pull_solid.py +67 -0
- scadpy/d3/solid/transformations/push_solid.py +67 -0
- scadpy/d3/solid/transformations/recoordinate_solid.py +68 -0
- scadpy/d3/solid/transformations/resize_solid.py +92 -0
- scadpy/d3/solid/transformations/rotate_solid.py +93 -0
- scadpy/d3/solid/transformations/scale_solid.py +58 -0
- scadpy/d3/solid/transformations/translate_solid.py +54 -0
- scadpy/d3/solid/types/__init__.py +3 -0
- scadpy/d3/solid/types/solid.py +448 -0
- scadpy/d3/utils/__init__.py +3 -0
- scadpy/d3/utils/resolve_vector_3d.py +50 -0
- scadpy/utils/__init__.py +6 -0
- scadpy/utils/resolve_vector.py +64 -0
- scadpy/utils/x.py +38 -0
- scadpy/utils/y.py +38 -0
- scadpy/utils/z.py +38 -0
- scadpy-0.1.0.dist-info/METADATA +282 -0
- scadpy-0.1.0.dist-info/RECORD +236 -0
- scadpy-0.1.0.dist-info/WHEEL +4 -0
- scadpy-0.1.0.dist-info/licenses/LICENSE.md +43 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from typeguard import typechecked
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from scadpy import Shape, TopologyFilter
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@typechecked
|
|
13
|
+
def resize_shape(
|
|
14
|
+
shape: Shape,
|
|
15
|
+
size: Iterable[float | None],
|
|
16
|
+
auto: bool = False,
|
|
17
|
+
pivot: float | Iterable[float] | None = None,
|
|
18
|
+
vertex_filter: TopologyFilter[Shape] | None = None,
|
|
19
|
+
) -> Shape:
|
|
20
|
+
"""Resize a shape to fit target dimensions.
|
|
21
|
+
|
|
22
|
+
Scales the shape so that each non-``None`` axis matches the given target
|
|
23
|
+
size. The scaling pivot defaults to the center of the bounding box so the
|
|
24
|
+
shape stays in place.
|
|
25
|
+
|
|
26
|
+
Shortcut delegating to :func:`resize_vertex_coordinates`.
|
|
27
|
+
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
shape : Shape
|
|
31
|
+
The shape to resize.
|
|
32
|
+
size : Iterable[float | None]
|
|
33
|
+
Target dimensions ``[width, height]``. Pass ``None`` for an axis to
|
|
34
|
+
leave it unchanged (or scale it proportionally when ``auto=True``).
|
|
35
|
+
auto : bool, default=False
|
|
36
|
+
If ``True``, axes with ``None`` are scaled proportionally to the
|
|
37
|
+
average ratio of the defined axes. If ``False``, ``None`` axes are
|
|
38
|
+
left unchanged.
|
|
39
|
+
pivot : float | Iterable[float] | None, default=None
|
|
40
|
+
The point relative to which scaling is performed. Defaults to the
|
|
41
|
+
center of the bounding box.
|
|
42
|
+
vertex_filter : TopologyFilter[Shape] | None, default=None
|
|
43
|
+
Boolean array or callable selecting which vertices are resized. If ``None``, all
|
|
44
|
+
vertices are resized.
|
|
45
|
+
|
|
46
|
+
Returns
|
|
47
|
+
-------
|
|
48
|
+
Shape
|
|
49
|
+
A new shape resized to the target dimensions.
|
|
50
|
+
|
|
51
|
+
Examples
|
|
52
|
+
--------
|
|
53
|
+
>>> from scadpy import rectangle, resize_shape
|
|
54
|
+
|
|
55
|
+
>>> # resize to an exact size on both axes:
|
|
56
|
+
>>> resize_shape(shape=rectangle([4, 2]), size=[6, 6]) # doctest: +SKIP
|
|
57
|
+
|
|
58
|
+
.. render-example::
|
|
59
|
+
:name: resize_shape_exact
|
|
60
|
+
:example: resize_shape(shape=rectangle([4, 2]), size=[6, 6])
|
|
61
|
+
:ghost: rectangle([4, 2])
|
|
62
|
+
|
|
63
|
+
>>> # freeze one axis (``None``) to leave it unchanged:
|
|
64
|
+
>>> resize_shape(shape=rectangle([4, 2]), size=[6, None]) # doctest: +SKIP
|
|
65
|
+
|
|
66
|
+
.. render-example::
|
|
67
|
+
:name: resize_shape_freeze
|
|
68
|
+
:example: resize_shape(shape=rectangle([4, 2]), size=[6, None])
|
|
69
|
+
:ghost: rectangle([4, 2])
|
|
70
|
+
|
|
71
|
+
>>> # scale frozen axes proportionally with ``auto=True``:
|
|
72
|
+
>>> resize_shape(shape=rectangle([4, 2]), size=[6, None], auto=True) # doctest: +SKIP
|
|
73
|
+
|
|
74
|
+
.. render-example::
|
|
75
|
+
:name: resize_shape_auto
|
|
76
|
+
:example: resize_shape(shape=rectangle([4, 2]), size=[6, None], auto=True)
|
|
77
|
+
:ghost: rectangle([4, 2])
|
|
78
|
+
"""
|
|
79
|
+
from scadpy import resolve_topology_filter, resize_vertex_coordinates
|
|
80
|
+
|
|
81
|
+
resolved_vertex_filter = resolve_topology_filter(shape, len(shape.vertex_coordinates), vertex_filter)
|
|
82
|
+
return shape.recoordinate(
|
|
83
|
+
resize_vertex_coordinates(
|
|
84
|
+
shape.vertex_coordinates,
|
|
85
|
+
size=size,
|
|
86
|
+
n_dims=2,
|
|
87
|
+
auto=auto,
|
|
88
|
+
pivot=pivot,
|
|
89
|
+
vertex_filter=resolved_vertex_filter,
|
|
90
|
+
)
|
|
91
|
+
)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
from typeguard import typechecked
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from scadpy.d2.shape import Shape
|
|
11
|
+
from scadpy import TopologyFilter
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@typechecked
|
|
15
|
+
def rotate_shape(
|
|
16
|
+
shape: Shape,
|
|
17
|
+
angle: float,
|
|
18
|
+
pivot: float | Iterable[float] = 0,
|
|
19
|
+
vertex_filter: TopologyFilter[Shape] | None = None,
|
|
20
|
+
) -> Shape:
|
|
21
|
+
"""Rotate a shape by a given angle around a pivot point.
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
shape : Shape
|
|
26
|
+
The shape to rotate.
|
|
27
|
+
angle : float
|
|
28
|
+
The rotation angle in degrees (counter-clockwise).
|
|
29
|
+
pivot : float | Iterable[float], default=0
|
|
30
|
+
The point around which rotation is applied. If a single float is provided,
|
|
31
|
+
it is broadcast to all coordinate dimensions. Defaults to the origin.
|
|
32
|
+
vertex_filter : TopologyFilter[Shape] | None, default=None
|
|
33
|
+
Boolean array or callable selecting which vertices are rotated. If ``None``, all
|
|
34
|
+
vertices are rotated.
|
|
35
|
+
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
38
|
+
Shape
|
|
39
|
+
A new shape with the selected vertices rotated around the pivot.
|
|
40
|
+
|
|
41
|
+
Examples
|
|
42
|
+
--------
|
|
43
|
+
>>> from scadpy import square, rotate_shape
|
|
44
|
+
|
|
45
|
+
>>> rotate_shape( # doctest: +SKIP
|
|
46
|
+
... shape=square(4), angle=45, pivot=[2, 2]
|
|
47
|
+
... )
|
|
48
|
+
|
|
49
|
+
.. render-example::
|
|
50
|
+
:name: rotate_shape
|
|
51
|
+
:example: rotate_shape(shape=square(4), angle=45, pivot=[2, 2])
|
|
52
|
+
:ghost: square(4)
|
|
53
|
+
"""
|
|
54
|
+
from scadpy import resolve_topology_filter, rotate_vertex_coordinates
|
|
55
|
+
|
|
56
|
+
angle_rad = np.deg2rad(angle)
|
|
57
|
+
c, s = np.cos(angle_rad), np.sin(angle_rad)
|
|
58
|
+
R = np.array([[c, -s], [s, c]])
|
|
59
|
+
|
|
60
|
+
resolved_vertex_filter = resolve_topology_filter(shape, len(shape.vertex_coordinates), vertex_filter)
|
|
61
|
+
return shape.recoordinate(
|
|
62
|
+
rotate_vertex_coordinates(shape.vertex_coordinates, R, pivot, resolved_vertex_filter)
|
|
63
|
+
)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from typeguard import typechecked
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from scadpy import Shape, TopologyFilter
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@typechecked
|
|
13
|
+
def scale_shape(
|
|
14
|
+
shape: Shape,
|
|
15
|
+
scale: float | Iterable[float],
|
|
16
|
+
pivot: float | Iterable[float] = 0,
|
|
17
|
+
vertex_filter: TopologyFilter[Shape] | None = None,
|
|
18
|
+
) -> Shape:
|
|
19
|
+
"""Scale a shape by a given factor, relative to a pivot point.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
shape : Shape
|
|
24
|
+
The shape to scale.
|
|
25
|
+
scale : float | Iterable[float]
|
|
26
|
+
The scaling factor(s). If a single float is provided, it is broadcast
|
|
27
|
+
to all coordinate dimensions.
|
|
28
|
+
pivot : float | Iterable[float], default=0
|
|
29
|
+
The point relative to which scaling is performed. If a single float is
|
|
30
|
+
provided, it is broadcast to all coordinate dimensions. Defaults to the origin.
|
|
31
|
+
vertex_filter : TopologyFilter[Shape] | None, default=None
|
|
32
|
+
Boolean array or callable selecting which vertices are scaled. If ``None``, all
|
|
33
|
+
vertices are scaled.
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
Shape
|
|
38
|
+
A new shape with the selected vertices scaled relative to the pivot.
|
|
39
|
+
|
|
40
|
+
Examples
|
|
41
|
+
--------
|
|
42
|
+
>>> from scadpy import square, scale_shape
|
|
43
|
+
|
|
44
|
+
>>> scale_shape( # doctest: +SKIP
|
|
45
|
+
... shape=square(4), scale=2, pivot=[2, 2]
|
|
46
|
+
... )
|
|
47
|
+
|
|
48
|
+
.. render-example::
|
|
49
|
+
:name: scale_shape
|
|
50
|
+
:example: scale_shape(shape=square(4), scale=2, pivot=[2, 2])
|
|
51
|
+
:ghost: square(4)
|
|
52
|
+
"""
|
|
53
|
+
from scadpy import resolve_topology_filter, scale_vertex_coordinates
|
|
54
|
+
|
|
55
|
+
resolved_vertex_filter = resolve_topology_filter(shape, len(shape.vertex_coordinates), vertex_filter)
|
|
56
|
+
return shape.recoordinate(
|
|
57
|
+
scale_vertex_coordinates(shape.vertex_coordinates, scale, pivot, resolved_vertex_filter)
|
|
58
|
+
)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from typeguard import typechecked
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from scadpy import Shape, TopologyFilter
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@typechecked
|
|
12
|
+
def shrink_shape(
|
|
13
|
+
shape: Shape, distance: float, part_filter: TopologyFilter[Shape] | None = None
|
|
14
|
+
) -> Shape:
|
|
15
|
+
"""
|
|
16
|
+
Shrink each selected part by offsetting its boundary inward by a given distance.
|
|
17
|
+
|
|
18
|
+
This is a convenience wrapper around :func:`grow_shape` with a negated distance.
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
shape : Shape
|
|
23
|
+
The input shape whose parts will be shrunk.
|
|
24
|
+
distance : float
|
|
25
|
+
The offset distance. Positive values shrink inward, negative values expand outward.
|
|
26
|
+
part_filter : TopologyFilter[Shape] | None, optional
|
|
27
|
+
A boolean mask selecting which parts to shrink. If None, all parts are shrunk.
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
Shape
|
|
32
|
+
A new shape with the selected parts shrunk and the unselected parts unchanged.
|
|
33
|
+
|
|
34
|
+
Examples
|
|
35
|
+
--------
|
|
36
|
+
>>> from scadpy import shrink_shape, square
|
|
37
|
+
>>> import numpy as np
|
|
38
|
+
|
|
39
|
+
>>> shape = square(10)
|
|
40
|
+
>>> shrink_shape(shape, 2) # doctest: +SKIP
|
|
41
|
+
|
|
42
|
+
.. render-example::
|
|
43
|
+
:name: shrink_shape
|
|
44
|
+
:example: shrink_shape(shape, 2)
|
|
45
|
+
:ghost: shape
|
|
46
|
+
|
|
47
|
+
>>> # negative distance expands outward
|
|
48
|
+
>>> shrink_shape(shape, -2) # doctest: +SKIP
|
|
49
|
+
|
|
50
|
+
.. render-example::
|
|
51
|
+
:name: shrink_shape_negative
|
|
52
|
+
:example: shrink_shape(shape, -2)
|
|
53
|
+
:ghost: shape
|
|
54
|
+
|
|
55
|
+
>>> # partial shrink
|
|
56
|
+
>>> a = square(6)
|
|
57
|
+
>>> b = square(4).translate(10)
|
|
58
|
+
>>> shrink_shape( # doctest: +SKIP
|
|
59
|
+
... a + b, 1, part_filter=np.array([True, False])
|
|
60
|
+
... )
|
|
61
|
+
|
|
62
|
+
.. render-example::
|
|
63
|
+
:name: shrink_shape_partial
|
|
64
|
+
:example: shrink_shape(a + b, 1, part_filter=np.array([True, False]))
|
|
65
|
+
:ghost: a + b
|
|
66
|
+
"""
|
|
67
|
+
from scadpy import grow_shape
|
|
68
|
+
|
|
69
|
+
return grow_shape(shape=shape, distance=-distance, part_filter=part_filter)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from typeguard import typechecked
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from scadpy import Shape, TopologyFilter
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@typechecked
|
|
13
|
+
def translate_shape(
|
|
14
|
+
shape: Shape,
|
|
15
|
+
translation: float | Iterable[float],
|
|
16
|
+
vertex_filter: TopologyFilter[Shape] | None = None,
|
|
17
|
+
) -> Shape:
|
|
18
|
+
"""Translate a shape by a given vector.
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
shape : Shape
|
|
23
|
+
The shape to translate.
|
|
24
|
+
translation : float | Iterable[float]
|
|
25
|
+
The translation vector. If a single float is provided, it is broadcast
|
|
26
|
+
to all coordinate dimensions.
|
|
27
|
+
vertex_filter : TopologyFilter[Shape] | None, default=None
|
|
28
|
+
Boolean array or callable selecting which vertices are translated. If ``None``, all
|
|
29
|
+
vertices are translated.
|
|
30
|
+
|
|
31
|
+
Returns
|
|
32
|
+
-------
|
|
33
|
+
Shape
|
|
34
|
+
A new shape with the selected vertices shifted by the translation vector.
|
|
35
|
+
|
|
36
|
+
Examples
|
|
37
|
+
--------
|
|
38
|
+
>>> from scadpy import square, translate_shape
|
|
39
|
+
|
|
40
|
+
>>> translate_shape( # doctest: +SKIP
|
|
41
|
+
... shape=square(4), translation=[3, 2]
|
|
42
|
+
... )
|
|
43
|
+
|
|
44
|
+
.. render-example::
|
|
45
|
+
:name: translate_shape
|
|
46
|
+
:example: translate_shape(shape=square(4), translation=[3, 2])
|
|
47
|
+
:ghost: square(4)
|
|
48
|
+
"""
|
|
49
|
+
from scadpy import resolve_topology_filter, translate_vertex_coordinates
|
|
50
|
+
|
|
51
|
+
resolved_vertex_filter = resolve_topology_filter(shape, len(shape.vertex_coordinates), vertex_filter)
|
|
52
|
+
return shape.recoordinate(
|
|
53
|
+
translate_vertex_coordinates(shape.vertex_coordinates, translation, resolved_vertex_filter)
|
|
54
|
+
)
|