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,40 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from numpy.typing import NDArray
|
|
7
|
+
from typeguard import typechecked
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from scadpy.d2.shape import Shape
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@typechecked
|
|
14
|
+
def get_shape_edge_normals(
|
|
15
|
+
shape: Shape,
|
|
16
|
+
) -> NDArray[np.float64]:
|
|
17
|
+
"""
|
|
18
|
+
For each edge in the shape, return its outward unit normal.
|
|
19
|
+
|
|
20
|
+
See :func:`get_assembly_edge_normals` for full documentation.
|
|
21
|
+
|
|
22
|
+
Examples
|
|
23
|
+
--------
|
|
24
|
+
>>> from scadpy import get_shape_edge_normals, square
|
|
25
|
+
|
|
26
|
+
>>> # square(2) centered at origin: 4 edges,
|
|
27
|
+
>>> # each normal points outward
|
|
28
|
+
>>> square_shape = square(2)
|
|
29
|
+
>>> get_shape_edge_normals(square_shape).round(4)
|
|
30
|
+
array([[ 0., -1.],
|
|
31
|
+
[ 1., -0.],
|
|
32
|
+
[ 0., 1.],
|
|
33
|
+
[-1., -0.]])
|
|
34
|
+
"""
|
|
35
|
+
from scadpy.core.assembly import get_assembly_edge_normals
|
|
36
|
+
|
|
37
|
+
return get_assembly_edge_normals(
|
|
38
|
+
edge_to_vertex=shape.edge_to_vertex,
|
|
39
|
+
vertex_coordinates=shape.vertex_coordinates,
|
|
40
|
+
)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from numpy.typing import NDArray
|
|
7
|
+
from typeguard import typechecked
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from scadpy.d2.shape import Shape
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@typechecked
|
|
14
|
+
def get_shape_edge_to_vertex(
|
|
15
|
+
shape: Shape,
|
|
16
|
+
) -> NDArray[np.int64]:
|
|
17
|
+
"""
|
|
18
|
+
For each edge in the shape, return the indices of its start and end vertices.
|
|
19
|
+
|
|
20
|
+
An edge connects two consecutive vertices within a ring. Edges are directed
|
|
21
|
+
implicitly by the ring winding order (CCW for exterior rings, CW for interior
|
|
22
|
+
rings in Shapely convention).
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
shape : Shape
|
|
27
|
+
The shape to extract edge-to-vertex indices from.
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
NDArray[np.int64]
|
|
32
|
+
2D array of shape ``(n_edges, 2)``. Each row is ``[start_vertex, end_vertex]``.
|
|
33
|
+
The number of edges equals the number of vertices (one edge per vertex,
|
|
34
|
+
since each ring is closed).
|
|
35
|
+
|
|
36
|
+
Examples
|
|
37
|
+
--------
|
|
38
|
+
>>> from scadpy import get_shape_edge_to_vertex, polygon, square
|
|
39
|
+
|
|
40
|
+
>>> # triangle: 3 vertices, 3 edges
|
|
41
|
+
>>> triangle = polygon([(0, 0), (1, 0), (0.5, 1)])
|
|
42
|
+
>>> get_shape_edge_to_vertex(triangle)
|
|
43
|
+
array([[0, 1],
|
|
44
|
+
[1, 2],
|
|
45
|
+
[2, 0]])
|
|
46
|
+
|
|
47
|
+
>>> # square: 4 vertices, 4 edges
|
|
48
|
+
>>> square_shape = square(1)
|
|
49
|
+
>>> get_shape_edge_to_vertex(square_shape).shape
|
|
50
|
+
(4, 2)
|
|
51
|
+
"""
|
|
52
|
+
rings = [
|
|
53
|
+
ring
|
|
54
|
+
for g in map(lambda p: p.geometry, shape._parts) # pyright: ignore[reportPrivateUsage]
|
|
55
|
+
for ring in (g.exterior, *g.interiors)
|
|
56
|
+
]
|
|
57
|
+
if not rings:
|
|
58
|
+
return np.empty((0, 2), dtype=np.int64)
|
|
59
|
+
|
|
60
|
+
# Build edge_to_vertex: for each ring, consecutive vertex pairs (wrapping around)
|
|
61
|
+
edge_rows: list[NDArray[np.int64]] = []
|
|
62
|
+
offset = 0
|
|
63
|
+
for ring in rings:
|
|
64
|
+
n = len(ring.coords) - 1 # exclude closing duplicate
|
|
65
|
+
local_indices = np.arange(n, dtype=np.int64)
|
|
66
|
+
starts = offset + local_indices
|
|
67
|
+
ends = offset + (local_indices + 1) % n
|
|
68
|
+
edge_rows.append(np.stack([starts, ends], axis=1))
|
|
69
|
+
offset += n
|
|
70
|
+
|
|
71
|
+
return np.concatenate(edge_rows, axis=0)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from numpy.typing import NDArray
|
|
7
|
+
from typeguard import typechecked
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from scadpy.d2.shape import Shape
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@typechecked
|
|
14
|
+
def get_shape_ring_to_part(
|
|
15
|
+
shape: Shape,
|
|
16
|
+
) -> NDArray[np.int64]:
|
|
17
|
+
"""
|
|
18
|
+
For each ring in the shape, return its part index
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
shape : Shape
|
|
23
|
+
The shape to extract ring part indices from.
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
NDArray[np.float64]
|
|
28
|
+
1D array of shape (n_rings,), one element per ring.
|
|
29
|
+
|
|
30
|
+
Examples
|
|
31
|
+
--------
|
|
32
|
+
>>> from scadpy import get_shape_ring_to_part, square
|
|
33
|
+
|
|
34
|
+
>>> # square with a hole (2 rings in part 0)
|
|
35
|
+
>>> # unioned with a separate square (1 ring in part 1)
|
|
36
|
+
>>> shape = (square(2) - square(1)) | square(1).translate([5, 0])
|
|
37
|
+
>>> result = get_shape_ring_to_part(shape)
|
|
38
|
+
>>> result # doctest: +NORMALIZE_WHITESPACE
|
|
39
|
+
array([0, 0, 1])
|
|
40
|
+
"""
|
|
41
|
+
part_indices = [
|
|
42
|
+
i
|
|
43
|
+
for i, p in enumerate(shape._parts) # pyright: ignore[reportPrivateUsage]
|
|
44
|
+
for _ in range(1 + len(p.geometry.interiors))
|
|
45
|
+
]
|
|
46
|
+
return np.array(part_indices, dtype=np.int64)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from numpy.typing import NDArray
|
|
7
|
+
from typeguard import typechecked
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from scadpy.d2.shape import Shape
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@typechecked
|
|
14
|
+
def get_shape_ring_types(
|
|
15
|
+
shape: Shape,
|
|
16
|
+
) -> NDArray[np.object_]:
|
|
17
|
+
"""
|
|
18
|
+
For each ring in the shape, return its type ('exterior' or 'interior').
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
shape : Shape
|
|
23
|
+
The shape to extract ring types from.
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
NDArray[np.object_]
|
|
28
|
+
1D array of shape (n_rings,), one element per ring.
|
|
29
|
+
|
|
30
|
+
Examples
|
|
31
|
+
--------
|
|
32
|
+
>>> from scadpy import get_shape_ring_types, square
|
|
33
|
+
|
|
34
|
+
>>> # square with a hole (exterior + interior)
|
|
35
|
+
>>> # unioned with a separate square (exterior only)
|
|
36
|
+
>>> shape = (square(2) - square(1)) | square(1).translate([5, 0])
|
|
37
|
+
>>> get_shape_ring_types(shape) # doctest: +NORMALIZE_WHITESPACE
|
|
38
|
+
array(['exterior', 'interior', 'exterior'], dtype=object)
|
|
39
|
+
"""
|
|
40
|
+
# extract and flatmap polygon ring types
|
|
41
|
+
ring_types = [
|
|
42
|
+
ring_type
|
|
43
|
+
for g in [p.geometry for p in shape._parts] # pyright: ignore[reportPrivateUsage]
|
|
44
|
+
for ring_type in ["exterior"] + ["interior"] * len(g.interiors)
|
|
45
|
+
]
|
|
46
|
+
return np.array(ring_types, dtype=np.object_)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
__all__ = [
|
|
2
|
+
"get_shape_part_vertex_coordinates",
|
|
3
|
+
"get_shape_vertex_coordinates",
|
|
4
|
+
"get_shape_vertex_to_part",
|
|
5
|
+
"get_shape_vertex_to_ring",
|
|
6
|
+
]
|
|
7
|
+
|
|
8
|
+
from .get_shape_part_vertex_coordinates import get_shape_part_vertex_coordinates
|
|
9
|
+
from .get_shape_vertex_coordinates import get_shape_vertex_coordinates
|
|
10
|
+
from .get_shape_vertex_to_part import get_shape_vertex_to_part
|
|
11
|
+
from .get_shape_vertex_to_ring import get_shape_vertex_to_ring
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from numpy.typing import NDArray
|
|
7
|
+
from shapely.coords import CoordinateSequence
|
|
8
|
+
from shapely.geometry import Polygon
|
|
9
|
+
from typeguard import typechecked
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from scadpy.core.part import Part
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@typechecked
|
|
16
|
+
def get_shape_part_vertex_coordinates(part: Part[Polygon]) -> NDArray[np.float64]:
|
|
17
|
+
"""
|
|
18
|
+
For each vertex in the part, return its coordinates
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
part : Part[Polygon]
|
|
23
|
+
The shape part to extract vertex coordinates from.
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
NDArray[np.float64]
|
|
28
|
+
2D array of shape (n_vertices, 2), one row per vertex.
|
|
29
|
+
|
|
30
|
+
Examples
|
|
31
|
+
--------
|
|
32
|
+
>>> from shapely.geometry import Polygon
|
|
33
|
+
>>> from scadpy import Part, get_shape_part_vertex_coordinates
|
|
34
|
+
...
|
|
35
|
+
>>> polygon = Polygon(
|
|
36
|
+
... shell=[(0, 0), (4, 0), (4, 4), (0, 4), (0, 0)],
|
|
37
|
+
... holes=[[(1, 1), (3, 1), (3, 3), (1, 3), (1, 1)]]
|
|
38
|
+
... )
|
|
39
|
+
>>> get_shape_part_vertex_coordinates(
|
|
40
|
+
... Part.from_geometry(polygon)
|
|
41
|
+
... ) # doctest: +NORMALIZE_WHITESPACE
|
|
42
|
+
array([[0., 0.],
|
|
43
|
+
[4., 0.],
|
|
44
|
+
[4., 4.],
|
|
45
|
+
...
|
|
46
|
+
[3., 1.],
|
|
47
|
+
[3., 3.],
|
|
48
|
+
[1., 3.]])
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def remove_closing_point(coordinates: CoordinateSequence) -> NDArray[np.float64]:
|
|
52
|
+
array = np.array(coordinates)
|
|
53
|
+
if len(array) > 1 and np.allclose(array[0], array[-1]): # pyright: ignore[reportAny]
|
|
54
|
+
return array[:-1]
|
|
55
|
+
return array
|
|
56
|
+
|
|
57
|
+
geometry = part.geometry
|
|
58
|
+
exterior = remove_closing_point(geometry.exterior.coords)
|
|
59
|
+
interiors = [remove_closing_point(interior.coords) for interior in geometry.interiors]
|
|
60
|
+
if not interiors:
|
|
61
|
+
return exterior
|
|
62
|
+
return np.vstack([exterior] + interiors)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from numpy.typing import NDArray
|
|
7
|
+
from typeguard import typechecked
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from scadpy import Shape
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@typechecked
|
|
14
|
+
def get_shape_vertex_coordinates(shape: Shape) -> NDArray[np.float64]:
|
|
15
|
+
"""
|
|
16
|
+
For each vertex in the shape, return its coordinates.
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
shape : Shape
|
|
21
|
+
The shape to extract vertex coordinates from.
|
|
22
|
+
|
|
23
|
+
Returns
|
|
24
|
+
-------
|
|
25
|
+
NDArray[np.float64]
|
|
26
|
+
2D array of shape (n_vertices, 2), one row per vertex.
|
|
27
|
+
|
|
28
|
+
Examples
|
|
29
|
+
--------
|
|
30
|
+
>>> from shapely.geometry import Polygon
|
|
31
|
+
>>> from scadpy import Shape, get_shape_vertex_coordinates
|
|
32
|
+
|
|
33
|
+
>>> polygon = Polygon([(0, 0), (2, 0), (2, 2), (0, 2)])
|
|
34
|
+
>>> get_shape_vertex_coordinates(
|
|
35
|
+
... Shape.from_geometry(polygon)
|
|
36
|
+
... ) # doctest: +NORMALIZE_WHITESPACE
|
|
37
|
+
array([[0., 0.],
|
|
38
|
+
[2., 0.],
|
|
39
|
+
[2., 2.],
|
|
40
|
+
[0., 2.]])
|
|
41
|
+
"""
|
|
42
|
+
from scadpy import get_assembly_vertex_coordinates, get_shape_part_vertex_coordinates
|
|
43
|
+
|
|
44
|
+
return get_assembly_vertex_coordinates(shape._parts, get_shape_part_vertex_coordinates, 2)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from numpy.typing import NDArray
|
|
7
|
+
from typeguard import typechecked
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from scadpy import Shape
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@typechecked
|
|
14
|
+
def get_shape_vertex_to_part(shape: Shape) -> NDArray[np.int64]:
|
|
15
|
+
"""
|
|
16
|
+
For each vertex in the shape, return its part index.
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
shape : Shape
|
|
21
|
+
The shape to extract part indices from.
|
|
22
|
+
|
|
23
|
+
Returns
|
|
24
|
+
-------
|
|
25
|
+
NDArray[np.int64]
|
|
26
|
+
1D array of shape (n_vertices,), one element per vertex.
|
|
27
|
+
|
|
28
|
+
Examples
|
|
29
|
+
--------
|
|
30
|
+
>>> from shapely.geometry import Polygon
|
|
31
|
+
>>> from scadpy import Shape, get_shape_vertex_to_part
|
|
32
|
+
|
|
33
|
+
>>> p1 = Polygon([(0, 0), (2, 0), (2, 2), (0, 2)])
|
|
34
|
+
>>> p2 = Polygon([(10, 10), (12, 10), (12, 12), (10, 12)])
|
|
35
|
+
>>> get_shape_vertex_to_part(
|
|
36
|
+
... Shape.from_geometries([p1, p2])
|
|
37
|
+
... ) # doctest: +NORMALIZE_WHITESPACE
|
|
38
|
+
array([0, 0, 0, 0, 1, 1, 1, 1])
|
|
39
|
+
"""
|
|
40
|
+
from scadpy import get_assembly_vertex_to_part, get_shape_part_vertex_coordinates
|
|
41
|
+
|
|
42
|
+
return get_assembly_vertex_to_part(shape._parts, get_shape_part_vertex_coordinates)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from numpy.typing import NDArray
|
|
7
|
+
from typeguard import typechecked
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from scadpy.d2.shape import Shape
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@typechecked
|
|
14
|
+
def get_shape_vertex_to_ring(
|
|
15
|
+
shape: Shape,
|
|
16
|
+
) -> NDArray[np.int64]:
|
|
17
|
+
"""
|
|
18
|
+
For each vertex in the shape, return the index of the ring (exterior or interior) it belongs to.
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
shape : Shape
|
|
23
|
+
The shape to extract vertex ring indices from.
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
NDArray[np.float64]
|
|
28
|
+
1D array of shape (n_vertices,), one element per vertex.
|
|
29
|
+
|
|
30
|
+
Examples
|
|
31
|
+
--------
|
|
32
|
+
>>> from scadpy import get_shape_vertex_to_ring, polygon, square
|
|
33
|
+
|
|
34
|
+
>>> # two separate triangles: 3 vertices in ring 0, 3 in ring 1
|
|
35
|
+
>>> shape = (
|
|
36
|
+
... polygon([(0, 0), (1, 0), (0.5, 1)])
|
|
37
|
+
... | polygon([(5, 0), (6, 0), (5.5, 1)])
|
|
38
|
+
... )
|
|
39
|
+
>>> result = get_shape_vertex_to_ring(shape)
|
|
40
|
+
>>> result # doctest: +NORMALIZE_WHITESPACE
|
|
41
|
+
array([0, 0, 0, 1, 1, 1])
|
|
42
|
+
|
|
43
|
+
>>> # square with a hole: 4 exterior vertices in ring 0,
|
|
44
|
+
>>> # 4 interior vertices in ring 1
|
|
45
|
+
>>> shape = square(4) - square(2)
|
|
46
|
+
>>> result = get_shape_vertex_to_ring(shape)
|
|
47
|
+
>>> result # doctest: +NORMALIZE_WHITESPACE
|
|
48
|
+
array([0, 0, 0, 0, 1, 1, 1, 1])
|
|
49
|
+
"""
|
|
50
|
+
# extract and flatmap polygon rings
|
|
51
|
+
rings = [
|
|
52
|
+
ring
|
|
53
|
+
for g in map(lambda p: p.geometry, shape._parts) # pyright: ignore[reportPrivateUsage]
|
|
54
|
+
for ring in (g.exterior, *g.interiors)
|
|
55
|
+
]
|
|
56
|
+
# no ring found
|
|
57
|
+
if not rings:
|
|
58
|
+
return np.array([], dtype=np.int64)
|
|
59
|
+
|
|
60
|
+
ring_indices = np.concatenate(
|
|
61
|
+
[np.full(len(ring.coords) - 1, i, dtype=np.int64) for i, ring in enumerate(rings)]
|
|
62
|
+
)
|
|
63
|
+
return np.array(ring_indices, dtype=np.int64)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
__all__ = [
|
|
2
|
+
"chamfer_shape",
|
|
3
|
+
"color_shape",
|
|
4
|
+
"convexify_shape",
|
|
5
|
+
"fill_shape",
|
|
6
|
+
"fillet_shape",
|
|
7
|
+
"grow_shape",
|
|
8
|
+
"linear_cut_shape",
|
|
9
|
+
"linear_extrude_shape",
|
|
10
|
+
"linear_slice_shape",
|
|
11
|
+
"mirror_shape",
|
|
12
|
+
"pull_shape",
|
|
13
|
+
"push_shape",
|
|
14
|
+
"radial_extrude_shape",
|
|
15
|
+
"radial_slice_shape",
|
|
16
|
+
"recoordinate_shape",
|
|
17
|
+
"resize_shape",
|
|
18
|
+
"rotate_shape",
|
|
19
|
+
"scale_shape",
|
|
20
|
+
"shrink_shape",
|
|
21
|
+
"translate_shape",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
from .chamfer_shape import chamfer_shape
|
|
25
|
+
from .color_shape import color_shape
|
|
26
|
+
from .convexify_shape import convexify_shape
|
|
27
|
+
from .fill_shape import fill_shape
|
|
28
|
+
from .fillet_shape import fillet_shape
|
|
29
|
+
from .grow_shape import grow_shape
|
|
30
|
+
from .linear_cut_shape import linear_cut_shape
|
|
31
|
+
from .linear_extrude_shape import linear_extrude_shape
|
|
32
|
+
from .linear_slice_shape import linear_slice_shape
|
|
33
|
+
from .mirror_shape import mirror_shape
|
|
34
|
+
from .pull_shape import pull_shape
|
|
35
|
+
from .push_shape import push_shape
|
|
36
|
+
from .radial_extrude_shape import radial_extrude_shape
|
|
37
|
+
from .radial_slice_shape import radial_slice_shape
|
|
38
|
+
from .recoordinate_shape import recoordinate_shape
|
|
39
|
+
from .resize_shape import resize_shape
|
|
40
|
+
from .rotate_shape import rotate_shape
|
|
41
|
+
from .scale_shape import scale_shape
|
|
42
|
+
from .shrink_shape import shrink_shape
|
|
43
|
+
from .translate_shape import translate_shape
|