From 47b18c058144fa14c05ea9d3e19956752d4bec4e Mon Sep 17 00:00:00 2001 From: Jacob Kerstetter Date: Tue, 21 Oct 2025 12:16:30 -0400 Subject: [PATCH 1/3] adding remaining unit support --- .../core/_grpc/_services/v0/prepare_tools.py | 37 +++++++++++--- .../core/_grpc/_services/v0/repair_tools.py | 12 ++--- src/ansys/geometry/core/designer/body.py | 8 ++- .../core/designer/geometry_commands.py | 2 +- .../geometry/core/tools/prepare_tools.py | 50 +++++++++++++++---- src/ansys/geometry/core/tools/repair_tools.py | 48 ++++++++++++------ 6 files changed, 116 insertions(+), 41 deletions(-) diff --git a/src/ansys/geometry/core/_grpc/_services/v0/prepare_tools.py b/src/ansys/geometry/core/_grpc/_services/v0/prepare_tools.py index 694b0496fc..b783b952c4 100644 --- a/src/ansys/geometry/core/_grpc/_services/v0/prepare_tools.py +++ b/src/ansys/geometry/core/_grpc/_services/v0/prepare_tools.py @@ -25,6 +25,7 @@ from ansys.geometry.core.errors import protect_grpc +from ..base.conversions import from_measurement_to_server_length from ..base.prepare_tools import GRPCPrepareToolsService from .conversions import build_grpc_id @@ -115,7 +116,7 @@ def share_topology(self, **kwargs) -> dict: # noqa: D102 # Create the request - assumes all inputs are valid and of the proper type request = ShareTopologyRequest( selection=[Body(id=body) for body in kwargs["bodies"]], - tolerance=DoubleValue(value=kwargs["tolerance"]), + tolerance=DoubleValue(value=from_measurement_to_server_length(kwargs["tolerance"])), preserve_instances=BoolValue(value=kwargs["preserve_instances"]), ) @@ -136,7 +137,7 @@ def enhanced_share_topology(self, **kwargs) -> dict: # noqa: D102 # Create the request - assumes all inputs are valid and of the proper type request = ShareTopologyRequest( selection=[Body(id=body) for body in kwargs["bodies"]], - tolerance=DoubleValue(value=kwargs["tolerance"]), + tolerance=DoubleValue(value=from_measurement_to_server_length(kwargs["tolerance"])), preserve_instances=BoolValue(value=kwargs["preserve_instances"]), ) @@ -158,12 +159,24 @@ def find_logos(self, **kwargs) -> dict: # noqa: D102 from ansys.api.geometry.v0.models_pb2 import FindLogoOptions from ansys.api.geometry.v0.preparetools_pb2 import FindLogosRequest + # Check height objects + min_height = ( + from_measurement_to_server_length(kwargs["min_height"]) + if kwargs["min_height"] is not None + else None + ) + max_height = ( + from_measurement_to_server_length(kwargs["max_height"]) + if kwargs["max_height"] is not None + else None + ) + # Create the request - assumes all inputs are valid and of the proper type request = FindLogosRequest( bodies=[build_grpc_id(body) for body in kwargs["bodies"]], options=FindLogoOptions( - min_height=kwargs["min_height"], - max_height=kwargs["max_height"], + min_height=min_height, + max_height=max_height, ), ) @@ -181,12 +194,24 @@ def find_and_remove_logos(self, **kwargs) -> dict: # noqa: D102 from ansys.api.geometry.v0.models_pb2 import FindLogoOptions from ansys.api.geometry.v0.preparetools_pb2 import FindLogosRequest + # Check height objects + min_height = ( + from_measurement_to_server_length(kwargs["min_height"]) + if kwargs["min_height"] is not None + else None + ) + max_height = ( + from_measurement_to_server_length(kwargs["max_height"]) + if kwargs["max_height"] is not None + else None + ) + # Create the request - assumes all inputs are valid and of the proper type request = FindLogosRequest( bodies=[build_grpc_id(body) for body in kwargs["bodies"]], options=FindLogoOptions( - min_height=kwargs["min_height"], - max_height=kwargs["max_height"], + min_height=min_height, + max_height=max_height, ), ) diff --git a/src/ansys/geometry/core/_grpc/_services/v0/repair_tools.py b/src/ansys/geometry/core/_grpc/_services/v0/repair_tools.py index 25a4986d62..ed0a8e02b5 100644 --- a/src/ansys/geometry/core/_grpc/_services/v0/repair_tools.py +++ b/src/ansys/geometry/core/_grpc/_services/v0/repair_tools.py @@ -31,6 +31,7 @@ from ansys.geometry.core.errors import protect_grpc +from ..base.conversions import from_measurement_to_server_angle, from_measurement_to_server_length from ..base.repair_tools import GRPCRepairToolsService from .conversions import ( serialize_tracker_command_response, @@ -64,8 +65,8 @@ def find_split_edges(self, **kwargs) -> dict: # noqa: D102 # Create the request - assumes all inputs are valid and of the proper type request = FindSplitEdgesRequest( bodies_or_faces=kwargs["bodies_or_faces"], - angle=DoubleValue(value=float(kwargs["angle"])), - distance=DoubleValue(value=float(kwargs["distance"])), + angle=DoubleValue(value=float(from_measurement_to_server_angle(kwargs["angle"]))), + distance=DoubleValue(value=float(from_measurement_to_server_length(kwargs["distance"]))), ) # Call the gRPC service @@ -132,7 +133,7 @@ def find_short_edges(self, **kwargs) -> dict: # noqa: D102 # Create the request - assumes all inputs are valid and of the proper type request = FindShortEdgesRequest( selection=kwargs["selection"], - max_edge_length=DoubleValue(value=kwargs["length"]), + max_edge_length=DoubleValue(value=from_measurement_to_server_length(kwargs["length"])), ) # Call the gRPC service @@ -366,7 +367,7 @@ def find_and_fix_short_edges(self, **kwargs): # noqa: D102 # Create the request - assumes all inputs are valid and of the proper type request = FindShortEdgesRequest( selection=kwargs["selection"], - max_edge_length=DoubleValue(value=kwargs["length"]), + max_edge_length=DoubleValue(value=from_measurement_to_server_length(kwargs["length"])), comprehensive=kwargs["comprehensive_result"], ) @@ -422,8 +423,7 @@ def find_and_fix_split_edges(self, **kwargs) -> dict: # noqa: D102 # Create the request - assumes all inputs are valid and of the proper type request = FindSplitEdgesRequest( bodies_or_faces=kwargs["bodies_or_faces"], - angle=DoubleValue(value=float(kwargs["angle"])), - distance=DoubleValue(value=float(kwargs["length"])), + distance=DoubleValue(value=float(from_measurement_to_server_length(kwargs["length"]))), comprehensive=kwargs["comprehensive_result"], ) diff --git a/src/ansys/geometry/core/designer/body.py b/src/ansys/geometry/core/designer/body.py index ea38c12e00..4475d803f7 100644 --- a/src/ansys/geometry/core/designer/body.py +++ b/src/ansys/geometry/core/designer/body.py @@ -1929,11 +1929,15 @@ def tessellate( # noqa: D102 ) @ensure_design_is_active - def shell_body(self, offset: Real) -> bool: # noqa: D102 + def shell_body(self, offset: Distance | Quantity | Real) -> bool: # noqa: D102 return self._template.shell_body(offset) @ensure_design_is_active - def remove_faces(self, selection: Face | Iterable[Face], offset: Real) -> bool: # noqa: D102 + def remove_faces( # noqa: D102 + self, + selection: Face | Iterable[Face], + offset: Distance | Quantity | Real, + ) -> bool: return self._template.remove_faces(selection, offset) @graphics_required diff --git a/src/ansys/geometry/core/designer/geometry_commands.py b/src/ansys/geometry/core/designer/geometry_commands.py index fe5f26c309..2c98a187a2 100644 --- a/src/ansys/geometry/core/designer/geometry_commands.py +++ b/src/ansys/geometry/core/designer/geometry_commands.py @@ -273,7 +273,7 @@ def extrude_faces( ---------- faces : Face | list[Face] Faces to extrude. - distance : Real + distance : Distance | Quantity | Real Distance to extrude. direction : UnitVector3D, default: None Direction of extrusion. If no direction is provided, it will be inferred. diff --git a/src/ansys/geometry/core/tools/prepare_tools.py b/src/ansys/geometry/core/tools/prepare_tools.py index 26b62c5781..5d655e0c85 100644 --- a/src/ansys/geometry/core/tools/prepare_tools.py +++ b/src/ansys/geometry/core/tools/prepare_tools.py @@ -228,7 +228,10 @@ def remove_rounds(self, faces: list["Face"], auto_shrink: bool = False) -> bool: @min_backend_version(24, 2, 0) def share_topology( - self, bodies: list["Body"], tol: Real = 0.0, preserve_instances: bool = False + self, + bodies: list["Body"], + tol: Distance | Quantity | Real = 0.0, + preserve_instances: bool = False, ) -> bool: """Share topology between the chosen bodies. @@ -236,7 +239,7 @@ def share_topology( ---------- bodies : list[Body] List of bodies to share topology between. - tol : Real + tol : Distance | Quantity | Real Maximum distance between bodies. preserve_instances : bool Whether instances are preserved. @@ -257,6 +260,7 @@ def share_topology( # Verify inputs check_type_all_elements_in_iterable(bodies, Body) + tol = tol if isinstance(tol, Distance) else Distance(tol) response = self._grpc_client._services.prepare_tools.share_topology( bodies=[body.id for body in bodies], @@ -268,7 +272,10 @@ def share_topology( @min_backend_version(25, 2, 0) def enhanced_share_topology( - self, bodies: list["Body"], tol: Real = 0.0, preserve_instances: bool = False + self, + bodies: list["Body"], + tol: Distance | Quantity | Real = 0.0, + preserve_instances: bool = False, ) -> RepairToolMessage: """Share topology between the chosen bodies. @@ -276,7 +283,7 @@ def enhanced_share_topology( ---------- bodies : list[Body] List of bodies to share topology between. - tol : Real + tol : Distance | Quantity | Real Maximum distance between bodies. preserve_instances : bool Whether instances are preserved. @@ -299,6 +306,7 @@ def enhanced_share_topology( # Verify inputs check_type_all_elements_in_iterable(bodies, Body) + tol = tol if isinstance(tol, Distance) else Distance(tol) response = self._grpc_client._services.prepare_tools.enhanced_share_topology( bodies=[body.id for body in bodies], @@ -318,7 +326,10 @@ def enhanced_share_topology( @check_input_types @min_backend_version(25, 2, 0) def find_logos( - self, bodies: list["Body"] = None, min_height: Real = None, max_height: Real = None + self, + bodies: list["Body"] = None, + min_height: Distance | Quantity | Real = None, + max_height: Distance | Quantity | Real = None ) -> "LogoProblemArea": """Detect logos in geometry. @@ -329,9 +340,9 @@ def find_logos( ---------- bodies : list[Body], optional List of bodies where logos should be detected - min_height : real, optional + min_height : Distance | Quantity | Real, optional The minimum height when searching for logos - max_height: real, optional + max_height: Distance | Quantity | Real, optional The minimum height when searching for logos Returns @@ -357,6 +368,13 @@ def find_logos( check_type_all_elements_in_iterable(bodies, Body) bodies = [] if bodies is None else bodies + + # Convert the height inputs to Distance if they are not already + if min_height: + min_height = min_height if isinstance(min_height, Distance) else Distance(min_height) + if max_height: + max_height = max_height if isinstance(max_height, Distance) else Distance(max_height) + response = self._grpc_client._services.prepare_tools.find_logos( bodies=[body.id for body in bodies], min_height=min_height, @@ -372,7 +390,10 @@ def find_logos( @check_input_types @min_backend_version(25, 2, 0) def find_and_remove_logos( - self, bodies: list["Body"] = None, min_height: Real = None, max_height: Real = None + self, + bodies: list["Body"] = None, + min_height: Distance | Quantity | Real = None, + max_height: Distance | Quantity | Real = None ) -> bool: """Detect and remove logos in geometry. @@ -382,10 +403,10 @@ def find_and_remove_logos( ---------- bodies : list[Body], optional List of bodies where logos should be detected and removed. - min_height : real, optional - The minimum height when searching for logos - max_height: real, optional + min_height : Distance | Quantity | Real, optional The minimum height when searching for logos + max_height: Distance | Quantity | Real, optional + The maximum height when searching for logos Returns ------- @@ -409,6 +430,13 @@ def find_and_remove_logos( check_type_all_elements_in_iterable(bodies, Body) bodies = [] if bodies is None else bodies + + # Convert the height inputs to Distance if they are not already + if min_height: + min_height = min_height if isinstance(min_height, Distance) else Distance(min_height) + if max_height: + max_height = max_height if isinstance(max_height, Distance) else Distance(max_height) + response = self._grpc_client._services.prepare_tools.find_and_remove_logos( bodies=[body.id for body in bodies], min_height=min_height, diff --git a/src/ansys/geometry/core/tools/repair_tools.py b/src/ansys/geometry/core/tools/repair_tools.py index 994cab0f2e..df0edceda7 100644 --- a/src/ansys/geometry/core/tools/repair_tools.py +++ b/src/ansys/geometry/core/tools/repair_tools.py @@ -97,7 +97,10 @@ def __init__(self, grpc_client: GrpcClient, modeler: "Modeler", _internal_use: b self._grpc_client = grpc_client def find_split_edges( - self, bodies: list["Body"], angle: Real = 0.0, length: Real = 0.0 + self, + bodies: list["Body"], + angle: Angle | pint.Quantity | Real = 0.0, + length: Distance | pint.Quantity | Real = 0.0 ) -> list[SplitEdgeProblemAreas]: """Find split edges in the given list of bodies. @@ -108,9 +111,9 @@ def find_split_edges( ---------- bodies : list[Body] List of bodies that split edges are investigated on. - angle : Real + angle : Angle | ~pint.Quantity | Real The maximum angle between edges. - length : Real + length : Distance | ~pint.Quantity | Real The maximum length of the edges. Returns @@ -123,6 +126,10 @@ def find_split_edges( body_ids = [body.id for body in bodies] + # Convert the measurement objects + angle = angle if isinstance(angle, Angle) else Angle(angle) + length = length if isinstance(length, Distance) else Distance(length) + response = self._grpc_client.services.repair_tools.find_split_edges( bodies_or_faces=body_ids, angle=angle, distance=length ) @@ -203,7 +210,7 @@ def find_inexact_edges(self, bodies: list["Body"]) -> list[InexactEdgeProblemAre ] def find_short_edges( - self, bodies: list["Body"], length: Real = 0.0 + self, bodies: list["Body"], length: Distance | pint.Quantity | Real = 0.0 ) -> list[ShortEdgeProblemAreas]: """Find the short edge problem areas. @@ -214,6 +221,8 @@ def find_short_edges( ---------- bodies : list[Body] List of bodies that short edges are investigated on. + length : Distance | ~pint.Quantity | Real, optional + The maximum length of the edges. By default, 0.0. Returns ------- @@ -224,6 +233,9 @@ def find_short_edges( return [] body_ids = [body.id for body in bodies] + + # Convert the measurement object + length = length if isinstance(length, Distance) else Distance(length) response = self._grpc_client.services.repair_tools.find_short_edges( selection=body_ids, length=length @@ -514,7 +526,10 @@ def find_interferences( @min_backend_version(25, 2, 0) def find_and_fix_short_edges( - self, bodies: list["Body"], length: Real = 0.0, comprehensive_result: bool = False + self, + bodies: list["Body"], + length: Distance | pint.Quantity | Real = 0.0, + comprehensive_result: bool = False ) -> RepairToolMessage: """Find and fix the short edge problem areas. @@ -524,7 +539,7 @@ def find_and_fix_short_edges( ---------- bodies : list[Body] List of bodies that short edges are investigated on. - length : Real, optional + length : Distance | ~pint.Quantity | Real, optional The maximum length of the edges. By default, 0.0. comprehensive_result : bool, optional Whether to fix all problem areas individually. @@ -542,7 +557,7 @@ def find_and_fix_short_edges( from ansys.geometry.core.designer.body import Body check_type_all_elements_in_iterable(bodies, Body) - check_type(length, Real) + check_type(length, (Distance, pint.Quantity, Real)) check_type(comprehensive_result, bool) if not bodies: @@ -552,6 +567,7 @@ def find_and_fix_short_edges( body_ids = [body.id for body in bodies] parent_design = get_design_from_body(bodies[0]) + length = length if isinstance(length, Distance) else Distance(length) response = self._grpc_client.services.repair_tools.find_and_fix_short_edges( selection=body_ids, @@ -581,8 +597,6 @@ def find_and_fix_extra_edges( ---------- bodies : list[Body] List of bodies that short edges are investigated on. - length : Real - The maximum length of the edges. comprehensive_result : bool, optional Whether to fix all problem areas individually. By default, False. @@ -627,8 +641,8 @@ def find_and_fix_extra_edges( def find_and_fix_split_edges( self, bodies: list["Body"], - angle: Real = 0.0, - length: Real = 0.0, + angle: Angle | pint.Quantity | Real = 0.0, + length: Distance | pint.Quantity | Real = 0.0, comprehensive_result: bool = False, ) -> RepairToolMessage: """Find and fix the split edge problem areas. @@ -639,9 +653,9 @@ def find_and_fix_split_edges( ---------- bodies : list[Body] List of bodies that split edges are investigated on. - angle : Real, optional + angle : Angle | ~pint.Quantity | Real, optional The maximum angle between edges. By default, 0.0. - length : Real, optional + length : Distance | ~pint.Quantity | Real, optional The maximum length of the edges. By default, 0.0. comprehensive_result : bool, optional Whether to fix all problem areas individually. @@ -659,8 +673,8 @@ def find_and_fix_split_edges( from ansys.geometry.core.designer.body import Body check_type_all_elements_in_iterable(bodies, Body) - check_type(angle, Real) - check_type(length, Real) + check_type(angle, (Angle, pint.Quantity, Real)) + check_type(length, (Distance, pint.Quantity, Real)) check_type(comprehensive_result, bool) if not bodies: @@ -671,6 +685,10 @@ def find_and_fix_split_edges( body_ids = [body.id for body in bodies] parent_design = get_design_from_body(bodies[0]) + # Convert the measurement objects + angle = angle if isinstance(angle, Angle) else Angle(angle) + length = length if isinstance(length, Distance) else Distance(length) + response = self._grpc_client.services.repair_tools.find_and_fix_split_edges( bodies_or_faces=body_ids, parent_design=parent_design, From f68d6bea195ea9482804ad0322e0a2af347882c2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 17:11:35 +0000 Subject: [PATCH 2/3] chore: auto fixes from pre-commit hooks --- src/ansys/geometry/core/_grpc/_services/v0/repair_tools.py | 4 +++- src/ansys/geometry/core/tools/prepare_tools.py | 4 ++-- src/ansys/geometry/core/tools/repair_tools.py | 6 +++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/ansys/geometry/core/_grpc/_services/v0/repair_tools.py b/src/ansys/geometry/core/_grpc/_services/v0/repair_tools.py index ed0a8e02b5..a17d4e1a01 100644 --- a/src/ansys/geometry/core/_grpc/_services/v0/repair_tools.py +++ b/src/ansys/geometry/core/_grpc/_services/v0/repair_tools.py @@ -66,7 +66,9 @@ def find_split_edges(self, **kwargs) -> dict: # noqa: D102 request = FindSplitEdgesRequest( bodies_or_faces=kwargs["bodies_or_faces"], angle=DoubleValue(value=float(from_measurement_to_server_angle(kwargs["angle"]))), - distance=DoubleValue(value=float(from_measurement_to_server_length(kwargs["distance"]))), + distance=DoubleValue( + value=float(from_measurement_to_server_length(kwargs["distance"])) + ), ) # Call the gRPC service diff --git a/src/ansys/geometry/core/tools/prepare_tools.py b/src/ansys/geometry/core/tools/prepare_tools.py index 5d655e0c85..30c4d66046 100644 --- a/src/ansys/geometry/core/tools/prepare_tools.py +++ b/src/ansys/geometry/core/tools/prepare_tools.py @@ -329,7 +329,7 @@ def find_logos( self, bodies: list["Body"] = None, min_height: Distance | Quantity | Real = None, - max_height: Distance | Quantity | Real = None + max_height: Distance | Quantity | Real = None, ) -> "LogoProblemArea": """Detect logos in geometry. @@ -393,7 +393,7 @@ def find_and_remove_logos( self, bodies: list["Body"] = None, min_height: Distance | Quantity | Real = None, - max_height: Distance | Quantity | Real = None + max_height: Distance | Quantity | Real = None, ) -> bool: """Detect and remove logos in geometry. diff --git a/src/ansys/geometry/core/tools/repair_tools.py b/src/ansys/geometry/core/tools/repair_tools.py index df0edceda7..7a57e1780b 100644 --- a/src/ansys/geometry/core/tools/repair_tools.py +++ b/src/ansys/geometry/core/tools/repair_tools.py @@ -100,7 +100,7 @@ def find_split_edges( self, bodies: list["Body"], angle: Angle | pint.Quantity | Real = 0.0, - length: Distance | pint.Quantity | Real = 0.0 + length: Distance | pint.Quantity | Real = 0.0, ) -> list[SplitEdgeProblemAreas]: """Find split edges in the given list of bodies. @@ -233,7 +233,7 @@ def find_short_edges( return [] body_ids = [body.id for body in bodies] - + # Convert the measurement object length = length if isinstance(length, Distance) else Distance(length) @@ -529,7 +529,7 @@ def find_and_fix_short_edges( self, bodies: list["Body"], length: Distance | pint.Quantity | Real = 0.0, - comprehensive_result: bool = False + comprehensive_result: bool = False, ) -> RepairToolMessage: """Find and fix the short edge problem areas. From cda6209ee9ac39819f81cd5e01891522fc11933b Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Tue, 21 Oct 2025 17:13:09 +0000 Subject: [PATCH 3/3] chore: adding changelog file 2340.maintenance.md [dependabot-skip] --- doc/changelog.d/2340.maintenance.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changelog.d/2340.maintenance.md diff --git a/doc/changelog.d/2340.maintenance.md b/doc/changelog.d/2340.maintenance.md new file mode 100644 index 0000000000..f3398ef583 --- /dev/null +++ b/doc/changelog.d/2340.maintenance.md @@ -0,0 +1 @@ +Add unit support