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,38 @@
|
|
|
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
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@typechecked
|
|
12
|
+
def is_shape_empty(shape: Shape) -> bool:
|
|
13
|
+
"""
|
|
14
|
+
Return whether the shape has no vertices.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
shape : Shape
|
|
19
|
+
The shape to check.
|
|
20
|
+
|
|
21
|
+
Returns
|
|
22
|
+
-------
|
|
23
|
+
bool
|
|
24
|
+
True if the shape has no vertices, False otherwise.
|
|
25
|
+
|
|
26
|
+
Examples
|
|
27
|
+
--------
|
|
28
|
+
>>> from shapely.geometry import Polygon
|
|
29
|
+
>>> from scadpy import Shape, is_shape_empty
|
|
30
|
+
|
|
31
|
+
>>> is_shape_empty(Shape.from_parts([]))
|
|
32
|
+
True
|
|
33
|
+
|
|
34
|
+
>>> polygon = Polygon([(0, 0), (2, 0), (2, 2), (0, 2)])
|
|
35
|
+
>>> is_shape_empty(Shape.from_geometry(polygon))
|
|
36
|
+
False
|
|
37
|
+
"""
|
|
38
|
+
return len(shape.vertex_coordinates) == 0
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
__all__ = [
|
|
2
|
+
"map_dxf_to_shape",
|
|
3
|
+
"map_geometries_to_shape",
|
|
4
|
+
"map_geometry_to_shape",
|
|
5
|
+
"map_parts_to_shape",
|
|
6
|
+
"map_svg_to_shape",
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
from .map_dxf_to_shape import map_dxf_to_shape
|
|
10
|
+
from .map_geometries_to_shape import map_geometries_to_shape
|
|
11
|
+
from .map_geometry_to_shape import map_geometry_to_shape
|
|
12
|
+
from .map_parts_to_shape import map_parts_to_shape
|
|
13
|
+
from .map_svg_to_shape import map_svg_to_shape
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from io import BytesIO
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING, cast
|
|
6
|
+
from urllib.request import Request, urlopen
|
|
7
|
+
|
|
8
|
+
from trimesh import load
|
|
9
|
+
from trimesh.path import Path2D
|
|
10
|
+
from typeguard import typechecked
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from scadpy.d2.shape import Shape
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@typechecked
|
|
17
|
+
def map_dxf_to_shape(source: str | Path) -> Shape:
|
|
18
|
+
"""Load a 2D shape from a DXF file or URL.
|
|
19
|
+
|
|
20
|
+
Closed paths in the DXF are converted to filled polygons. Open paths
|
|
21
|
+
(lines, arcs, splines that do not form a closed region) are ignored.
|
|
22
|
+
``source`` can be a local file path or an ``http``/``https`` URL.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
source : str or Path
|
|
27
|
+
Path to a local ``.dxf`` file or an HTTP/HTTPS URL pointing to one.
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
Shape
|
|
32
|
+
A new shape whose parts correspond to the closed filled regions
|
|
33
|
+
found in the DXF.
|
|
34
|
+
|
|
35
|
+
Examples
|
|
36
|
+
--------
|
|
37
|
+
>>> from scadpy import map_dxf_to_shape
|
|
38
|
+
|
|
39
|
+
>>> map_dxf_to_shape("https://raw.githubusercontent.com/mikedh/trimesh/main/models/2D/wrench.dxf") # doctest: +SKIP
|
|
40
|
+
|
|
41
|
+
.. render-example::
|
|
42
|
+
:name: map_dxf_to_shape
|
|
43
|
+
:example: map_dxf_to_shape("https://raw.githubusercontent.com/mikedh/trimesh/main/models/2D/wrench.dxf")
|
|
44
|
+
"""
|
|
45
|
+
from scadpy import map_geometries_to_shape
|
|
46
|
+
|
|
47
|
+
if isinstance(source, str) and source.startswith(("http://", "https://")):
|
|
48
|
+
req = Request(source, headers={"User-Agent": "ScadPy"})
|
|
49
|
+
with urlopen(req) as response:
|
|
50
|
+
data = BytesIO(response.read())
|
|
51
|
+
path = cast(Path2D, load(data, file_type="dxf"))
|
|
52
|
+
else:
|
|
53
|
+
path = cast(Path2D, load(source))
|
|
54
|
+
|
|
55
|
+
return map_geometries_to_shape(list(path.polygons_full))
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Sequence
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from shapely.geometry import Polygon
|
|
7
|
+
from typeguard import typechecked
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from scadpy.d2.shape import Shape
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@typechecked
|
|
14
|
+
def map_geometries_to_shape(geometries: Sequence[Polygon]) -> Shape:
|
|
15
|
+
"""Map a sequence of polygons to a shape.
|
|
16
|
+
|
|
17
|
+
Each polygon is validated and oriented via :func:`map_parts_to_shape`.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
geometries : Sequence[Polygon]
|
|
22
|
+
The polygons to map.
|
|
23
|
+
|
|
24
|
+
Returns
|
|
25
|
+
-------
|
|
26
|
+
Shape
|
|
27
|
+
A new shape containing all valid, oriented polygons.
|
|
28
|
+
|
|
29
|
+
Examples
|
|
30
|
+
--------
|
|
31
|
+
>>> from shapely.geometry import Polygon
|
|
32
|
+
>>> from scadpy import map_geometries_to_shape
|
|
33
|
+
|
|
34
|
+
>>> map_geometries_to_shape( # doctest: +SKIP
|
|
35
|
+
... [Polygon([(0, 0), (4, 0), (4, 4), (0, 4)])]
|
|
36
|
+
... )
|
|
37
|
+
|
|
38
|
+
.. render-example::
|
|
39
|
+
:name: map_geometries_to_shape
|
|
40
|
+
:example: map_geometries_to_shape([Polygon([(0, 0), (4, 0), (4, 4), (0, 4)])])
|
|
41
|
+
"""
|
|
42
|
+
from scadpy.core.part import Part
|
|
43
|
+
from scadpy.d2.shape import Shape
|
|
44
|
+
|
|
45
|
+
return Shape.from_parts([Part[Polygon].from_geometry(g) for g in geometries])
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from shapely.geometry import Polygon
|
|
6
|
+
from typeguard import typechecked
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from scadpy.d2.shape import Shape
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@typechecked
|
|
13
|
+
def map_geometry_to_shape(geometry: Polygon) -> Shape:
|
|
14
|
+
"""Map a single polygon to a shape.
|
|
15
|
+
|
|
16
|
+
Shortcut for :func:`map_geometries_to_shape` with a single polygon.
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
geometry : Polygon
|
|
21
|
+
The polygon to map.
|
|
22
|
+
|
|
23
|
+
Returns
|
|
24
|
+
-------
|
|
25
|
+
Shape
|
|
26
|
+
A new shape containing the single valid, oriented polygon.
|
|
27
|
+
|
|
28
|
+
Examples
|
|
29
|
+
--------
|
|
30
|
+
>>> from shapely.geometry import Polygon
|
|
31
|
+
>>> from scadpy import map_geometry_to_shape
|
|
32
|
+
|
|
33
|
+
>>> map_geometry_to_shape( # doctest: +SKIP
|
|
34
|
+
... Polygon([(0, 0), (4, 0), (4, 4), (0, 4)])
|
|
35
|
+
... )
|
|
36
|
+
|
|
37
|
+
.. render-example::
|
|
38
|
+
:name: map_geometry_to_shape
|
|
39
|
+
:example: map_geometry_to_shape(Polygon([(0, 0), (4, 0), (4, 4), (0, 4)]))
|
|
40
|
+
"""
|
|
41
|
+
from scadpy.d2.shape.importers import map_geometries_to_shape
|
|
42
|
+
|
|
43
|
+
return map_geometries_to_shape([geometry])
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Sequence
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from shapely.geometry import Polygon
|
|
7
|
+
from shapely.validation import make_valid
|
|
8
|
+
from typeguard import typechecked
|
|
9
|
+
|
|
10
|
+
from scadpy.d2.shape.types.utils import shapely_base_geometry_to_shapely_polygons
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from scadpy import Part, Shape
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@typechecked
|
|
17
|
+
def map_parts_to_shape(
|
|
18
|
+
parts: Sequence[Part[Polygon]],
|
|
19
|
+
) -> Shape:
|
|
20
|
+
"""Map a sequence of parts to a shape, repairing and orienting each polygon.
|
|
21
|
+
|
|
22
|
+
Each polygon is validated using :func:`shapely.validation.make_valid`. If a
|
|
23
|
+
polygon is invalid, it is repaired and may be split into multiple valid polygons.
|
|
24
|
+
All resulting polygons are oriented counter-clockwise (exterior) and clockwise
|
|
25
|
+
(holes) using :func:`shapely.geometry.polygon.orient`.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
parts : Sequence[Part[Polygon]]
|
|
30
|
+
The parts to map. Each part holds a Shapely polygon and a color.
|
|
31
|
+
|
|
32
|
+
Returns
|
|
33
|
+
-------
|
|
34
|
+
Shape
|
|
35
|
+
A new shape containing all valid, oriented polygons from the input parts.
|
|
36
|
+
|
|
37
|
+
Examples
|
|
38
|
+
--------
|
|
39
|
+
>>> from shapely.geometry import Polygon
|
|
40
|
+
>>> from scadpy import map_parts_to_shape
|
|
41
|
+
>>> from scadpy.core.part import Part
|
|
42
|
+
|
|
43
|
+
>>> map_parts_to_shape( # doctest: +SKIP
|
|
44
|
+
... [Part.from_geometry(Polygon([(0, 0), (4, 0), (4, 4), (0, 4)]))]
|
|
45
|
+
... )
|
|
46
|
+
|
|
47
|
+
.. render-example::
|
|
48
|
+
:name: map_parts_to_shape
|
|
49
|
+
:example: map_parts_to_shape([Part.from_geometry(Polygon([(0, 0), (4, 0), (4, 4), (0, 4)]))])
|
|
50
|
+
"""
|
|
51
|
+
from scadpy.core.part import Part
|
|
52
|
+
from scadpy.d2.shape import Shape
|
|
53
|
+
|
|
54
|
+
validated: list[Part[Polygon]] = []
|
|
55
|
+
for part in parts:
|
|
56
|
+
geom = make_valid(part.geometry) if not part.geometry.is_valid else part.geometry
|
|
57
|
+
for polygon in shapely_base_geometry_to_shapely_polygons(geom):
|
|
58
|
+
validated.append(Part.from_geometry(polygon, part.color))
|
|
59
|
+
|
|
60
|
+
shape = Shape()
|
|
61
|
+
shape._parts = validated
|
|
62
|
+
return shape
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from io import BytesIO
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING, cast
|
|
6
|
+
from urllib.request import Request, urlopen
|
|
7
|
+
|
|
8
|
+
from trimesh import load
|
|
9
|
+
from trimesh.path import Path2D
|
|
10
|
+
from typeguard import typechecked
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from scadpy.d2.shape import Shape
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@typechecked
|
|
17
|
+
def map_svg_to_shape(source: str | Path) -> Shape:
|
|
18
|
+
"""Load a 2D shape from an SVG file or URL.
|
|
19
|
+
|
|
20
|
+
Closed paths in the SVG are converted to filled polygons. Open paths
|
|
21
|
+
and decorative elements (text, images, gradients) are ignored.
|
|
22
|
+
``source`` can be a local file path or an ``http``/``https`` URL.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
source : str or Path
|
|
27
|
+
Path to a local ``.svg`` file or an HTTP/HTTPS URL pointing to one.
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
Shape
|
|
32
|
+
A new shape whose parts correspond to the closed filled regions
|
|
33
|
+
found in the SVG.
|
|
34
|
+
|
|
35
|
+
Examples
|
|
36
|
+
--------
|
|
37
|
+
>>> from scadpy import map_svg_to_shape
|
|
38
|
+
|
|
39
|
+
>>> map_svg_to_shape("https://upload.wikimedia.org/wikipedia/commons/0/04/Pentagon.svg") # doctest: +SKIP
|
|
40
|
+
|
|
41
|
+
.. render-example::
|
|
42
|
+
:name: map_svg_to_shape
|
|
43
|
+
:example: map_svg_to_shape("https://upload.wikimedia.org/wikipedia/commons/0/04/Pentagon.svg")
|
|
44
|
+
"""
|
|
45
|
+
from scadpy import map_geometries_to_shape
|
|
46
|
+
|
|
47
|
+
if isinstance(source, str) and source.startswith(("http://", "https://")):
|
|
48
|
+
req = Request(source, headers={"User-Agent": "ScadPy"})
|
|
49
|
+
with urlopen(req) as response:
|
|
50
|
+
data = BytesIO(response.read())
|
|
51
|
+
path = cast(Path2D, load(data, file_type="svg"))
|
|
52
|
+
else:
|
|
53
|
+
path = cast(Path2D, load(source))
|
|
54
|
+
|
|
55
|
+
return map_geometries_to_shape(list(path.polygons_full))
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from typeguard import typechecked
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from scadpy.d2.shape import Shape
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@typechecked
|
|
13
|
+
def circle(radius: float, segment_count: int = 64) -> Shape:
|
|
14
|
+
"""
|
|
15
|
+
Create a circle approximated by a polygon.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
radius : float
|
|
20
|
+
The radius of the circle. Must be strictly positive.
|
|
21
|
+
segment_count : int, optional
|
|
22
|
+
The number of segments used to approximate the circle.
|
|
23
|
+
Higher values produce a smoother shape. Default is 64.
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
Shape
|
|
28
|
+
A :class:`~scadpy.d2.shape.types.Shape` object representing the approximated circle.
|
|
29
|
+
|
|
30
|
+
Notes
|
|
31
|
+
-----
|
|
32
|
+
- The circle is centered at the origin (0, 0).
|
|
33
|
+
- The more segments, the smoother the approximation.
|
|
34
|
+
|
|
35
|
+
Examples
|
|
36
|
+
--------
|
|
37
|
+
>>> from scadpy import circle
|
|
38
|
+
|
|
39
|
+
>>> # circle of radius 5 with default resolution (64 vertices)
|
|
40
|
+
>>> x = circle(5)
|
|
41
|
+
>>> len(x.vertex_coordinates)
|
|
42
|
+
64
|
|
43
|
+
|
|
44
|
+
>>> # circle of radius 3 with low resolution
|
|
45
|
+
>>> x = circle(3, segment_count=8)
|
|
46
|
+
>>> coords = x.vertex_coordinates[:4]
|
|
47
|
+
>>> coords.round(2) # doctest: +NORMALIZE_WHITESPACE
|
|
48
|
+
array([[ 3. , 0. ],
|
|
49
|
+
[ 2.12, 2.12],
|
|
50
|
+
[ 0. , 3. ],
|
|
51
|
+
[-2.12, 2.12]])
|
|
52
|
+
|
|
53
|
+
>>> # invalid circle (radius <= 0)
|
|
54
|
+
>>> circle(0)
|
|
55
|
+
Traceback (most recent call last):
|
|
56
|
+
...
|
|
57
|
+
ValueError: Circle radius must be strictly positive.
|
|
58
|
+
"""
|
|
59
|
+
from scadpy.d2.shape import polygon
|
|
60
|
+
|
|
61
|
+
if radius <= 0:
|
|
62
|
+
raise ValueError("Circle radius must be strictly positive.")
|
|
63
|
+
if segment_count < 3:
|
|
64
|
+
raise ValueError("Circle vertex segment_count must be at least 3.")
|
|
65
|
+
|
|
66
|
+
angles = np.linspace(0, 2 * np.pi, segment_count, endpoint=False)
|
|
67
|
+
points = np.column_stack((radius * np.cos(angles), radius * np.sin(angles)))
|
|
68
|
+
return polygon(points=points)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from shapely.geometry import Polygon
|
|
7
|
+
from typeguard import typechecked
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from scadpy.d2.shape import Shape
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@typechecked
|
|
14
|
+
def polygon(points: Iterable[Iterable[float]]) -> Shape:
|
|
15
|
+
"""
|
|
16
|
+
Create a 2D polygon shape from a sequence of points.
|
|
17
|
+
|
|
18
|
+
This function constructs a :class:`~scadpy.d2.shape.types.Shape` from the given 2D points.
|
|
19
|
+
The polygon is automatically closed by connecting the last point to the first.
|
|
20
|
+
If the polygon is self-intersecting, it may be split into multiple parts.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
points : Iterable[Iterable[float]]
|
|
25
|
+
A sequence of coordinate pairs ``[x, y]`` defining the vertices
|
|
26
|
+
of the polygon. At least three points are required.
|
|
27
|
+
|
|
28
|
+
Returns
|
|
29
|
+
-------
|
|
30
|
+
Shape
|
|
31
|
+
A :class:`~scadpy.d2.shape.types.Shape` object representing the polygon.
|
|
32
|
+
|
|
33
|
+
Notes
|
|
34
|
+
-----
|
|
35
|
+
- The polygon is automatically closed by connecting the last point to the first.
|
|
36
|
+
- The input points are converted into 2D coordinates; extra dimensions are ignored.
|
|
37
|
+
- If the polygon is self-intersecting, it may be split into multiple parts.
|
|
38
|
+
|
|
39
|
+
Examples
|
|
40
|
+
--------
|
|
41
|
+
>>> import numpy as np
|
|
42
|
+
>>> from scadpy import polygon
|
|
43
|
+
|
|
44
|
+
>>> # simple triangle
|
|
45
|
+
>>> p = polygon([[0, 0], [1, 0], [0, 1]])
|
|
46
|
+
>>> p.vertex_coordinates # doctest: +NORMALIZE_WHITESPACE
|
|
47
|
+
array([[0., 0.],
|
|
48
|
+
[1., 0.],
|
|
49
|
+
[0., 1.]])
|
|
50
|
+
|
|
51
|
+
>>> # square defined manually
|
|
52
|
+
>>> # equivalent to square(2)
|
|
53
|
+
>>> p = polygon([[-1, -1], [1, -1], [1, 1], [-1, 1]])
|
|
54
|
+
>>> p.vertex_coordinates # doctest: +NORMALIZE_WHITESPACE
|
|
55
|
+
array([[-1., -1.],
|
|
56
|
+
[ 1., -1.],
|
|
57
|
+
[ 1., 1.],
|
|
58
|
+
[-1., 1.]])
|
|
59
|
+
|
|
60
|
+
>>> # self-intersecting polygon generate multiple parts
|
|
61
|
+
>>> p = polygon([[0, 0], [2, 2], [0, 2], [2, 0]])
|
|
62
|
+
>>> vtop = p.vertex_to_part[:, np.newaxis]
|
|
63
|
+
>>> stacked = np.hstack([vtop, p.vertex_coordinates])
|
|
64
|
+
>>> stacked # doctest: +NORMALIZE_WHITESPACE
|
|
65
|
+
array([[0., 2., 0.],
|
|
66
|
+
[0., 1., 1.],
|
|
67
|
+
[0., 0., 0.],
|
|
68
|
+
[1., 2., 2.],
|
|
69
|
+
[1., 0., 2.],
|
|
70
|
+
[1., 1., 1.]])
|
|
71
|
+
|
|
72
|
+
>>> # invalid polygon (less than 3 points)
|
|
73
|
+
>>> polygon([[0, 0], [1, 1]])
|
|
74
|
+
Traceback (most recent call last):
|
|
75
|
+
...
|
|
76
|
+
ValueError: A polygon must have at least 3 points
|
|
77
|
+
"""
|
|
78
|
+
from scadpy.d2 import resolve_vector_2d
|
|
79
|
+
from scadpy.d2.shape import Shape
|
|
80
|
+
|
|
81
|
+
coords = [tuple(resolve_vector_2d(p, 0)) for p in points]
|
|
82
|
+
if len(coords) < 3:
|
|
83
|
+
raise ValueError("A polygon must have at least 3 points")
|
|
84
|
+
|
|
85
|
+
polygon = Polygon(coords)
|
|
86
|
+
return Shape.from_geometry(polygon)
|
|
@@ -0,0 +1,85 @@
|
|
|
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.d2.shape import Shape
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@typechecked
|
|
13
|
+
def rectangle(size: Iterable[float]) -> Shape:
|
|
14
|
+
"""
|
|
15
|
+
Create a rectangle centered at the origin.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
size : Iterable[float]
|
|
20
|
+
The dimensions of the rectangle as ``[width, height]``.
|
|
21
|
+
Both values must be strictly positive numbers.
|
|
22
|
+
|
|
23
|
+
Returns
|
|
24
|
+
-------
|
|
25
|
+
Shape
|
|
26
|
+
A :class:`~scadpy.d2.shape.types.Shape` object representing the rectangle.
|
|
27
|
+
|
|
28
|
+
Notes
|
|
29
|
+
-----
|
|
30
|
+
- The rectangle is always centered at the origin (0, 0).
|
|
31
|
+
- The edges of the rectangle are aligned with the X and Y axes.
|
|
32
|
+
|
|
33
|
+
Examples
|
|
34
|
+
--------
|
|
35
|
+
>>> from scadpy import rectangle
|
|
36
|
+
|
|
37
|
+
>>> # rectangle 4 units wide and 2 units tall
|
|
38
|
+
>>> x = rectangle([4, 2])
|
|
39
|
+
>>> x.vertex_coordinates # doctest: +NORMALIZE_WHITESPACE
|
|
40
|
+
array([[-2., -1.],
|
|
41
|
+
[ 2., -1.],
|
|
42
|
+
[ 2., 1.],
|
|
43
|
+
[-2., 1.]])
|
|
44
|
+
|
|
45
|
+
>>> # equivalent to square(10)
|
|
46
|
+
>>> x = rectangle([10, 10])
|
|
47
|
+
>>> x.vertex_coordinates # doctest: +NORMALIZE_WHITESPACE
|
|
48
|
+
array([[-5., -5.],
|
|
49
|
+
[ 5., -5.],
|
|
50
|
+
[ 5., 5.],
|
|
51
|
+
[-5., 5.]])
|
|
52
|
+
|
|
53
|
+
>>> # if one or no dimension is provided,
|
|
54
|
+
>>> # the missing value defaults to 1.0
|
|
55
|
+
>>> x = rectangle([5])
|
|
56
|
+
>>> x.vertex_coordinates # doctest: +NORMALIZE_WHITESPACE
|
|
57
|
+
array([[-2.5, -0.5],
|
|
58
|
+
[ 2.5, -0.5],
|
|
59
|
+
[ 2.5, 0.5],
|
|
60
|
+
[-2.5, 0.5]])
|
|
61
|
+
|
|
62
|
+
>>> # invalid rectangle
|
|
63
|
+
>>> rectangle([0, 5])
|
|
64
|
+
Traceback (most recent call last):
|
|
65
|
+
...
|
|
66
|
+
ValueError: Rectangle dimensions must be strictly positive.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
from scadpy.d2 import resolve_vector_2d
|
|
70
|
+
from scadpy.d2.shape import polygon
|
|
71
|
+
|
|
72
|
+
width, height = resolve_vector_2d(size, 1.0) # pyright: ignore[reportAny]
|
|
73
|
+
|
|
74
|
+
if width <= 0 or height <= 0:
|
|
75
|
+
raise ValueError("Rectangle dimensions must be strictly positive.")
|
|
76
|
+
|
|
77
|
+
half_width, half_height = width / 2.0, height / 2.0 # pyright: ignore[reportAny]
|
|
78
|
+
|
|
79
|
+
points = [
|
|
80
|
+
(-half_width, -half_height),
|
|
81
|
+
(half_width, -half_height),
|
|
82
|
+
(half_width, half_height),
|
|
83
|
+
(-half_width, half_height),
|
|
84
|
+
]
|
|
85
|
+
return polygon(points=points)
|
|
@@ -0,0 +1,57 @@
|
|
|
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.d2.shape import Shape
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@typechecked
|
|
12
|
+
def square(size: float) -> Shape:
|
|
13
|
+
"""
|
|
14
|
+
Creates a square centered at the origin.
|
|
15
|
+
|
|
16
|
+
This function is a convenience wrapper around
|
|
17
|
+
:func:`~scadpy.d2.shape.primitives.rectangle`, with equal width and height.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
size : float
|
|
22
|
+
The length of each side of the square.
|
|
23
|
+
|
|
24
|
+
Returns
|
|
25
|
+
-------
|
|
26
|
+
Shape
|
|
27
|
+
A :class:`~scadpy.d2.shape.types.Shape` object representing the square.
|
|
28
|
+
|
|
29
|
+
Notes
|
|
30
|
+
-----
|
|
31
|
+
- The square is centered at the origin `(0, 0)`.
|
|
32
|
+
- The square is equivalent to calling ``rectangle([size, size])``.
|
|
33
|
+
|
|
34
|
+
Examples
|
|
35
|
+
--------
|
|
36
|
+
>>> from scadpy import square
|
|
37
|
+
|
|
38
|
+
>>> # square of size 1x1
|
|
39
|
+
>>> x = square(1)
|
|
40
|
+
>>> x.vertex_coordinates # doctest: +NORMALIZE_WHITESPACE
|
|
41
|
+
array([[-0.5, -0.5],
|
|
42
|
+
[ 0.5, -0.5],
|
|
43
|
+
[ 0.5, 0.5],
|
|
44
|
+
[-0.5, 0.5]])
|
|
45
|
+
|
|
46
|
+
>>> # square of size 5x5
|
|
47
|
+
>>> x = square(5)
|
|
48
|
+
>>> x.vertex_coordinates # doctest: +NORMALIZE_WHITESPACE
|
|
49
|
+
array([[-2.5, -2.5],
|
|
50
|
+
[ 2.5, -2.5],
|
|
51
|
+
[ 2.5, 2.5],
|
|
52
|
+
[-2.5, 2.5]])
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
from scadpy.d2.shape import rectangle
|
|
56
|
+
|
|
57
|
+
return rectangle(size=[size, size])
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
__all__ = [
|
|
2
|
+
"are_shape_corners_convex",
|
|
3
|
+
"get_shape_corner_angles",
|
|
4
|
+
"get_shape_corner_normals",
|
|
5
|
+
"get_shape_corner_to_incoming_directed_edge",
|
|
6
|
+
"get_shape_corner_to_outgoing_directed_edge",
|
|
7
|
+
"get_shape_corner_to_vertex",
|
|
8
|
+
"get_shape_directed_edge_directions",
|
|
9
|
+
"get_shape_directed_edge_to_corner",
|
|
10
|
+
"get_shape_directed_edge_to_edge",
|
|
11
|
+
"get_shape_directed_edge_to_vertex",
|
|
12
|
+
"get_shape_edge_lengths",
|
|
13
|
+
"get_shape_edge_midpoints",
|
|
14
|
+
"get_shape_edge_normals",
|
|
15
|
+
"get_shape_edge_to_vertex",
|
|
16
|
+
"get_shape_part_vertex_coordinates",
|
|
17
|
+
"get_shape_ring_to_part",
|
|
18
|
+
"get_shape_ring_types",
|
|
19
|
+
"get_shape_vertex_coordinates",
|
|
20
|
+
"get_shape_vertex_to_part",
|
|
21
|
+
"get_shape_vertex_to_ring",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
from .corner import (
|
|
25
|
+
are_shape_corners_convex,
|
|
26
|
+
get_shape_corner_angles,
|
|
27
|
+
get_shape_corner_normals,
|
|
28
|
+
get_shape_corner_to_incoming_directed_edge,
|
|
29
|
+
get_shape_corner_to_outgoing_directed_edge,
|
|
30
|
+
get_shape_corner_to_vertex,
|
|
31
|
+
)
|
|
32
|
+
from .directed_edge import (
|
|
33
|
+
get_shape_directed_edge_directions,
|
|
34
|
+
get_shape_directed_edge_to_corner,
|
|
35
|
+
get_shape_directed_edge_to_edge,
|
|
36
|
+
get_shape_directed_edge_to_vertex,
|
|
37
|
+
)
|
|
38
|
+
from .edge import (
|
|
39
|
+
get_shape_edge_lengths,
|
|
40
|
+
get_shape_edge_midpoints,
|
|
41
|
+
get_shape_edge_normals,
|
|
42
|
+
get_shape_edge_to_vertex,
|
|
43
|
+
)
|
|
44
|
+
from .ring import (
|
|
45
|
+
get_shape_ring_to_part,
|
|
46
|
+
get_shape_ring_types,
|
|
47
|
+
)
|
|
48
|
+
from .vertex import (
|
|
49
|
+
get_shape_part_vertex_coordinates,
|
|
50
|
+
get_shape_vertex_coordinates,
|
|
51
|
+
get_shape_vertex_to_part,
|
|
52
|
+
get_shape_vertex_to_ring,
|
|
53
|
+
)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
__all__ = [
|
|
2
|
+
"are_shape_corners_convex",
|
|
3
|
+
"get_shape_corner_angles",
|
|
4
|
+
"get_shape_corner_normals",
|
|
5
|
+
"get_shape_corner_to_incoming_directed_edge",
|
|
6
|
+
"get_shape_corner_to_outgoing_directed_edge",
|
|
7
|
+
"get_shape_corner_to_vertex",
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
from .are_shape_corners_convex import are_shape_corners_convex
|
|
11
|
+
from .get_shape_corner_angles import get_shape_corner_angles
|
|
12
|
+
from .get_shape_corner_normals import get_shape_corner_normals
|
|
13
|
+
from .get_shape_corner_to_incoming_directed_edge import get_shape_corner_to_incoming_directed_edge
|
|
14
|
+
from .get_shape_corner_to_outgoing_directed_edge import get_shape_corner_to_outgoing_directed_edge
|
|
15
|
+
from .get_shape_corner_to_vertex import get_shape_corner_to_vertex
|