diff --git a/doc/changelog.d/1753.maintenance.md b/doc/changelog.d/1753.maintenance.md new file mode 100644 index 0000000000..97e5671828 --- /dev/null +++ b/doc/changelog.d/1753.maintenance.md @@ -0,0 +1 @@ +update CHANGELOG for v0.9.0 \ No newline at end of file diff --git a/doc/changelog.d/2441.maintenance.md b/doc/changelog.d/2441.maintenance.md new file mode 100644 index 0000000000..5358bcfe36 --- /dev/null +++ b/doc/changelog.d/2441.maintenance.md @@ -0,0 +1 @@ +Chore: v1 implementation of repair stubs 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 e60a3fc05c..5ab137fc0f 100644 --- a/src/ansys/geometry/core/_grpc/_services/v0/repair_tools.py +++ b/src/ansys/geometry/core/_grpc/_services/v0/repair_tools.py @@ -19,12 +19,7 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -"""Module containing the repair tools service implementation for v0. - -This module defines an abstract base class for a gRPC-based repair tools service. -The class provides a set of abstract methods for identifying and repairing various -geometry issues, such as split edges, extra edges, duplicate faces etc. -""" +"""Module containing the repair tools service implementation for v0.""" from google.protobuf.wrappers_pb2 import Int32Value import grpc @@ -393,7 +388,7 @@ def find_and_fix_short_edges(self, **kwargs): # noqa: D102 "repaired": response.repaired, "created_bodies_monikers": [], "modified_bodies_monikers": [], - "complete_command_response": serialized_tracker_response, + "tracker_response": serialized_tracker_response, } @protect_grpc @@ -420,7 +415,7 @@ def find_and_fix_extra_edges(self, **kwargs) -> dict: # noqa: D102 "repaired": response.repaired, "created_bodies_monikers": response.created_bodies_monikers, "modified_bodies_monikers": response.modified_bodies_monikers, - "complete_command_response": serialized_tracker_response, + "tracker_response": serialized_tracker_response, } @protect_grpc @@ -449,7 +444,7 @@ def find_and_fix_split_edges(self, **kwargs) -> dict: # noqa: D102 "repaired": response.repaired, "created_bodies_monikers": [], "modified_bodies_monikers": [], - "complete_command_response": serialized_tracker_response, + "tracker_response": serialized_tracker_response, } @protect_grpc @@ -476,7 +471,7 @@ def find_and_fix_simplify(self, **kwargs) -> dict: # noqa: D102 "repaired": response.repaired, "created_bodies_monikers": [], "modified_bodies_monikers": [], - "complete_command_response": serialized_tracker_response, + "tracker_response": serialized_tracker_response, } @protect_grpc @@ -514,7 +509,7 @@ def find_and_fix_stitch_faces(self, **kwargs) -> dict: # noqa: D102 "modified_bodies_monikers": response.modified_bodies_monikers, "found": response.found, "repaired": response.repaired, - "complete_command_response": serialized_tracker_response, + "tracker_response": serialized_tracker_response, } @protect_grpc @@ -522,7 +517,7 @@ def inspect_geometry(self, **kwargs) -> dict: # noqa: D102 from ansys.api.geometry.v0.repairtools_pb2 import InspectGeometryRequest # Create the request - assumes all inputs are valid and of the proper type - request = InspectGeometryRequest(bodies=kwargs.get("bodies", [])) + request = InspectGeometryRequest(bodies=kwargs.get("bodies")) # Call the gRPC service inspect_result_response = self.stub.InspectGeometry(request) @@ -535,7 +530,7 @@ def repair_geometry(self, **kwargs) -> dict: # noqa: D102 from ansys.api.geometry.v0.repairtools_pb2 import RepairGeometryRequest # Create the request - assumes all inputs are valid and of the proper type - request = RepairGeometryRequest(bodies=kwargs.get("bodies", [])) + request = RepairGeometryRequest(bodies=kwargs.get("bodies")) # Call the gRPC service response = self.stub.RepairGeometry(request) @@ -566,7 +561,9 @@ def fix_duplicate_faces(self, **kwargs) -> dict: # noqa: D102 # Return the response - formatted as a dictionary return { "tracker_response": serialized_tracker_response, - "repair_tracker_response": self.__serialize_message_response(response), + "success": response.result.success, + "created_bodies_monikers": response.result.created_bodies_monikers, + "modified_bodies_monikers": response.result.modified_bodies_monikers, } @protect_grpc @@ -590,7 +587,9 @@ def fix_missing_faces(self, **kwargs) -> dict: # noqa: D102 # Return the response - formatted as a dictionary return { "tracker_response": serialized_tracker_response, - "repair_tracker_response": self.__serialize_message_response(response), + "success": response.result.success, + "created_bodies_monikers": response.result.created_bodies_monikers, + "modified_bodies_monikers": response.result.modified_bodies_monikers, } @protect_grpc @@ -614,7 +613,9 @@ def fix_inexact_edges(self, **kwargs) -> dict: # noqa: D102 # Return the response - formatted as a dictionary return { "tracker_response": serialized_tracker_response, - "repair_tracker_response": self.__serialize_message_response(response), + "success": response.result.success, + "created_bodies_monikers": response.result.created_bodies_monikers, + "modified_bodies_monikers": response.result.modified_bodies_monikers, } @protect_grpc @@ -636,7 +637,9 @@ def fix_extra_edges(self, **kwargs) -> dict: # noqa: D102 # Return the response - formatted as a dictionary return { "tracker_response": serialized_tracker_response, - "repair_tracker_response": self.__serialize_message_response(response), + "success": response.result.success, + "created_bodies_monikers": response.result.created_bodies_monikers, + "modified_bodies_monikers": response.result.modified_bodies_monikers, } @protect_grpc @@ -658,7 +661,9 @@ def fix_short_edges(self, **kwargs) -> dict: # noqa: D102 # Return the response - formatted as a dictionary return { "tracker_response": serialized_tracker_response, - "repair_tracker_response": self.__serialize_message_response(response), + "success": response.result.success, + "created_bodies_monikers": response.result.created_bodies_monikers, + "modified_bodies_monikers": response.result.modified_bodies_monikers, } @protect_grpc @@ -680,7 +685,9 @@ def fix_small_faces(self, **kwargs) -> dict: # noqa: D102 # Return the response - formatted as a dictionary return { "tracker_response": serialized_tracker_response, - "repair_tracker_response": self.__serialize_message_response(response), + "success": response.result.success, + "created_bodies_monikers": response.result.created_bodies_monikers, + "modified_bodies_monikers": response.result.modified_bodies_monikers, } @protect_grpc @@ -702,7 +709,9 @@ def fix_split_edges(self, **kwargs) -> dict: # noqa: D102 # Return the response - formatted as a dictionary return { "tracker_response": serialized_tracker_response, - "repair_tracker_response": self.__serialize_message_response(response), + "success": response.result.success, + "created_bodies_monikers": response.result.created_bodies_monikers, + "modified_bodies_monikers": response.result.modified_bodies_monikers, } @protect_grpc @@ -726,7 +735,9 @@ def fix_stitch_faces(self, **kwargs) -> dict: # noqa: D102 # Return the response - formatted as a dictionary return { "tracker_response": serialized_tracker_response, - "repair_tracker_response": self.__serialize_message_response(response), + "success": response.result.success, + "created_bodies_monikers": response.result.created_bodies_monikers, + "modified_bodies_monikers": response.result.modified_bodies_monikers, } @protect_grpc @@ -750,7 +761,9 @@ def fix_unsimplified_faces(self, **kwargs) -> dict: # noqa: D102 # Return the response - formatted as a dictionary return { "tracker_response": serialized_tracker_response, - "repair_tracker_response": self.__serialize_message_response(response), + "success": response.result.success, + "created_bodies_monikers": response.result.created_bodies_monikers, + "modified_bodies_monikers": response.result.modified_bodies_monikers, } @protect_grpc @@ -774,7 +787,9 @@ def fix_interference(self, **kwargs) -> dict: # noqa: D102 # Return the response - formatted as a dictionary return { "tracker_response": serialized_tracker_response, - "repair_tracker_response": self.__serialize_message_response(response), + "success": response.result.success, + "created_bodies_monikers": response.result.created_bodies_monikers, + "modified_bodies_monikers": response.result.modified_bodies_monikers, } def __serialize_inspect_result_response(self, response) -> dict: # noqa: D102 @@ -830,10 +845,3 @@ def serialize_issue(issue): for body_issues in response.issues_by_body ] } - - def __serialize_message_response(self, response): - return { - "success": response.result.success, - "created_bodies_monikers": response.result.created_bodies_monikers, - "modified_bodies_monikers": response.result.modified_bodies_monikers, - } diff --git a/src/ansys/geometry/core/_grpc/_services/v1/conversions.py b/src/ansys/geometry/core/_grpc/_services/v1/conversions.py index aa55dd7d12..a8bb1ef596 100644 --- a/src/ansys/geometry/core/_grpc/_services/v1/conversions.py +++ b/src/ansys/geometry/core/_grpc/_services/v1/conversions.py @@ -44,6 +44,7 @@ CurveGeometry as GRPCCurveGeometry, DrivingDimensionEntity as GRPCDrivingDimension, EdgeTessellation as GRPCEdgeTessellation, + EnhancedRepairToolMessage as GRPCEnhancedRepairToolResponse, Geometries as GRPCGeometries, Knot as GRPCKnot, MaterialEntity as GRPCMaterial, @@ -1349,6 +1350,38 @@ def from_angle_to_grpc_quantity(input: "Measurement") -> GRPCQuantity: return GRPCQuantity(value_in_geometry_units=input.value.m_as(DEFAULT_UNITS.SERVER_ANGLE)) +def from_area_to_grpc_quantity(input: "Measurement") -> GRPCQuantity: + """Convert a ``Measurement`` containing an area to a gRPC quantity. + + Parameters + ---------- + input : Measurement + Source measurement data. + + Returns + ------- + GRPCQuantity + Converted gRPC quantity. + """ + return GRPCQuantity(value_in_geometry_units=input.value.m_as(DEFAULT_UNITS.SERVER_AREA)) + + +def from_volume_to_grpc_quantity(input: "Measurement") -> GRPCQuantity: + """Convert a ``Measurement`` containing a volume to a gRPC quantity. + + Parameters + ---------- + input : Measurement + Source measurement data. + + Returns + ------- + GRPCQuantity + Converted gRPC quantity. + """ + return GRPCQuantity(value_in_geometry_units=input.value.m_as(DEFAULT_UNITS.SERVER_VOLUME)) + + def _nurbs_curves_compatibility(backend_version: "semver.Version", grpc_geometries: GRPCGeometries): """Check if the backend version is compatible with NURBS curves in sketches. @@ -1568,3 +1601,93 @@ def get_tracker_response_with_created_bodies(response) -> dict: "created_bodies", [] ) return serialized_response + + +def serialize_repair_command_response(response: GRPCEnhancedRepairToolResponse) -> dict: + """Serialize a EnhancedRepairToolResponse object into a dictionary. + + Parameters + ---------- + response : GRPCEnhancedRepairToolResponse + The gRPC EnhancedRepairToolResponse object to serialize. + A dictionary representation of the EnhancedRepairToolResponse object. + """ + return { + "success": response.tracked_command_response.command_response.success, + "found": response.found, + "repaired": response.repaired, + "complete_command_response": serialize_tracked_command_response(response.tracked_changes), + "created_bodies_monikers": [ + created_body.id for created_body in response.tracked_changes.get("created_bodies", []) + ], + "modified_bodies_monikers": [ + modified_body.id + for modified_body in response.tracked_changes.get("modified_bodies", []) + ], + "deleted_bodies_monikers": [ + deleted_body.id for deleted_body in response.tracked_changes.get("deleted_bodies", []) + ], + } + + +def response_problem_area_for_body(response) -> dict: + """Get a dictionary response from problem areas for a body. + + Parameters + ---------- + response + The response to convert. + + Returns + ------- + dict + A dictionary representation of the ProblemAreaForBody object. + """ + return { + "problems": [ + {"id": res.problem_area_id, "bodies": [body.id for body in res.body_ids]} + for res in response.result + ] + } + + +def response_problem_area_for_face(response) -> dict: + """Get a dictionary response from problem areas for a face. + + Parameters + ---------- + response + The response to convert. + + Returns + ------- + dict + A dictionary representation of the ProblemAreaForFace object. + """ + return { + "problems": [ + {"id": res.problem_area_id, "faces": [face.id for face in res.face_ids]} + for res in response.result + ] + } + + +def response_problem_area_for_edge(response) -> dict: + """Get a dictionary response from problem areas for an edge. + + Parameters + ---------- + response + The response to convert. + + Returns + ------- + dict + A dictionary representation of the ProblemAreaForEdge object. + """ + return { + "problems": [ + {"id": res.problem_area_id, "edges": [edge.id for edge in res.edge_ids]} + for res in response.result + ] + } diff --git a/src/ansys/geometry/core/_grpc/_services/v1/repair_tools.py b/src/ansys/geometry/core/_grpc/_services/v1/repair_tools.py index 4c95a9a041..c2f784ba2b 100644 --- a/src/ansys/geometry/core/_grpc/_services/v1/repair_tools.py +++ b/src/ansys/geometry/core/_grpc/_services/v1/repair_tools.py @@ -26,11 +26,25 @@ from ansys.geometry.core.errors import protect_grpc from ..base.repair_tools import GRPCRepairToolsService - - -class GRPCRepairToolsServiceV1(GRPCRepairToolsService): # pragma: no cover +from .conversions import ( + build_grpc_id, + from_angle_to_grpc_quantity, + from_area_to_grpc_quantity, + from_length_to_grpc_quantity, + response_problem_area_for_body, + response_problem_area_for_edge, + response_problem_area_for_face, + serialize_repair_command_response, +) + + +class GRPCRepairToolsServiceV1(GRPCRepairToolsService): # noqa: D102 """Repair tools service for gRPC communication with the Geometry server. + This class provides methods to interact with the Geometry server's + Repair Tools service. It is specifically designed for the v1 version + of the Geometry API. + Parameters ---------- channel : grpc.Channel @@ -38,115 +52,496 @@ class GRPCRepairToolsServiceV1(GRPCRepairToolsService): # pragma: no cover """ @protect_grpc - def __init__(self, channel: grpc.Channel): # noqa: D102 - from ansys.api.geometry.v1.repairtools_pb2_grpc import RepairToolsStub + def __init__(self, channel: grpc.Channel): + from ansys.api.discovery.v1.operations.repair_pb2_grpc import RepairStub - self.stub = RepairToolsStub(channel) + self.stub = RepairStub(channel) @protect_grpc def find_split_edges(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FindSplitEdgesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FindSplitEdgesRequest( + body_or_face_ids=[build_grpc_id(item) for item in kwargs["bodies_or_faces"]], + angle=from_angle_to_grpc_quantity(kwargs["angle"]) + if kwargs["angle"] is not None + else None, + distance=from_length_to_grpc_quantity(kwargs["distance"]) + if kwargs["distance"] is not None + else None, + ) + + # Call the gRPC service + response = self.stub.FindSplitEdges(request) + + # Format and return the response as a dictionary + return response_problem_area_for_edge(response) @protect_grpc def find_extra_edges(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FindExtraEdgesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FindExtraEdgesRequest( + selection_id=[build_grpc_id(item) for item in kwargs["selection"]] + ) + + # Return the response - formatted as a dictionary + response = self.stub.FindExtraEdges(request) + + # Return the response - formatted as a dictionary + return response_problem_area_for_edge(response) @protect_grpc def find_inexact_edges(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FindInexactEdgesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FindInexactEdgesRequest( + selection_id=[build_grpc_id(item) for item in kwargs["selection"]] + ) + + # Call the gRPC service + response = self.stub.FindInexactEdges(request) + + # Return the response - formatted as a dictionary + return response_problem_area_for_edge(response) @protect_grpc def find_short_edges(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FindShortEdgesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FindShortEdgesRequest( + selection_id=[build_grpc_id(item) for item in kwargs["selection"]], + max_edge_length=from_length_to_grpc_quantity(kwargs["length"]), + ) + + # Call the gRPC service + response = self.stub.FindShortEdges(request) + + return response_problem_area_for_edge(response) @protect_grpc def find_duplicate_faces(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FindDuplicateFacesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FindDuplicateFacesRequest( + face_ids=[build_grpc_id(face) for face in kwargs["faces"]] + ) + + # Call the gRPC service + response = self.stub.FindDuplicateFaces(request) + + # Return the response - formatted as a dictionary + return response_problem_area_for_face(response) @protect_grpc def find_missing_faces(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FindMissingFacesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FindMissingFacesRequest( + face_ids=[build_grpc_id(face) for face in kwargs["faces"]], + angle=from_angle_to_grpc_quantity(kwargs["angle"]) + if kwargs["angle"] is not None + else None, + distance=from_length_to_grpc_quantity(kwargs["distance"]) + if kwargs["distance"] is not None + else None, + ) + + # Call the gRPC service + response = self.stub.FindMissingFaces(request) + + # Return the response - formatted as a dictionary + return response_problem_area_for_face(response) @protect_grpc def find_small_faces(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FindSmallFacesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FindSmallFacesRequest( + selection_id=[build_grpc_id(item) for item in kwargs["selection"]], + area=from_area_to_grpc_quantity(kwargs["area"]) if kwargs["area"] is not None else None, + width=from_length_to_grpc_quantity(kwargs["width"]) + if kwargs["width"] is not None + else None, + ) + + # Call the gRPC service + response = self.stub.FindSmallFaces(request) + + # Return the response - formatted as a dictionary + return response_problem_area_for_face(response) @protect_grpc def find_stitch_faces(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FindStitchFacesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FindStitchFacesRequest( + face_ids=[build_grpc_id(face) for face in kwargs["faces"]], + maximum_distance=from_length_to_grpc_quantity(kwargs["distance"]) + if kwargs["distance"] is not None + else None, + ) + + # Call the gRPC service + response = self.stub.FindStitchFaces(request) + + # Return the response - formatted as a dictionary + return response_problem_area_for_body(response) @protect_grpc def find_simplify(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FindAdjustSimplifyRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FindAdjustSimplifyRequest( + selection_id=[build_grpc_id(item) for item in kwargs["selection"]] + ) + + # Call the gRPC service + response = self.stub.FindAdjustSimplify(request) + + # Return the response - formatted as a dictionary + return response_problem_area_for_body(response) @protect_grpc def find_interferences(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FindInterferenceRequest + from google.protobuf.wrappers_pb2 import BoolValue + + # Create the request - assumes all inputs are valid and of the proper type + request = FindInterferenceRequest( + bodY_ids=[build_grpc_id(body) for body in kwargs["bodies"]], + cut_smaller_body=BoolValue(value=kwargs["cut_smaller_body"]), + ) + + # Call the gRPC service + response = self.stub.FindInterference(request) + + # Return the response - formatted as a dictionary + return response_problem_area_for_body(response) @protect_grpc - def find_and_fix_short_edges(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + def find_and_fix_short_edges(self, **kwargs): # noqa: D102 + from ansys.api.discovery.v1.operations.repair_pb2 import FindShortEdgesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FindShortEdgesRequest( + selection_id=[build_grpc_id(item) for item in kwargs["selection"]], + max_edge_length=from_length_to_grpc_quantity(kwargs["length"]), + comprehensive=kwargs["comprehensive_result"], + ) + + # Call the gRPC service + response = self.stub.FindAndFixShortEdges(request) + + return serialize_repair_command_response(response) @protect_grpc def find_and_fix_extra_edges(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FindExtraEdgesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FindExtraEdgesRequest( + selection_id=[build_grpc_id(item) for item in kwargs["selection"]], + comprehensive=kwargs["comprehensive_result"], + ) + + # Call the gRPC service + response = self.stub.FindAndFixExtraEdges(request) + + return serialize_repair_command_response(response) @protect_grpc def find_and_fix_split_edges(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FindSplitEdgesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FindSplitEdgesRequest( + body_or_face_ids=[build_grpc_id(item) for item in kwargs["bodies_or_faces"]], + distance=from_length_to_grpc_quantity(kwargs["length"]), + comprehensive=kwargs["comprehensive_result"], + ) + + # Call the gRPC service + response = self.stub.FindAndFixSplitEdges(request) + + return serialize_repair_command_response(response) @protect_grpc def find_and_fix_simplify(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FindAdjustSimplifyRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FindAdjustSimplifyRequest( + selection_id=[build_grpc_id(item) for item in kwargs["selection"]], + comprehensive=kwargs["comprehensive_result"], + ) + + # Call the gRPC service + response = self.stub.FindAndSimplify(request) + + return serialize_repair_command_response(response) @protect_grpc def find_and_fix_stitch_faces(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FindStitchFacesRequest + from google.protobuf.wrappers_pb2 import BoolValue + + # Create the request - assumes all inputs are valid and of the proper type + request = FindStitchFacesRequest( + face_ids=[build_grpc_id(item) for item in kwargs["body_ids"]], + maximum_distance=from_length_to_grpc_quantity(kwargs["max_distance"]) + if kwargs["max_distance"] is not None + else None, + allow_multiple_bodies=BoolValue(value=kwargs["allow_multiple_bodies"]), + maintain_components=BoolValue(value=kwargs["maintain_components"]), + check_for_coincidence=BoolValue(value=kwargs["check_for_coincidence"]), + comprehensive=kwargs["comprehensive_result"], + ) + + # Call the gRPC service + response = self.stub.FindAndFixStitchFaces(request) + + return serialize_repair_command_response(response) @protect_grpc def inspect_geometry(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import InspectGeometryRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = InspectGeometryRequest( + body_ids=[build_grpc_id(body) for body in kwargs.get("bodies")] + ) + + # Call the gRPC service + inspect_result_response = self.stub.InspectGeometry(request) + + # Serialize and return the response + return self.__serialize_inspect_result_response(inspect_result_response) @protect_grpc def repair_geometry(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import RepairGeometryRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = RepairGeometryRequest( + body_ids=[build_grpc_id(body) for body in kwargs.get("bodies")] + ) + + # Call the gRPC service + response = self.stub.RepairGeometry(request) + + # Return the response - formatted as a dictionary + return serialize_repair_command_response(response) @protect_grpc def fix_duplicate_faces(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FixDuplicateFacesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FixDuplicateFacesRequest( + duplicate_face_problem_area_id=int(kwargs["duplicate_face_problem_area_id"]), + ) + + # Call the gRPC service + response = self.stub.FixDuplicateFaces(request) + + # Return the response - formatted as a dictionary + return serialize_repair_command_response(response) @protect_grpc def fix_missing_faces(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FixMissingFacesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FixMissingFacesRequest( + missing_face_problem_area_id=int(kwargs["missing_face_problem_area_id"]), + ) + + # Call the gRPC service + response = self.stub.FixMissingFaces(request) + + # Return the response - formatted as a dictionary + return serialize_repair_command_response(response) @protect_grpc def fix_inexact_edges(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FixInexactEdgesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FixInexactEdgesRequest( + inexact_edge_problem_area_id=int(kwargs["inexact_edge_problem_area_id"]), + ) + + # Call the gRPC service + response = self.stub.FixInexactEdges(request) + + # Return the response - formatted as a dictionary + return serialize_repair_command_response(response) @protect_grpc def fix_extra_edges(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FixExtraEdgesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FixExtraEdgesRequest( + extra_edge_problem_area_id=int(kwargs["extra_edge_problem_area_id"]), + ) + + # Call the gRPC service + response = self.stub.FixExtraEdges(request) + + # Return the response - formatted as a dictionary + return serialize_repair_command_response(response) @protect_grpc def fix_short_edges(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FixShortEdgesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FixShortEdgesRequest( + short_edge_problem_area_id=int(kwargs["short_edge_problem_area_id"]), + ) + + # Call the gRPC service + response = self.stub.FixShortEdges(request) + + # Return the response - formatted as a dictionary + return serialize_repair_command_response(response) @protect_grpc def fix_small_faces(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FixSmallFacesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FixSmallFacesRequest( + small_face_problem_area_id=int(kwargs["small_face_problem_area_id"]), + ) + + # Call the gRPC service + response = self.stub.FixSmallFaces(request) + + # Return the response - formatted as a dictionary + return serialize_repair_command_response(response) @protect_grpc def fix_split_edges(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FixSplitEdgesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FixSplitEdgesRequest( + split_edge_problem_area_id=int(kwargs["split_edge_problem_area_id"]), + ) + + # Call the gRPC service + response = self.stub.FixSplitEdges(request) + + # Return the response - formatted as a dictionary + return serialize_repair_command_response(response) @protect_grpc def fix_stitch_faces(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FixStitchFacesRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FixStitchFacesRequest( + stitch_face_problem_area_id=int(kwargs["stitch_face_problem_area_id"]), + ) + + # Call the gRPC service + response = self.stub.FixStitchFaces(request) + + # Return the response - formatted as a dictionary + return serialize_repair_command_response(response) @protect_grpc def fix_unsimplified_faces(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FixAdjustSimplifyRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FixAdjustSimplifyRequest( + adjust_simplify_problem_area_id=int(kwargs["adjust_simplify_problem_area_id"]), + ) + + # Call the gRPC service + response = self.stub.FixAdjustSimplify(request) + + # Return the response - formatted as a dictionary + return serialize_repair_command_response(response) @protect_grpc def fix_interference(self, **kwargs) -> dict: # noqa: D102 - raise NotImplementedError + from ansys.api.discovery.v1.operations.repair_pb2 import FixInterferenceRequest + + # Create the request - assumes all inputs are valid and of the proper type + request = FixInterferenceRequest( + interference_problem_area_id=int(kwargs["interference_problem_area_id"]), + ) + + # Call the gRPC service + response = self.stub.FixInterference(request) + + # Return the response - formatted as a dictionary + return serialize_repair_command_response(response) + + def __serialize_inspect_result_response(self, response) -> dict: # noqa: D102 + def serialize_body(body): + return { + "id": body.id, + "name": body.name, + "can_suppress": body.can_suppress, + "transform_to_master": { + "m00": body.transform_to_master.m00, + "m11": body.transform_to_master.m11, + "m22": body.transform_to_master.m22, + "m33": body.transform_to_master.m33, + }, + "master_id": body.master_id, + "parent_id": body.parent_id, + } + + def serialize_face(face): + return { + "id": face.id, + "surface_type": face.surface_type, + "export_id": face.export_id, + "is_reversed": getattr(face, "is_reversed", False), + "parent_id": face.parent_id.id, + } + + def serialize_edge(edge): + return { + "id": edge.id, + "curve_type": edge.curve_type, + "export_id": edge.export_id, + "length": edge.length, + "owner_id": edge.owner_id, + "parent": serialize_body(edge.parent) if hasattr(edge, "parent") else None, + } + + def serialize_issue(issue): + return { + "message_type": issue.message_type, + "message_id": issue.message_id, + "message": issue.message, + "faces": [serialize_face(f) for f in issue.faces], + "edges": [serialize_edge(e) for e in issue.edges], + } + + return { + "issues_by_body": [ + { + "body": serialize_body(body_issues.body), + "issues": [serialize_issue(i) for i in body_issues.issues], + } + for body_issues in response.issues_by_body + ] + } diff --git a/src/ansys/geometry/core/tools/problem_areas.py b/src/ansys/geometry/core/tools/problem_areas.py index cf1b1a7a8d..253c0ac63f 100644 --- a/src/ansys/geometry/core/tools/problem_areas.py +++ b/src/ansys/geometry/core/tools/problem_areas.py @@ -32,7 +32,10 @@ get_design_from_face, ) from ansys.geometry.core.misc.checks import check_type_all_elements_in_iterable -from ansys.geometry.core.tools.repair_tool_message import RepairToolMessage +from ansys.geometry.core.tools.repair_tool_message import ( + RepairToolMessage, + create_repair_message_from_response, +) if TYPE_CHECKING: # pragma: no cover from ansys.geometry.core.designer.body import Body @@ -141,7 +144,7 @@ def fix(self) -> RepairToolMessage: else: parent_design._update_from_tracker(response.get("tracker_response")) - message = self.build_repair_tool_message(response.get("repair_tracker_response")) + message = create_repair_message_from_response(response) return message @@ -195,7 +198,7 @@ def fix(self) -> RepairToolMessage: else: parent_design._update_from_tracker(response.get("tracker_response")) - message = self.build_repair_tool_message(response.get("repair_tracker_response")) + message = create_repair_message_from_response(response) return message @@ -250,7 +253,7 @@ def fix(self) -> RepairToolMessage: else: parent_design._update_from_tracker(response.get("tracker_response")) - message = self.build_repair_tool_message(response.get("repair_tracker_response")) + message = create_repair_message_from_response(response) return message @@ -304,7 +307,7 @@ def fix(self) -> RepairToolMessage: else: parent_design._update_from_tracker(response.get("tracker_response")) - message = self.build_repair_tool_message(response.get("repair_tracker_response")) + message = create_repair_message_from_response(response) return message @@ -358,7 +361,7 @@ def fix(self) -> RepairToolMessage: else: parent_design._update_from_tracker(response.get("tracker_response")) - message = self.build_repair_tool_message(response.get("repair_tracker_response")) + message = create_repair_message_from_response(response) return message @@ -412,7 +415,7 @@ def fix(self) -> RepairToolMessage: else: parent_design._update_from_tracker(response.get("tracker_response")) - message = self.build_repair_tool_message(response.get("repair_tracker_response")) + message = create_repair_message_from_response(response) return message @@ -466,7 +469,7 @@ def fix(self) -> RepairToolMessage: else: parent_design._update_from_tracker(response.get("tracker_response")) - message = self.build_repair_tool_message(response.get("repair_tracker_response")) + message = create_repair_message_from_response(response) return message @@ -520,7 +523,7 @@ def fix(self) -> RepairToolMessage: else: parent_design._update_from_tracker(response.get("tracker_response")) - message = self.build_repair_tool_message(response.get("repair_tracker_response")) + message = create_repair_message_from_response(response) return message @@ -569,7 +572,7 @@ def fix(self) -> RepairToolMessage: else: parent_design._update_from_tracker(response.get("tracker_response")) - message = self.build_repair_tool_message(response.get("repair_tracker_response")) + message = create_repair_message_from_response(response) return message @@ -625,7 +628,7 @@ def fix(self) -> RepairToolMessage: ## The tool does not return the created or modified objects. ## https://github.com/ansys/pyansys-geometry/issues/1319 - message = RepairToolMessage(response.get("repair_tracker_response").get("success"), [], []) + message = RepairToolMessage(response.get("success"), [], []) return message diff --git a/src/ansys/geometry/core/tools/repair_tool_message.py b/src/ansys/geometry/core/tools/repair_tool_message.py index ea1725a2bb..ca52e6cd90 100644 --- a/src/ansys/geometry/core/tools/repair_tool_message.py +++ b/src/ansys/geometry/core/tools/repair_tool_message.py @@ -92,3 +92,26 @@ def found(self) -> int: def repaired(self) -> int: """Number of problem areas repaired during the repair operation.""" return self._repaired + + +def create_repair_message_from_response(response) -> "RepairToolMessage": + """Create a RepairToolMessage from a serialized response. + + Parameters + ---------- + response : serialized response + The serialized response object containing repair tool information. + + Returns + ------- + RepairToolMessage + An instance of RepairToolMessage populated with data from the response. + """ + return RepairToolMessage( + success=response.get("success"), + created_bodies=response.get("created_bodies_monikers", []), + modified_bodies=response.get("modified_bodies_monikers", []), + deleted_bodies=response.get("deleted_bodies_monikers", []), + found=response.get("found", -1), + repaired=response.get("repaired", -1), + ) diff --git a/src/ansys/geometry/core/tools/repair_tools.py b/src/ansys/geometry/core/tools/repair_tools.py index 92a4daee65..2a76abd612 100644 --- a/src/ansys/geometry/core/tools/repair_tools.py +++ b/src/ansys/geometry/core/tools/repair_tools.py @@ -53,7 +53,10 @@ StitchFaceProblemAreas, UnsimplifiedFaceProblemAreas, ) -from ansys.geometry.core.tools.repair_tool_message import RepairToolMessage +from ansys.geometry.core.tools.repair_tool_message import ( + RepairToolMessage, + create_repair_message_from_response, +) from ansys.geometry.core.typing import Real if TYPE_CHECKING: # pragma: no cover @@ -586,10 +589,10 @@ def find_and_fix_short_edges( if not pyansys_geometry.USE_TRACKER_TO_UPDATE_DESIGN: parent_design._update_design_inplace() else: - parent_design._update_from_tracker(response["complete_command_response"]) + parent_design._update_from_tracker(response["tracker_response"]) # Build the response message - return self.__build_repair_tool_message(response) + return create_repair_message_from_response(response) @min_backend_version(25, 2, 0) def find_and_fix_extra_edges( @@ -638,10 +641,10 @@ def find_and_fix_extra_edges( if not pyansys_geometry.USE_TRACKER_TO_UPDATE_DESIGN: parent_design._update_design_inplace() else: - parent_design._update_from_tracker(response["complete_command_response"]) + parent_design._update_from_tracker(response["tracker_response"]) # Build the response message - return self.__build_repair_tool_message(response) + return create_repair_message_from_response(response) @min_backend_version(25, 2, 0) def find_and_fix_split_edges( @@ -707,10 +710,10 @@ def find_and_fix_split_edges( if not pyansys_geometry.USE_TRACKER_TO_UPDATE_DESIGN: parent_design._update_design_inplace() else: - parent_design._update_from_tracker(response["complete_command_response"]) + parent_design._update_from_tracker(response["tracker_response"]) # Build the response message - return self.__build_repair_tool_message(response) + return create_repair_message_from_response(response) @min_backend_version(25, 2, 0) def find_and_fix_simplify( @@ -760,10 +763,10 @@ def find_and_fix_simplify( if not pyansys_geometry.USE_TRACKER_TO_UPDATE_DESIGN: parent_design._update_design_inplace() else: - parent_design._update_from_tracker(response["complete_command_response"]) + parent_design._update_from_tracker(response["tracker_response"]) # Build the response message - return self.__build_repair_tool_message(response) + return create_repair_message_from_response(response) @min_backend_version(25, 2, 0) def find_and_fix_stitch_faces( @@ -834,10 +837,10 @@ def find_and_fix_stitch_faces( if not pyansys_geometry.USE_TRACKER_TO_UPDATE_DESIGN: parent_design._update_design_inplace() else: - parent_design._update_from_tracker(response["complete_command_response"]) + parent_design._update_from_tracker(response["tracker_response"]) # Build the response message - return self.__build_repair_tool_message(response) + return create_repair_message_from_response(response) @min_backend_version(25, 2, 0) def inspect_geometry(self, bodies: list["Body"] = None) -> list[InspectResult]: @@ -929,26 +932,4 @@ def repair_geometry(self, bodies: list["Body"] = None) -> RepairToolMessage: body_ids=[] if bodies is None else [b.id for b in bodies], ) - return self.__build_repair_tool_message(response) - - def __build_repair_tool_message(self, response: dict) -> RepairToolMessage: - """Build a repair tool message from the service response. - - Parameters - ---------- - response : dict - The response from the service containing information about the repair operation. - - Returns - ------- - RepairToolMessage - A message containing the success status, created bodies, modified bodies, - number of found problem areas, and number of repaired problem areas. - """ - return RepairToolMessage( - success=response.get("success"), - created_bodies=response.get("created_bodies_monikers", []), - modified_bodies=response.get("modified_bodies_monikers", []), - found=response.get("found", -1), - repaired=response.get("repaired", -1), - ) + return create_repair_message_from_response(response)