Skip to content

Commit afb33f7

Browse files
jacobrkerstetterpre-commit-ci[bot]pyansys-ci-botRobPasMue
authored
feat: grpc rearchitecutre - components model (#2263)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: pyansys-ci-bot <[email protected]> Co-authored-by: Roberto Pastor Muela <[email protected]>
1 parent 86bbb5c commit afb33f7

File tree

9 files changed

+513
-93
lines changed

9 files changed

+513
-93
lines changed

doc/changelog.d/2263.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Grpc rearchitecutre - components model

src/ansys/geometry/core/_grpc/_services/_service.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from .base.beams import GRPCBeamsService
2929
from .base.bodies import GRPCBodyService
3030
from .base.commands import GRPCCommandsService
31+
from .base.components import GRPCComponentsService
3132
from .base.coordinate_systems import GRPCCoordinateSystemService
3233
from .base.curves import GRPCCurvesService
3334
from .base.dbuapplication import GRPCDbuApplicationService
@@ -88,6 +89,7 @@ def __init__(self, channel: grpc.Channel, version: GeometryApiProtos | str | Non
8889
self._beams = None
8990
self._bodies = None
9091
self._commands = None
92+
self._components = None
9193
self._coordinate_systems = None
9294
self._curves = None
9395
self._dbu_application = None
@@ -234,6 +236,32 @@ def commands(self) -> GRPCCommandsService:
234236

235237
return self._commands
236238

239+
@property
240+
def components(self) -> GRPCComponentsService:
241+
"""
242+
Get the components service for the specified version.
243+
244+
Returns
245+
-------
246+
GRPCComponentsService
247+
The components service for the specified version.
248+
"""
249+
if not self._components:
250+
# Import the appropriate components service based on the version
251+
from .v0.components import GRPCComponentsServiceV0
252+
from .v1.components import GRPCComponentsServiceV1
253+
254+
if self.version == GeometryApiProtos.V0:
255+
self._components = GRPCComponentsServiceV0(self.channel)
256+
elif self.version == GeometryApiProtos.V1: # pragma: no cover
257+
# V1 is not implemented yet
258+
self._components = GRPCComponentsServiceV1(self.channel)
259+
else: # pragma: no cover
260+
# This should never happen as the version is set in the constructor
261+
raise ValueError(f"Unsupported version: {self.version}")
262+
263+
return self._components
264+
237265
@property
238266
def coordinate_systems(self) -> GRPCCoordinateSystemService:
239267
"""
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Copyright (C) 2023 - 2025 ANSYS, Inc. and/or its affiliates.
2+
# SPDX-License-Identifier: MIT
3+
#
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
"""Module containing the components service implementation (abstraction layer)."""
23+
24+
from abc import ABC, abstractmethod
25+
26+
import grpc
27+
28+
29+
class GRPCComponentsService(ABC): # pragma: no cover
30+
"""Components service for gRPC communication with the Geometry server.
31+
32+
Parameters
33+
----------
34+
channel : grpc.Channel
35+
The gRPC channel to the server.
36+
"""
37+
38+
def __init__(self, channel: grpc.Channel):
39+
"""Initialize the GRPCComponentsService class."""
40+
41+
@abstractmethod
42+
def create(self, **kwargs) -> dict:
43+
"""Create a component."""
44+
pass
45+
46+
@abstractmethod
47+
def set_name(self, **kwargs) -> dict:
48+
"""Set the name of a component."""
49+
pass
50+
51+
@abstractmethod
52+
def set_placement(self, **kwargs) -> dict:
53+
"""Set the placement of a component."""
54+
pass
55+
56+
@abstractmethod
57+
def set_shared_topology(self, **kwargs) -> dict:
58+
"""Set the shared topology of a component."""
59+
pass
60+
61+
@abstractmethod
62+
def delete(self, **kwargs) -> dict:
63+
"""Delete a component."""
64+
pass
65+
66+
@abstractmethod
67+
def import_groups(self, **kwargs) -> dict:
68+
"""Import groups from a component."""
69+
pass
70+
71+
@abstractmethod
72+
def make_independent(self, **kwargs) -> dict:
73+
"""Make a component independent."""
74+
pass

src/ansys/geometry/core/_grpc/_services/v0/beams.py

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,14 @@
2626
from ansys.geometry.core.errors import protect_grpc
2727

2828
from ..base.beams import GRPCBeamsService
29-
from .conversions import from_point3d_to_grpc_point
29+
from ..base.conversions import to_distance
30+
from .conversions import (
31+
from_grpc_curve_to_curve,
32+
from_grpc_frame_to_frame,
33+
from_grpc_material_to_material,
34+
from_grpc_point_to_point3d,
35+
from_point3d_to_grpc_point,
36+
)
3037

3138

3239
class GRPCBeamsServiceV0(GRPCBeamsService):
@@ -83,6 +90,8 @@ def create_descriptive_beam_segments(self, **kwargs) -> dict: # noqa: D102
8390
from ansys.api.geometry.v0.commands_pb2 import CreateBeamSegmentsRequest
8491
from ansys.api.geometry.v0.models_pb2 import Line
8592

93+
from ansys.geometry.core.shapes.parameterization import Interval, ParamUV
94+
8695
# Create the gRPC Line objects
8796
lines = []
8897
for segment in kwargs["segments"]:
@@ -105,7 +114,57 @@ def create_descriptive_beam_segments(self, **kwargs) -> dict: # noqa: D102
105114

106115
# Return the response - formatted as a dictionary
107116
return {
108-
"created_beams": resp.created_beams,
117+
"created_beams": [
118+
{
119+
"cross_section": {
120+
"section_anchor": beam.cross_section.section_anchor,
121+
"section_angle": beam.cross_section.section_angle,
122+
"section_frame": from_grpc_frame_to_frame(beam.cross_section.section_frame),
123+
"section_profile": [
124+
[
125+
{
126+
"geometry": from_grpc_curve_to_curve(curve.curve),
127+
"start": from_grpc_point_to_point3d(curve.start),
128+
"end": from_grpc_point_to_point3d(curve.end),
129+
"interval": Interval(curve.interval_start, curve.interval_end),
130+
"length": to_distance(curve.length).value,
131+
}
132+
for curve in curve_list.curves
133+
]
134+
for curve_list in beam.cross_section.section_profile
135+
],
136+
},
137+
"properties": {
138+
"area": beam.properties.area,
139+
"centroid": ParamUV(beam.properties.centroid_x, beam.properties.centroid_y),
140+
"warping_constant": beam.properties.warping_constant,
141+
"ixx": beam.properties.ixx,
142+
"ixy": beam.properties.ixy,
143+
"iyy": beam.properties.iyy,
144+
"shear_center": ParamUV(
145+
beam.properties.shear_center_x, beam.properties.shear_center_y
146+
),
147+
"torsional_constant": beam.properties.torsional_constant,
148+
},
149+
"id": beam.id.id,
150+
"start": from_grpc_point_to_point3d(beam.shape.start),
151+
"end": from_grpc_point_to_point3d(beam.shape.end),
152+
"name": beam.name,
153+
"is_deleted": beam.is_deleted,
154+
"is_reversed": beam.is_reversed,
155+
"is_rigid": beam.is_rigid,
156+
"material": from_grpc_material_to_material(beam.material),
157+
"shape": {
158+
"geometry": from_grpc_curve_to_curve(beam.shape.curve),
159+
"start": from_grpc_point_to_point3d(beam.shape.start),
160+
"end": from_grpc_point_to_point3d(beam.shape.end),
161+
"interval": Interval(beam.shape.interval_start, beam.shape.interval_end),
162+
"length": to_distance(beam.shape.length).value,
163+
},
164+
"beam_type": beam.type,
165+
}
166+
for beam in resp.created_beams
167+
],
109168
}
110169

111170
@protect_grpc
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
# Copyright (C) 2023 - 2025 ANSYS, Inc. and/or its affiliates.
2+
# SPDX-License-Identifier: MIT
3+
#
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
"""Module containing the components service implementation for v0."""
23+
24+
import grpc
25+
26+
from ansys.geometry.core.errors import protect_grpc
27+
28+
from ..base.components import GRPCComponentsService
29+
from ..base.conversions import from_measurement_to_server_angle
30+
from .conversions import (
31+
build_grpc_id,
32+
from_grpc_matrix_to_matrix,
33+
from_point3d_to_grpc_point,
34+
from_unit_vector_to_grpc_direction,
35+
)
36+
37+
38+
class GRPCComponentsServiceV0(GRPCComponentsService):
39+
"""Components service for gRPC communication with the Geometry server.
40+
41+
This class provides methods to call components in the
42+
Geometry server using gRPC. It is specifically designed for the v0
43+
version of the Geometry API.
44+
45+
Parameters
46+
----------
47+
channel : grpc.Channel
48+
The gRPC channel to the server.
49+
"""
50+
51+
@protect_grpc
52+
def __init__(self, channel: grpc.Channel): # noqa: D102
53+
from ansys.api.geometry.v0.components_pb2_grpc import ComponentsStub
54+
55+
self.stub = ComponentsStub(channel)
56+
57+
@protect_grpc
58+
def create(self, **kwargs) -> dict: # noqa: D102
59+
from ansys.api.geometry.v0.components_pb2 import CreateRequest
60+
61+
# Create the request - assumes all inputs are valid and of the proper type
62+
request = CreateRequest(
63+
name=kwargs["name"],
64+
parent=kwargs["parent_id"],
65+
template=kwargs["template_id"],
66+
instance_name=kwargs["instance_name"],
67+
)
68+
69+
# Call the gRPC service
70+
response = self.stub.Create(request)
71+
72+
# Return the response - formatted as a dictionary
73+
return {
74+
"id": response.component.id,
75+
"name": response.component.name,
76+
"instance_name": response.component.instance_name,
77+
}
78+
79+
@protect_grpc
80+
def set_name(self, **kwargs) -> dict: # noqa: D102
81+
from ansys.api.geometry.v0.models_pb2 import SetObjectNameRequest
82+
83+
# Create the request - assumes all inputs are valid and of the proper type
84+
request = SetObjectNameRequest(id=build_grpc_id(kwargs["id"]), name=kwargs["name"])
85+
86+
# Call the gRPC service
87+
_ = self.stub.SetName(request)
88+
89+
# Return the response - formatted as a dictionary
90+
return {}
91+
92+
@protect_grpc
93+
def set_placement(self, **kwargs) -> dict: # noqa: D102
94+
from ansys.api.geometry.v0.components_pb2 import SetPlacementRequest
95+
96+
# Create the direction and point objects
97+
translation = (
98+
from_unit_vector_to_grpc_direction(kwargs["translation"].normalize())
99+
if kwargs["translation"] is not None
100+
else None
101+
)
102+
origin = (
103+
from_point3d_to_grpc_point(kwargs["rotation_axis_origin"])
104+
if kwargs["rotation_axis_origin"] is not None
105+
else None
106+
)
107+
direction = (
108+
from_unit_vector_to_grpc_direction(kwargs["rotation_axis_direction"])
109+
if kwargs["rotation_axis_direction"] is not None
110+
else None
111+
)
112+
113+
# Create the request - assumes all inputs are valid and of the proper type
114+
request = SetPlacementRequest(
115+
id=kwargs["id"],
116+
translation=translation,
117+
rotation_axis_origin=origin,
118+
rotation_axis_direction=direction,
119+
rotation_angle=from_measurement_to_server_angle(kwargs["rotation_angle"]),
120+
)
121+
122+
# Call the gRPC service
123+
response = self.stub.SetPlacement(request)
124+
125+
# Return the response - formatted as a dictionary
126+
return {"matrix": from_grpc_matrix_to_matrix(response.matrix)}
127+
128+
@protect_grpc
129+
def set_shared_topology(self, **kwargs) -> dict: # noqa: D102
130+
from ansys.api.geometry.v0.components_pb2 import SetSharedTopologyRequest
131+
132+
# Create the request - assumes all inputs are valid and of the proper type
133+
request = SetSharedTopologyRequest(
134+
id=kwargs["id"],
135+
share_type=kwargs["share_type"].value,
136+
)
137+
138+
# Call the gRPC service
139+
_ = self.stub.SetSharedTopology(request)
140+
141+
# Return the response - formatted as a dictionary
142+
return {}
143+
144+
@protect_grpc
145+
def delete(self, **kwargs) -> dict: # noqa: D102
146+
# Create the request - assumes all inputs are valid and of the proper type
147+
request = build_grpc_id(kwargs["id"])
148+
149+
# Call the gRPC service
150+
_ = self.stub.Delete(request)
151+
152+
# Return the response - formatted as a dictionary
153+
return {}
154+
155+
@protect_grpc
156+
def import_groups(self, **kwargs) -> dict: # noqa: D102
157+
from ansys.api.geometry.v0.components_pb2 import ImportGroupsRequest
158+
159+
# Create the request - assumes all inputs are valid and of the proper type
160+
request = ImportGroupsRequest(
161+
id=build_grpc_id(kwargs["id"]),
162+
)
163+
164+
# Call the gRPC service
165+
_ = self.stub.ImportGroups(request)
166+
167+
# Return the response - formatted as a dictionary
168+
return {}
169+
170+
@protect_grpc
171+
def make_independent(self, **kwargs) -> dict: # noqa: D102
172+
from ansys.api.geometry.v0.components_pb2 import MakeIndependentRequest
173+
174+
# Create the request - assumes all inputs are valid and of the proper type
175+
request = MakeIndependentRequest(
176+
ids=[build_grpc_id(id) for id in kwargs["ids"]],
177+
)
178+
179+
# Call the gRPC service
180+
_ = self.stub.MakeIndependent(request)
181+
182+
# Return the response - formatted as a dictionary
183+
return {}

0 commit comments

Comments
 (0)