21
21
# SOFTWARE.
22
22
"""Module for creating a named selection."""
23
23
24
- from beartype import beartype as check_input_types
24
+ from typing import TYPE_CHECKING
25
25
26
+ from ansys .api .dbu .v0 .dbumodels_pb2 import EntityIdentifier
26
27
from ansys .api .geometry .v0 .namedselections_pb2 import CreateRequest
27
28
from ansys .api .geometry .v0 .namedselections_pb2_grpc import NamedSelectionsStub
28
29
from ansys .geometry .core .connection .client import GrpcClient
30
+ from ansys .geometry .core .connection .conversions import grpc_point_to_point3d
29
31
from ansys .geometry .core .designer .beam import Beam
30
32
from ansys .geometry .core .designer .body import Body
31
33
from ansys .geometry .core .designer .designpoint import DesignPoint
32
34
from ansys .geometry .core .designer .edge import Edge
33
35
from ansys .geometry .core .designer .face import Face
34
36
from ansys .geometry .core .errors import protect_grpc
37
+ from ansys .geometry .core .misc .auxiliary import (
38
+ get_beams_from_ids ,
39
+ get_bodies_from_ids ,
40
+ get_edges_from_ids ,
41
+ get_faces_from_ids ,
42
+ )
43
+
44
+ if TYPE_CHECKING :
45
+ from ansys .geometry .core .designer .design import Design
35
46
36
47
37
48
class NamedSelection :
@@ -46,6 +57,8 @@ class NamedSelection:
46
57
----------
47
58
name : str
48
59
User-defined name for the named selection.
60
+ design : Design
61
+ Design instance to which the named selection belongs.
49
62
grpc_client : GrpcClient
50
63
Active supporting Geometry service instance for design modeling.
51
64
bodies : list[Body], default: None
@@ -61,10 +74,10 @@ class NamedSelection:
61
74
"""
62
75
63
76
@protect_grpc
64
- @check_input_types
65
77
def __init__ (
66
78
self ,
67
79
name : str ,
80
+ design : "Design" ,
68
81
grpc_client : GrpcClient ,
69
82
bodies : list [Body ] | None = None ,
70
83
faces : list [Face ] | None = None ,
@@ -75,6 +88,7 @@ def __init__(
75
88
):
76
89
"""Initialize the ``NamedSelection`` class."""
77
90
self ._name = name
91
+ self ._design = design
78
92
self ._grpc_client = grpc_client
79
93
self ._named_selections_stub = NamedSelectionsStub (self ._grpc_client .channel )
80
94
@@ -97,19 +111,26 @@ def __init__(
97
111
self ._beams = beams
98
112
self ._design_points = design_points
99
113
114
+ # Store ids for later use... when verifying if the NS changed.
115
+ self ._ids_cached = {
116
+ "bodies" : [body .id for body in bodies ],
117
+ "faces" : [face .id for face in faces ],
118
+ "edges" : [edge .id for edge in edges ],
119
+ "beams" : [beam .id for beam in beams ],
120
+ "design_points" : [dp .id for dp in design_points ],
121
+ }
122
+
100
123
if preexisting_id :
101
124
self ._id = preexisting_id
102
125
return
103
126
104
127
# All ids should be unique - no duplicated values
105
128
ids = set ()
106
129
107
- # Loop over bodies, faces and edges
108
- [ids .add (body .id ) for body in bodies ]
109
- [ids .add (face .id ) for face in faces ]
110
- [ids .add (edge .id ) for edge in edges ]
111
- [ids .add (beam .id ) for beam in beams ]
112
- [ids .add (dp .id ) for dp in design_points ]
130
+ # Loop over all entities to get their ids
131
+ for value in self ._ids_cached .values ():
132
+ for entity_id in value :
133
+ ids .add (entity_id )
113
134
114
135
named_selection_request = CreateRequest (name = name , members = ids )
115
136
self ._grpc_client .log .debug ("Requesting creation of named selection." )
@@ -129,28 +150,84 @@ def name(self) -> str:
129
150
@property
130
151
def bodies (self ) -> list [Body ]:
131
152
"""All bodies in the named selection."""
153
+ self .__verify_ns ()
154
+ if self ._bodies is None :
155
+ # Get all bodies from the named selection
156
+ self ._bodies = get_bodies_from_ids (self ._design , self ._ids_cached ["bodies" ])
157
+
132
158
return self ._bodies
133
159
134
160
@property
135
161
def faces (self ) -> list [Face ]:
136
162
"""All faces in the named selection."""
163
+ self .__verify_ns ()
164
+ if self ._faces is None :
165
+ # Get all faces from the named selection
166
+ self ._faces = get_faces_from_ids (self ._design , self ._ids_cached ["faces" ])
167
+
137
168
return self ._faces
138
169
139
170
@property
140
171
def edges (self ) -> list [Edge ]:
141
172
"""All edges in the named selection."""
173
+ self .__verify_ns ()
174
+ if self ._edges is None :
175
+ # Get all edges from the named selection
176
+ self ._edges = get_edges_from_ids (self ._design , self ._ids_cached ["edges" ])
177
+
142
178
return self ._edges
143
179
144
180
@property
145
181
def beams (self ) -> list [Beam ]:
146
182
"""All beams in the named selection."""
183
+ self .__verify_ns ()
184
+ if self ._beams is None :
185
+ # Get all beams from the named selection
186
+ self ._beams = get_beams_from_ids (self ._design , self ._ids_cached ["beams" ])
187
+
147
188
return self ._beams
148
189
149
190
@property
150
191
def design_points (self ) -> list [DesignPoint ]:
151
192
"""All design points in the named selection."""
193
+ self .__verify_ns ()
194
+ if self ._design_points is None :
195
+ # Get all design points from the named selection
196
+ self ._design_points = [
197
+ DesignPoint (dp_id , f"dp: { dp_id } " , grpc_point_to_point3d (dp_point ))
198
+ for dp_id , dp_point in self ._ids_cached ["design_points" ]
199
+ ]
200
+
152
201
return self ._design_points
153
202
203
+ def __verify_ns (self ) -> None :
204
+ """Verify that the contents of the named selection are up to date."""
205
+ if self ._grpc_client .backend_version < (25 , 2 , 0 ):
206
+ self ._grpc_client .log .warning (
207
+ "Accessing members of named selections is only"
208
+ " consistent starting in version 2025 R2."
209
+ )
210
+ return
211
+
212
+ # Get all entities from the named selection
213
+ resp = self ._named_selections_stub .Get (EntityIdentifier (id = self ._id ))
214
+
215
+ # Check if the named selection has changed
216
+ ids = {
217
+ "bodies" : [body .id for body in resp .bodies ],
218
+ "faces" : [face .id for face in resp .faces ],
219
+ "edges" : [edge .id for edge in resp .edges ],
220
+ "beams" : [beam .id .id for beam in resp .beams ],
221
+ "design_points" : [(dp .id , dp .points [0 ]) for dp in resp .design_points ],
222
+ }
223
+
224
+ for key in ids :
225
+ if ids [key ] != self ._ids_cached [key ]:
226
+ # Clear the cache for that specific entity
227
+ setattr (self , f"_{ key } " , None )
228
+ # Update the cache
229
+ self ._ids_cached [key ] = ids [key ]
230
+
154
231
def __repr__ (self ) -> str :
155
232
"""Represent the ``NamedSelection`` as a string."""
156
233
lines = [f"ansys.geometry.core.designer.selection.NamedSelection { hex (id (self ))} " ]
0 commit comments