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.
Files changed (236) hide show
  1. scadpy/__init__.py +5 -0
  2. scadpy/color/__init__.py +3 -0
  3. scadpy/color/constants/BEIGE.py +3 -0
  4. scadpy/color/constants/BLACK.py +3 -0
  5. scadpy/color/constants/BLUE.py +3 -0
  6. scadpy/color/constants/BROWN.py +3 -0
  7. scadpy/color/constants/DARK_GRAY.py +3 -0
  8. scadpy/color/constants/DEFAULT_COLOR.py +3 -0
  9. scadpy/color/constants/DEFAULT_OPACITY.py +1 -0
  10. scadpy/color/constants/GRAY.py +3 -0
  11. scadpy/color/constants/GREEN.py +3 -0
  12. scadpy/color/constants/ORANGE.py +3 -0
  13. scadpy/color/constants/RED.py +3 -0
  14. scadpy/color/constants/WHITE.py +3 -0
  15. scadpy/color/constants/YELLOW.py +3 -0
  16. scadpy/color/constants/__init__.py +29 -0
  17. scadpy/color/type/__init__.py +3 -0
  18. scadpy/color/type/color.py +3 -0
  19. scadpy/color/utils/__init__.py +3 -0
  20. scadpy/color/utils/get_random_color.py +36 -0
  21. scadpy/core/__init__.py +3 -0
  22. scadpy/core/assembly/__init__.py +5 -0
  23. scadpy/core/assembly/combinations/__init__.py +13 -0
  24. scadpy/core/assembly/combinations/concat_assemblies.py +50 -0
  25. scadpy/core/assembly/combinations/exclude_assemblies.py +135 -0
  26. scadpy/core/assembly/combinations/intersect_assemblies.py +128 -0
  27. scadpy/core/assembly/combinations/subtract_assemblies.py +151 -0
  28. scadpy/core/assembly/combinations/unify_assemblies.py +59 -0
  29. scadpy/core/assembly/topologies/__init__.py +41 -0
  30. scadpy/core/assembly/topologies/directed_edge/__init__.py +9 -0
  31. scadpy/core/assembly/topologies/directed_edge/get_assembly_directed_edge_directions.py +70 -0
  32. scadpy/core/assembly/topologies/directed_edge/get_assembly_directed_edge_to_edge.py +49 -0
  33. scadpy/core/assembly/topologies/directed_edge/get_assembly_directed_edge_to_vertex.py +54 -0
  34. scadpy/core/assembly/topologies/edge/__init__.py +9 -0
  35. scadpy/core/assembly/topologies/edge/get_assembly_edge_lengths.py +46 -0
  36. scadpy/core/assembly/topologies/edge/get_assembly_edge_midpoints.py +51 -0
  37. scadpy/core/assembly/topologies/edge/get_assembly_edge_normals.py +67 -0
  38. scadpy/core/assembly/topologies/face_corner/__init__.py +13 -0
  39. scadpy/core/assembly/topologies/face_corner/get_assembly_face_corner_angles.py +72 -0
  40. scadpy/core/assembly/topologies/face_corner/get_assembly_face_corner_normals.py +103 -0
  41. scadpy/core/assembly/topologies/face_corner/get_assembly_face_corner_to_incoming_directed_edge.py +65 -0
  42. scadpy/core/assembly/topologies/face_corner/get_assembly_face_corner_to_outgoing_directed_edge.py +65 -0
  43. scadpy/core/assembly/topologies/face_corner/get_assembly_face_directed_edge_to_corner.py +79 -0
  44. scadpy/core/assembly/topologies/part/__init__.py +5 -0
  45. scadpy/core/assembly/topologies/part/get_assembly_part_colors.py +55 -0
  46. scadpy/core/assembly/topologies/vertex/__init__.py +7 -0
  47. scadpy/core/assembly/topologies/vertex/get_assembly_vertex_coordinates.py +70 -0
  48. scadpy/core/assembly/topologies/vertex/get_assembly_vertex_to_part.py +62 -0
  49. scadpy/core/assembly/transformations/__init__.py +19 -0
  50. scadpy/core/assembly/transformations/color_assembly.py +24 -0
  51. scadpy/core/assembly/transformations/mirror_vertex_coordinates.py +68 -0
  52. scadpy/core/assembly/transformations/pull_vertex_coordinates.py +64 -0
  53. scadpy/core/assembly/transformations/push_vertex_coordinates.py +64 -0
  54. scadpy/core/assembly/transformations/resize_vertex_coordinates.py +121 -0
  55. scadpy/core/assembly/transformations/rotate_vertex_coordinates.py +73 -0
  56. scadpy/core/assembly/transformations/scale_vertex_coordinates.py +76 -0
  57. scadpy/core/assembly/transformations/translate_vertex_coordinates.py +70 -0
  58. scadpy/core/assembly/types/__init__.py +7 -0
  59. scadpy/core/assembly/types/assembly.py +14 -0
  60. scadpy/core/assembly/types/topology_filter.py +6 -0
  61. scadpy/core/assembly/utils/__init__.py +9 -0
  62. scadpy/core/assembly/utils/lookup_pairs.py +56 -0
  63. scadpy/core/assembly/utils/resolve_topology_filter.py +84 -0
  64. scadpy/core/assembly/utils/transform_filtered_parts.py +55 -0
  65. scadpy/core/component/__init__.py +3 -0
  66. scadpy/core/component/exporters/__init__.py +7 -0
  67. scadpy/core/component/exporters/map_component_to_html_file.py +47 -0
  68. scadpy/core/component/exporters/map_component_to_screen.py +63 -0
  69. scadpy/core/component/features/__init__.py +5 -0
  70. scadpy/core/component/features/get_component_bounds.py +38 -0
  71. scadpy/core/component/utils/__init__.py +9 -0
  72. scadpy/core/component/utils/blend_component_colors.py +77 -0
  73. scadpy/core/component/utils/get_intersecting_component_index_groups.py +108 -0
  74. scadpy/core/part/__init__.py +3 -0
  75. scadpy/core/part/combinations/__init__.py +11 -0
  76. scadpy/core/part/combinations/concat_parts.py +48 -0
  77. scadpy/core/part/combinations/intersect_parts.py +147 -0
  78. scadpy/core/part/combinations/subtract_parts.py +94 -0
  79. scadpy/core/part/combinations/unify_parts.py +143 -0
  80. scadpy/core/part/types/__init__.py +5 -0
  81. scadpy/core/part/types/part.py +34 -0
  82. scadpy/core/part/utils/__init__.py +5 -0
  83. scadpy/core/part/utils/blend_part_colors.py +32 -0
  84. scadpy/d2/__init__.py +2 -0
  85. scadpy/d2/shape/__init__.py +9 -0
  86. scadpy/d2/shape/combinations/__init__.py +21 -0
  87. scadpy/d2/shape/combinations/are_shape_parts_intersecting.py +49 -0
  88. scadpy/d2/shape/combinations/concat_shape.py +48 -0
  89. scadpy/d2/shape/combinations/exclude_shape.py +71 -0
  90. scadpy/d2/shape/combinations/intersect_shape.py +64 -0
  91. scadpy/d2/shape/combinations/intersect_shape_parts.py +71 -0
  92. scadpy/d2/shape/combinations/subtract_shape.py +72 -0
  93. scadpy/d2/shape/combinations/subtract_shape_parts.py +66 -0
  94. scadpy/d2/shape/combinations/unify_shape.py +51 -0
  95. scadpy/d2/shape/combinations/unify_shape_parts.py +74 -0
  96. scadpy/d2/shape/exporters/__init__.py +17 -0
  97. scadpy/d2/shape/exporters/map_shape_to_dxf.py +43 -0
  98. scadpy/d2/shape/exporters/map_shape_to_dxf_file.py +38 -0
  99. scadpy/d2/shape/exporters/map_shape_to_html.py +117 -0
  100. scadpy/d2/shape/exporters/map_shape_to_html_file.py +58 -0
  101. scadpy/d2/shape/exporters/map_shape_to_screen.py +51 -0
  102. scadpy/d2/shape/exporters/map_shape_to_svg.py +40 -0
  103. scadpy/d2/shape/exporters/map_shape_to_svg_file.py +38 -0
  104. scadpy/d2/shape/features/__init__.py +9 -0
  105. scadpy/d2/shape/features/get_shape_bounds.py +40 -0
  106. scadpy/d2/shape/features/get_shape_part_bounds.py +37 -0
  107. scadpy/d2/shape/features/is_shape_empty.py +38 -0
  108. scadpy/d2/shape/importers/__init__.py +13 -0
  109. scadpy/d2/shape/importers/map_dxf_to_shape.py +55 -0
  110. scadpy/d2/shape/importers/map_geometries_to_shape.py +45 -0
  111. scadpy/d2/shape/importers/map_geometry_to_shape.py +43 -0
  112. scadpy/d2/shape/importers/map_parts_to_shape.py +62 -0
  113. scadpy/d2/shape/importers/map_svg_to_shape.py +55 -0
  114. scadpy/d2/shape/primitives/__init__.py +6 -0
  115. scadpy/d2/shape/primitives/circle.py +68 -0
  116. scadpy/d2/shape/primitives/polygon.py +86 -0
  117. scadpy/d2/shape/primitives/rectangle.py +85 -0
  118. scadpy/d2/shape/primitives/square.py +57 -0
  119. scadpy/d2/shape/topologies/__init__.py +53 -0
  120. scadpy/d2/shape/topologies/corner/__init__.py +15 -0
  121. scadpy/d2/shape/topologies/corner/are_shape_corners_convex.py +75 -0
  122. scadpy/d2/shape/topologies/corner/get_shape_corner_angles.py +58 -0
  123. scadpy/d2/shape/topologies/corner/get_shape_corner_normals.py +82 -0
  124. scadpy/d2/shape/topologies/corner/get_shape_corner_to_incoming_directed_edge.py +39 -0
  125. scadpy/d2/shape/topologies/corner/get_shape_corner_to_outgoing_directed_edge.py +39 -0
  126. scadpy/d2/shape/topologies/corner/get_shape_corner_to_vertex.py +65 -0
  127. scadpy/d2/shape/topologies/directed_edge/__init__.py +11 -0
  128. scadpy/d2/shape/topologies/directed_edge/get_shape_directed_edge_directions.py +44 -0
  129. scadpy/d2/shape/topologies/directed_edge/get_shape_directed_edge_to_corner.py +41 -0
  130. scadpy/d2/shape/topologies/directed_edge/get_shape_directed_edge_to_edge.py +51 -0
  131. scadpy/d2/shape/topologies/directed_edge/get_shape_directed_edge_to_vertex.py +63 -0
  132. scadpy/d2/shape/topologies/edge/__init__.py +11 -0
  133. scadpy/d2/shape/topologies/edge/get_shape_edge_lengths.py +43 -0
  134. scadpy/d2/shape/topologies/edge/get_shape_edge_midpoints.py +46 -0
  135. scadpy/d2/shape/topologies/edge/get_shape_edge_normals.py +40 -0
  136. scadpy/d2/shape/topologies/edge/get_shape_edge_to_vertex.py +71 -0
  137. scadpy/d2/shape/topologies/ring/__init__.py +7 -0
  138. scadpy/d2/shape/topologies/ring/get_shape_ring_to_part.py +46 -0
  139. scadpy/d2/shape/topologies/ring/get_shape_ring_types.py +46 -0
  140. scadpy/d2/shape/topologies/vertex/__init__.py +11 -0
  141. scadpy/d2/shape/topologies/vertex/get_shape_part_vertex_coordinates.py +62 -0
  142. scadpy/d2/shape/topologies/vertex/get_shape_vertex_coordinates.py +44 -0
  143. scadpy/d2/shape/topologies/vertex/get_shape_vertex_to_part.py +42 -0
  144. scadpy/d2/shape/topologies/vertex/get_shape_vertex_to_ring.py +63 -0
  145. scadpy/d2/shape/transformations/__init__.py +43 -0
  146. scadpy/d2/shape/transformations/chamfer_shape.py +259 -0
  147. scadpy/d2/shape/transformations/color_shape.py +46 -0
  148. scadpy/d2/shape/transformations/convexify_shape.py +79 -0
  149. scadpy/d2/shape/transformations/fill_shape.py +68 -0
  150. scadpy/d2/shape/transformations/fillet_shape.py +289 -0
  151. scadpy/d2/shape/transformations/grow_shape.py +82 -0
  152. scadpy/d2/shape/transformations/linear_cut_shape.py +116 -0
  153. scadpy/d2/shape/transformations/linear_extrude_shape.py +60 -0
  154. scadpy/d2/shape/transformations/linear_slice_shape.py +144 -0
  155. scadpy/d2/shape/transformations/mirror_shape.py +53 -0
  156. scadpy/d2/shape/transformations/pull_shape.py +67 -0
  157. scadpy/d2/shape/transformations/push_shape.py +67 -0
  158. scadpy/d2/shape/transformations/radial_extrude_shape.py +285 -0
  159. scadpy/d2/shape/transformations/radial_slice_shape.py +132 -0
  160. scadpy/d2/shape/transformations/recoordinate_shape.py +82 -0
  161. scadpy/d2/shape/transformations/resize_shape.py +91 -0
  162. scadpy/d2/shape/transformations/rotate_shape.py +63 -0
  163. scadpy/d2/shape/transformations/scale_shape.py +58 -0
  164. scadpy/d2/shape/transformations/shrink_shape.py +69 -0
  165. scadpy/d2/shape/transformations/translate_shape.py +54 -0
  166. scadpy/d2/shape/types/__init__.py +3 -0
  167. scadpy/d2/shape/types/shape.py +792 -0
  168. scadpy/d2/shape/types/utils/__init__.py +5 -0
  169. scadpy/d2/shape/types/utils/shapely_base_geometry_to_shapely_polygons.py +25 -0
  170. scadpy/d2/shape/utils/__init__.py +5 -0
  171. scadpy/d2/shape/utils/shapely_base_geometry_to_shapely_polygons.py +55 -0
  172. scadpy/d2/utils/__init__.py +3 -0
  173. scadpy/d2/utils/resolve_vector_2d.py +50 -0
  174. scadpy/d3/__init__.py +2 -0
  175. scadpy/d3/solid/__init__.py +8 -0
  176. scadpy/d3/solid/combinations/__init__.py +21 -0
  177. scadpy/d3/solid/combinations/are_solid_parts_intersecting.py +51 -0
  178. scadpy/d3/solid/combinations/concat_solid.py +48 -0
  179. scadpy/d3/solid/combinations/exclude_solid.py +71 -0
  180. scadpy/d3/solid/combinations/intersect_solid.py +64 -0
  181. scadpy/d3/solid/combinations/intersect_solid_parts.py +73 -0
  182. scadpy/d3/solid/combinations/subtract_solid.py +72 -0
  183. scadpy/d3/solid/combinations/subtract_solid_parts.py +68 -0
  184. scadpy/d3/solid/combinations/unify_solid.py +51 -0
  185. scadpy/d3/solid/combinations/unify_solid_parts.py +73 -0
  186. scadpy/d3/solid/exporters/__init__.py +11 -0
  187. scadpy/d3/solid/exporters/map_solid_to_html.py +318 -0
  188. scadpy/d3/solid/exporters/map_solid_to_html_file.py +58 -0
  189. scadpy/d3/solid/exporters/map_solid_to_screen.py +51 -0
  190. scadpy/d3/solid/exporters/map_solid_to_stl_file.py +48 -0
  191. scadpy/d3/solid/features/__init__.py +11 -0
  192. scadpy/d3/solid/features/get_solid_bounds.py +37 -0
  193. scadpy/d3/solid/features/get_solid_part_bounds.py +37 -0
  194. scadpy/d3/solid/features/get_solid_part_colors.py +39 -0
  195. scadpy/d3/solid/features/is_solid_empty.py +36 -0
  196. scadpy/d3/solid/importers/__init__.py +11 -0
  197. scadpy/d3/solid/importers/map_geometries_to_solid.py +42 -0
  198. scadpy/d3/solid/importers/map_geometry_to_solid.py +42 -0
  199. scadpy/d3/solid/importers/map_parts_to_solid.py +66 -0
  200. scadpy/d3/solid/importers/map_stl_to_solid.py +37 -0
  201. scadpy/d3/solid/primitives/__init__.py +7 -0
  202. scadpy/d3/solid/primitives/cone.py +70 -0
  203. scadpy/d3/solid/primitives/cuboid.py +75 -0
  204. scadpy/d3/solid/primitives/cylinder.py +73 -0
  205. scadpy/d3/solid/primitives/polyhedron.py +60 -0
  206. scadpy/d3/solid/primitives/sphere.py +58 -0
  207. scadpy/d3/solid/topologies/__init__.py +8 -0
  208. scadpy/d3/solid/topologies/triangle/__init__.py +5 -0
  209. scadpy/d3/solid/topologies/triangle/get_solid_triangle_to_vertex.py +49 -0
  210. scadpy/d3/solid/topologies/vertex/__init__.py +7 -0
  211. scadpy/d3/solid/topologies/vertex/get_solid_vertex_coordinates.py +39 -0
  212. scadpy/d3/solid/topologies/vertex/get_solid_vertex_to_part.py +37 -0
  213. scadpy/d3/solid/transformations/__init__.py +23 -0
  214. scadpy/d3/solid/transformations/color_solid.py +46 -0
  215. scadpy/d3/solid/transformations/convexify_solid.py +64 -0
  216. scadpy/d3/solid/transformations/mirror_solid.py +53 -0
  217. scadpy/d3/solid/transformations/pull_solid.py +67 -0
  218. scadpy/d3/solid/transformations/push_solid.py +67 -0
  219. scadpy/d3/solid/transformations/recoordinate_solid.py +68 -0
  220. scadpy/d3/solid/transformations/resize_solid.py +92 -0
  221. scadpy/d3/solid/transformations/rotate_solid.py +93 -0
  222. scadpy/d3/solid/transformations/scale_solid.py +58 -0
  223. scadpy/d3/solid/transformations/translate_solid.py +54 -0
  224. scadpy/d3/solid/types/__init__.py +3 -0
  225. scadpy/d3/solid/types/solid.py +448 -0
  226. scadpy/d3/utils/__init__.py +3 -0
  227. scadpy/d3/utils/resolve_vector_3d.py +50 -0
  228. scadpy/utils/__init__.py +6 -0
  229. scadpy/utils/resolve_vector.py +64 -0
  230. scadpy/utils/x.py +38 -0
  231. scadpy/utils/y.py +38 -0
  232. scadpy/utils/z.py +38 -0
  233. scadpy-0.1.0.dist-info/METADATA +282 -0
  234. scadpy-0.1.0.dist-info/RECORD +236 -0
  235. scadpy-0.1.0.dist-info/WHEEL +4 -0
  236. 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
+ )
@@ -0,0 +1,3 @@
1
+ __all__ = ["Shape"]
2
+
3
+ from .shape import Shape