diff --git a/doc/changelog.d/2288.maintenance.md b/doc/changelog.d/2288.maintenance.md new file mode 100644 index 0000000000..765f7aa18c --- /dev/null +++ b/doc/changelog.d/2288.maintenance.md @@ -0,0 +1 @@ +Removing commands stub from body module diff --git a/src/ansys/geometry/core/_grpc/_services/base/bodies.py b/src/ansys/geometry/core/_grpc/_services/base/bodies.py index a3ad45a881..5cdbcfd121 100644 --- a/src/ansys/geometry/core/_grpc/_services/base/bodies.py +++ b/src/ansys/geometry/core/_grpc/_services/base/bodies.py @@ -236,3 +236,38 @@ def create_body_from_loft_profiles_with_guides(self, **kwargs) -> dict: def combine_merge(self, **kwargs) -> dict: """Combine and merge bodies.""" pass + + @abstractmethod + def assign_midsurface_thickness(self, **kwargs) -> dict: + """Assign a thickness to a midsurface body.""" + pass + + @abstractmethod + def assign_midsurface_offset(self, **kwargs) -> dict: + """Assign a offset to a midsurface body.""" + pass + + @abstractmethod + def shell(self, **kwargs) -> dict: + """Shell a body.""" + pass + + @abstractmethod + def remove_faces(self, **kwargs) -> dict: + """Remove faces from a body.""" + pass + + @abstractmethod + def imprint_curves(self, **kwargs) -> dict: + """Imprint curves on a body.""" + pass + + @abstractmethod + def project_curves(self, **kwargs) -> dict: + """Project curves on a body.""" + pass + + @abstractmethod + def imprint_projected_curves(self, **kwargs) -> dict: + """Imprint projected curves on a body.""" + pass diff --git a/src/ansys/geometry/core/_grpc/_services/v0/bodies.py b/src/ansys/geometry/core/_grpc/_services/v0/bodies.py index 6452108f4a..93ef9c5a7a 100644 --- a/src/ansys/geometry/core/_grpc/_services/v0/bodies.py +++ b/src/ansys/geometry/core/_grpc/_services/v0/bodies.py @@ -905,3 +905,185 @@ def combine_merge(self, **kwargs) -> dict: # noqa: D102 # Return the response - formatted as a dictionary return {} + + @protect_grpc + def assign_midsurface_thickness(self, **kwargs) -> dict: # noqa: D102 + from ansys.api.geometry.v0.commands_pb2 import AssignMidSurfaceThicknessRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = AssignMidSurfaceThicknessRequest( + bodies_or_faces=kwargs["ids"], + thickness=from_measurement_to_server_length(kwargs["thickness"]), + ) + + # Call the gRPC service + self.command_stub.AssignMidSurfaceThickness(request=request) + + # Return the response - formatted as a dictionary + return {} + + @protect_grpc + def assign_midsurface_offset(self, **kwargs) -> dict: # noqa: D102 + from ansys.api.geometry.v0.commands_pb2 import AssignMidSurfaceOffsetTypeRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = AssignMidSurfaceOffsetTypeRequest( + bodies_or_faces=kwargs["ids"], + offset_type=kwargs["offset_type"].value, + ) + + # Call the gRPC service + self.command_stub.AssignMidSurfaceOffsetType(request=request) + + # Return the response - formatted as a dictionary + return {} + + @protect_grpc + def shell(self, **kwargs) -> dict: # noqa: D102 + from ansys.api.geometry.v0.commands_pb2 import ShellRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = ShellRequest( + selection=build_grpc_id(kwargs["id"]), + offset=from_measurement_to_server_length(kwargs["offset"]), + ) + + # Call the gRPC service + response = self.command_stub.Shell(request=request) + + # Return the response - formatted as a dictionary + return { + "success": response.success, + } + + @protect_grpc + def remove_faces(self, **kwargs) -> dict: # noqa: D102 + from ansys.api.geometry.v0.commands_pb2 import RemoveFacesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = RemoveFacesRequest( + selection=[build_grpc_id(id) for id in kwargs["face_ids"]], + offset=from_measurement_to_server_length(kwargs["offset"]), + ) + + # Call the gRPC service + response = self.command_stub.RemoveFaces(request=request) + + # Return the response - formatted as a dictionary + return { + "success": response.success, + } + + @protect_grpc + def imprint_curves(self, **kwargs) -> dict: # noqa: D102 + from ansys.api.geometry.v0.commands_pb2 import ImprintCurvesRequest + + # Convert sketch and trimmed curves to gRPC format + sketch = kwargs["sketch"] + curves = None + if sketch: + curves = from_sketch_shapes_to_grpc_geometries(sketch.plane, sketch.edges, sketch.faces) + + trimmed_curves = None + if kwargs["tc"]: + trimmed_curves = [from_trimmed_curve_to_grpc_trimmed_curve(tc) for tc in kwargs["tc"]] + + # Create the request - assumes all inputs are valid and of the proper type + request = ImprintCurvesRequest( + body=kwargs["id"], + curves=curves, + faces=kwargs["face_ids"], + plane=from_plane_to_grpc_plane(sketch.plane) if sketch else None, + trimmed_curves=trimmed_curves, + ) + + # Call the gRPC service + response = self.command_stub.ImprintCurves(request=request) + + # Return the response - formatted as a dictionary + return { + "edges": [ + { + "id": edge.id, + "curve_type": edge.curve_type, + "is_reversed": edge.is_reversed, + } + for edge in response.edges + ], + "faces": [ + { + "id": face.id, + "surface_type": face.surface_type, + "is_reversed": face.is_reversed, + } + for face in response.faces + ], + } + + @protect_grpc + def project_curves(self, **kwargs) -> dict: # noqa: D102 + from ansys.api.geometry.v0.commands_pb2 import ProjectCurvesRequest + + # Convert sketch and trimmed curves to gRPC format + sketch = kwargs["sketch"] + curves = from_sketch_shapes_to_grpc_geometries( + sketch.plane, sketch.edges, sketch.faces, kwargs["only_one_curve"] + ) + + # Create the request - assumes all inputs are valid and of the proper type + request = ProjectCurvesRequest( + body=kwargs["id"], + curves=curves, + direction=from_unit_vector_to_grpc_direction(kwargs["direction"]), + closest_face=kwargs["closest_face"], + plane=from_plane_to_grpc_plane(sketch.plane), + ) + + # Call the gRPC service + response = self.command_stub.ProjectCurves(request=request) + + # Return the response - formatted as a dictionary + return { + "faces": [ + { + "id": face.id, + "surface_type": face.surface_type, + "is_reversed": face.is_reversed, + } + for face in response.faces + ], + } + + @protect_grpc + def imprint_projected_curves(self, **kwargs) -> dict: # noqa: D102 + from ansys.api.geometry.v0.commands_pb2 import ProjectCurvesRequest + + # Convert sketch and trimmed curves to gRPC format + sketch = kwargs["sketch"] + curves = from_sketch_shapes_to_grpc_geometries( + sketch.plane, sketch.edges, sketch.faces, kwargs["only_one_curve"] + ) + + # Create the request - assumes all inputs are valid and of the proper type + request = ProjectCurvesRequest( + body=kwargs["id"], + curves=curves, + direction=from_unit_vector_to_grpc_direction(kwargs["direction"]), + closest_face=kwargs["closest_face"], + plane=from_plane_to_grpc_plane(sketch.plane), + ) + + # Call the gRPC service + response = self.command_stub.ImprintProjectedCurves(request=request) + + # Return the response - formatted as a dictionary + return { + "faces": [ + { + "id": face.id, + "surface_type": face.surface_type, + "is_reversed": face.is_reversed, + } + for face in response.faces + ], + } diff --git a/src/ansys/geometry/core/_grpc/_services/v1/bodies.py b/src/ansys/geometry/core/_grpc/_services/v1/bodies.py index c5a13c9fad..d9d1838e0a 100644 --- a/src/ansys/geometry/core/_grpc/_services/v1/bodies.py +++ b/src/ansys/geometry/core/_grpc/_services/v1/bodies.py @@ -207,3 +207,31 @@ def create_body_from_loft_profiles_with_guides(self, **kwargs) -> dict: # noqa: @protect_grpc def combine_merge(self, **kwargs) -> dict: # noqa: D102 raise NotImplementedError + + @protect_grpc + def assign_midsurface_thickness(self, **kwargs) -> dict: # noqa: D102 + raise NotImplementedError + + @protect_grpc + def assign_midsurface_offset(self, **kwargs) -> dict: # noqa: D102 + raise NotImplementedError + + @protect_grpc + def shell(self, **kwargs) -> dict: # noqa: D102 + raise NotImplementedError + + @protect_grpc + def remove_faces(self, **kwargs) -> dict: # noqa: D102 + raise NotImplementedError + + @protect_grpc + def imprint_curves(self, **kwargs) -> dict: # noqa: D102 + raise NotImplementedError + + @protect_grpc + def project_curves(self, **kwargs) -> dict: # noqa: D102 + raise NotImplementedError + + @protect_grpc + def imprint_projected_curves(self, **kwargs) -> dict: # noqa: D102 + raise NotImplementedError diff --git a/src/ansys/geometry/core/designer/body.py b/src/ansys/geometry/core/designer/body.py index 0d6ef83692..56b879c68a 100644 --- a/src/ansys/geometry/core/designer/body.py +++ b/src/ansys/geometry/core/designer/body.py @@ -28,31 +28,15 @@ from typing import TYPE_CHECKING, Union from ansys.api.dbu.v0.dbumodels_pb2 import EntityIdentifier -from ansys.api.geometry.v0.commands_pb2 import ( - AssignMidSurfaceOffsetTypeRequest, - AssignMidSurfaceThicknessRequest, - ImprintCurvesRequest, - ProjectCurvesRequest, - RemoveFacesRequest, - ShellRequest, -) -from ansys.api.geometry.v0.commands_pb2_grpc import CommandsStub from beartype import beartype as check_input_types import matplotlib.colors as mcolors from pint import Quantity import ansys.geometry.core as pyansys_geom from ansys.geometry.core.connection.client import GrpcClient -from ansys.geometry.core.connection.conversions import ( - plane_to_grpc_plane, - sketch_shapes_to_grpc_geometries, - trimmed_curve_to_grpc_trimmed_curve, - unit_vector_to_grpc_direction, -) from ansys.geometry.core.designer.edge import CurveType, Edge from ansys.geometry.core.designer.face import Face, SurfaceType from ansys.geometry.core.designer.vertex import Vertex -from ansys.geometry.core.errors import protect_grpc from ansys.geometry.core.materials.material import Material from ansys.geometry.core.math.bbox import BoundingBox from ansys.geometry.core.math.constants import IDENTITY_MATRIX44 @@ -343,12 +327,12 @@ def remove_assigned_material(self) -> None: return @abstractmethod - def add_midsurface_thickness(self, thickness: Quantity) -> None: + def add_midsurface_thickness(self, thickness: Distance | Quantity | Real) -> None: """Add a mid-surface thickness to a surface body. Parameters ---------- - thickness : ~pint.Quantity + thickness : Distance | Quantity | Real Thickness to assign. Notes @@ -654,12 +638,12 @@ def tessellate( return @abstractmethod - def shell_body(self, offset: Real) -> bool: + def shell_body(self, offset: Distance | Quantity | Real) -> bool: """Shell the body to the thickness specified. Parameters ---------- - offset : Real + offset : Distance | Quantity | Real Shell thickness. Returns @@ -674,14 +658,16 @@ def shell_body(self, offset: Real) -> bool: return @abstractmethod - def remove_faces(self, selection: Face | Iterable[Face], offset: Real) -> bool: + def remove_faces( + self, selection: Face | Iterable[Face], offset: Distance | Quantity | Real + ) -> bool: """Shell by removing a given set of faces. Parameters ---------- selection : Face | Iterable[Face] Face or faces to be removed. - offset : Real + offset : Distance | Quantity | Real Shell thickness. Returns @@ -875,7 +861,6 @@ def __init__( self._surface_thickness = None self._surface_offset = None self._is_alive = True - self._commands_stub = CommandsStub(self._grpc_client.channel) self._tessellation = None self._fill_style = FillStyle.DEFAULT self._color = None @@ -1084,30 +1069,25 @@ def remove_assigned_material(self) -> None: # noqa: D102 self._grpc_client.log.debug(f"Removing assigned material for body {self.id}.") self._grpc_client.services.bodies.remove_assigned_material(ids=[self.id]) - @protect_grpc @check_input_types - def add_midsurface_thickness(self, thickness: Quantity) -> None: # noqa: D102 + def add_midsurface_thickness(self, thickness: Distance | Quantity | Real) -> None: # noqa: D102 + thickness = thickness if isinstance(thickness, Distance) else Distance(thickness) + if self.is_surface: - self._commands_stub.AssignMidSurfaceThickness( - AssignMidSurfaceThicknessRequest( - bodies_or_faces=[self.id], - thickness=thickness.m_as(DEFAULT_UNITS.SERVER_LENGTH), - ) + self._grpc_client.services.bodies.assign_midsurface_thickness( + ids=[self.id], thickness=thickness ) - self._surface_thickness = thickness + self._surface_thickness = thickness.value else: self._grpc_client.log.warning( f"Body {self.name} cannot be assigned a mid-surface thickness because it is not a surface. Ignoring request." # noqa : E501 ) - @protect_grpc @check_input_types def add_midsurface_offset(self, offset: MidSurfaceOffsetType) -> None: # noqa: D102 if self.is_surface: - self._commands_stub.AssignMidSurfaceOffsetType( - AssignMidSurfaceOffsetTypeRequest( - bodies_or_faces=[self.id], offset_type=offset.value - ) + self._grpc_client.services.bodies.assign_midsurface_offset( + ids=[self.id], offset_type=offset ) self._surface_offset = offset else: @@ -1328,30 +1308,29 @@ def tessellate( # noqa: D102 else: return comp - @protect_grpc @reset_tessellation_cache @check_input_types @min_backend_version(25, 2, 0) - def shell_body(self, offset: Real) -> bool: # noqa: D102 + def shell_body(self, offset: Distance | Quantity | Real) -> bool: # noqa: D102 self._grpc_client.log.debug(f"Shelling body {self.id} to offset {offset}.") - result = self._commands_stub.Shell( - ShellRequest( - selection=self._grpc_id, - offset=offset, - ) + offset = offset if isinstance(offset, Distance) else Distance(offset) + result = self._grpc_client.services.bodies.shell( + id=self.id, + offset=offset, ) - if result.success is False: + if result.get("success") is False: self._grpc_client.log.warning(f"Failed to shell body {self.id}.") - return result.success + return result.get("success") - @protect_grpc @reset_tessellation_cache @check_input_types @min_backend_version(25, 2, 0) - 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: selection: list[Face] = selection if isinstance(selection, Iterable) else [selection] check_type_all_elements_in_iterable(selection, Face) @@ -1362,17 +1341,16 @@ def remove_faces(self, selection: Face | Iterable[Face], offset: Real) -> bool: self._grpc_client.log.debug(f"Removing faces to shell body {self.id}.") - result = self._commands_stub.RemoveFaces( - RemoveFacesRequest( - selection=[face._grpc_id for face in selection], - offset=offset, - ) + offset = offset if isinstance(offset, Distance) else Distance(offset) + result = self._grpc_client.services.bodies.remove_faces( + face_ids=[face.id for face in selection], + offset=offset, ) - if result.success is False: + if result.get("success") is False: self._grpc_client.log.warning(f"Failed to remove faces from body {self.id}.") - return result.success + return result.get("success") @min_backend_version(25, 2, 0) @check_input_types @@ -1641,7 +1619,6 @@ def add_midsurface_offset( # noqa: D102 ) -> None: self._template.add_midsurface_offset(offset) - @protect_grpc @ensure_design_is_active def imprint_curves( # noqa: D102 self, faces: list[Face], sketch: Sketch = None, trimmed_curves: list[TrimmedCurve] = None @@ -1680,50 +1657,35 @@ def imprint_curves( # noqa: D102 f"Imprinting curves on {self.id} for faces {[face.id for face in faces]}." ) - curves = None - grpc_trimmed_curves = None - - if sketch: - curves = sketch_shapes_to_grpc_geometries(sketch._plane, sketch.edges, sketch.faces) - - if trimmed_curves: - grpc_trimmed_curves = [ - trimmed_curve_to_grpc_trimmed_curve(curve) for curve in trimmed_curves - ] - - imprint_response = self._template._commands_stub.ImprintCurves( - ImprintCurvesRequest( - body=self._id, - curves=curves, - faces=[face._id for face in faces], - plane=plane_to_grpc_plane(sketch.plane) if sketch else None, - trimmed_curves=grpc_trimmed_curves, - ) + imprint_response = self._template._grpc_client.services.bodies.imprint_curves( + id=self.id, + sketch=sketch, + face_ids=[face.id for face in faces], + tc=trimmed_curves, ) new_edges = [ Edge( - grpc_edge.id, - CurveType(grpc_edge.curve_type), + edge.get("id"), + CurveType(edge.get("curve_type")), self, self._template._grpc_client, ) - for grpc_edge in imprint_response.edges + for edge in imprint_response.get("edges") ] new_faces = [ Face( - grpc_face.id, - SurfaceType(grpc_face.surface_type), + face.get("id"), + SurfaceType(face.get("surface_type")), self, self._template._grpc_client, ) - for grpc_face in imprint_response.faces + for face in imprint_response.get("faces") ] return (new_edges, new_faces) - @protect_grpc @ensure_design_is_active def project_curves( # noqa: D102 self, @@ -1732,35 +1694,29 @@ def project_curves( # noqa: D102 closest_face: bool, only_one_curve: bool = False, ) -> list[Face]: - curves = sketch_shapes_to_grpc_geometries( - sketch._plane, sketch.edges, sketch.faces, only_one_curve=only_one_curve - ) self._template._grpc_client.log.debug(f"Projecting provided curves on {self.id}.") - project_response = self._template._commands_stub.ProjectCurves( - ProjectCurvesRequest( - body=self._id, - curves=curves, - direction=unit_vector_to_grpc_direction(direction), - closest_face=closest_face, - plane=plane_to_grpc_plane(sketch.plane), - ) + project_response = self._template._grpc_client.services.bodies.project_curves( + id=self.id, + sketch=sketch, + direction=direction, + closest_face=closest_face, + only_one_curve=only_one_curve, ) projected_faces = [ Face( - grpc_face.id, - SurfaceType(grpc_face.surface_type), + face.get("id"), + SurfaceType(face.get("surface_type")), self, self._template._grpc_client, ) - for grpc_face in project_response.faces + for face in project_response.get("faces") ] return projected_faces @check_input_types - @protect_grpc @ensure_design_is_active def imprint_projected_curves( # noqa: D102 self, @@ -1769,29 +1725,24 @@ def imprint_projected_curves( # noqa: D102 closest_face: bool, only_one_curve: bool = False, ) -> list[Face]: - curves = sketch_shapes_to_grpc_geometries( - sketch._plane, sketch.edges, sketch.faces, only_one_curve=only_one_curve - ) self._template._grpc_client.log.debug(f"Projecting provided curves on {self.id}.") - response = self._template._commands_stub.ImprintProjectedCurves( - ProjectCurvesRequest( - body=self._id, - curves=curves, - direction=unit_vector_to_grpc_direction(direction), - closest_face=closest_face, - plane=plane_to_grpc_plane(sketch.plane), - ) + response = self._template._grpc_client.services.bodies.imprint_projected_curves( + id=self.id, + direction=direction, + sketch=sketch, + closest_face=closest_face, + only_one_curve=only_one_curve, ) imprinted_faces = [ Face( - grpc_face.id, - SurfaceType(grpc_face.surface_type), + face.get("id"), + SurfaceType(face.get("surface_type")), self, self._template._grpc_client, ) - for grpc_face in response.faces + for face in response.get("faces") ] return imprinted_faces diff --git a/tests/integration/test_design.py b/tests/integration/test_design.py index 672c90ce61..9a1cb0cdcc 100644 --- a/tests/integration/test_design.py +++ b/tests/integration/test_design.py @@ -1740,7 +1740,7 @@ def test_midsurface_properties(modeler: Modeler): assert "Exists : True" in surf_repr assert "Parent component : MidSurfaceProperties" in surf_repr assert "Surface body : True" in surf_repr - assert "Surface thickness : 30 millimeter" in surf_repr + assert "Surface thickness : 30.0 millimeter" in surf_repr assert "Surface offset : MidSurfaceOffsetType.BOTTOM" in surf_repr assert f"Color : {DEFAULT_COLOR}" in surf_repr