Branch data Line data Source code
1 : : //- File: CAEntityId.cpp
2 : : //- Owner: Dong Zhu
3 : : //- Description: Cubit Attribute for entity ids.
4 : : //- Checked By:
5 : : //- Version:
6 : :
7 : :
8 : : #include "CAEntityId.hpp"
9 : : #include "CAMergePartner.hpp"
10 : : #include "TDUniqueId.hpp"
11 : : #include "TopologyBridge.hpp"
12 : : #include "RefEntity.hpp"
13 : : #include "RefVertex.hpp"
14 : : #include "RefEdge.hpp"
15 : : #include "RefFace.hpp"
16 : : #include "CastTo.hpp"
17 : : #include "MergeTool.hpp"
18 : : #include "RefEntityFactory.hpp"
19 : : #include "GeometryQueryTool.hpp"
20 : : #include "GSaveOpen.hpp"
21 : : #include "CADeferredAttrib.hpp"
22 : : #include "BasicTopologyEntity.hpp"
23 : : #include "GeometryEntity.hpp"
24 : :
25 : 13661 : CubitAttrib* CAEntityId_creator(RefEntity* entity, const CubitSimpleAttrib &p_csa)
26 : : {
27 [ + - ]: 13661 : return new CAEntityId(entity, p_csa);
28 : : }
29 : :
30 : 13661 : CAEntityId::CAEntityId(RefEntity* new_attrib_owner,
31 : : const CubitSimpleAttrib &csa_ptr)
32 : 13661 : : CubitAttrib(new_attrib_owner)
33 : : {
34 : 13661 : entityId = 0;
35 : 13661 : boundingUid = CUBIT_INT_MIN;
36 : 13661 : boundingSense = CUBIT_UNKNOWN;
37 : 13661 : boundingXYZ = NULL;
38 : :
39 [ + - ][ + + ]: 13661 : if(!csa_ptr.isEmpty())
40 : : {
41 [ + - ][ + - ]: 2557 : PRINT_DEBUG_94( "Creating ENTITY_ID attribute from CSA for %s %d\n",
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
42 : : (attribOwnerEntity ? attribOwnerEntity->class_name() : "(none)"),
43 [ # # ]: 0 : (attribOwnerEntity ? attribOwnerEntity->id() : 0));
44 : :
45 [ + - ]: 2557 : const std::vector<int>& i_list = csa_ptr.int_data_list();
46 : :
47 [ + - ][ - + ]: 2557 : assert(i_list.size() > 0);
48 [ + - ]: 2557 : entityId = i_list[0];
49 : :
50 [ + - ][ + - ]: 2557 : if (i_list.size() > 1) {
51 [ + - ]: 2557 : boundingUid = i_list[1];
52 [ + - ]: 2557 : boundingSense = (CubitSense) (i_list[2]);
53 : : }
54 : : else {
55 : 0 : boundingUid = CUBIT_INT_MIN;
56 : 0 : boundingSense = CUBIT_UNKNOWN;
57 : : }
58 : :
59 [ + - ]: 2557 : const std::vector<double>& d_list = csa_ptr.double_data_list();
60 [ + - ][ + + ]: 2557 : if (d_list.size() > 0) {
61 [ + - ][ - + ]: 40 : assert(d_list.size() == 3);
62 [ - + ]: 40 : RefEdge *edge = CAST_TO(new_attrib_owner, RefEdge);
63 [ + - ]: 40 : if (edge) {
64 [ + - ][ + - ]: 40 : assert(edge->start_vertex() == edge->end_vertex());
[ - + ]
65 : : }
66 : : else {
67 [ # # ][ # # ]: 0 : PRINT_ERROR("Unexpected NULL pointer for edge.\n");
[ # # ][ # # ]
68 : : }
69 [ + - ]: 40 : boundingXYZ = new CubitVector(d_list[0],
70 [ + - ]: 40 : d_list[1],
71 [ + - ][ + - ]: 40 : d_list[2]);
[ + - ]
72 : : }
73 : 2557 : else boundingXYZ = NULL;
74 : : }
75 : 13661 : }
76 : :
77 : 40092 : CAEntityId::~CAEntityId()
78 : : {
79 [ + + ]: 13364 : if ( boundingXYZ ) delete boundingXYZ;
80 [ - + ]: 26728 : }
81 : :
82 : :
83 : 6561 : CubitStatus CAEntityId::actuate()
84 : : {
85 [ - + ]: 6561 : if ( hasActuated)
86 : 0 : return CUBIT_SUCCESS;
87 : :
88 [ - + ]: 6561 : if ( !attribOwnerEntity )
89 : 0 : return CUBIT_FAILURE;
90 : :
91 : 6561 : int this_owner_id = attribOwnerEntity->id();
92 : :
93 : 6561 : deleteAttrib = CUBIT_FALSE;
94 : :
95 : : // First, check to see if we are importing a Cubit file, in which
96 : : // case we may need to add an increment to the CAEntityId id, for
97 : : // consistency. In the Cubit file restore, mesh gets reattached to
98 : : // geometry based on the geometry id. When importing into an
99 : : // existing session of Cubit (where a model already exists), we
100 : : // need to use a consistent id increment so that the mesh gets
101 : : // restored to the proper geometry entity.
102 : 6561 : int id_inc = 0;
103 [ - + ]: 6561 : if( GSaveOpen::gso_sets_ids() )
104 : : {
105 : 0 : id_inc = GSaveOpen::get_id_inc( attribOwnerEntity );
106 [ # # ]: 0 : if( id_inc == -1 )
107 : 0 : id_inc = 0;
108 : : }
109 : :
110 : : // three possibilities:
111 : :
112 : : // 1) owner entity id is the same as this attrib id
113 [ + + ]: 6561 : if (entityId == this_owner_id+id_inc) {
114 : 1273 : hasActuated = CUBIT_TRUE;
115 [ - + ][ # # ]: 1273 : PRINT_DEBUG_102("CAEntityId::actuate: already have id for %s %d\n",
116 [ # # ]: 0 : attribOwnerEntity->class_name(), this_owner_id+id_inc);
117 : 1273 : return CUBIT_SUCCESS;
118 : : }
119 : :
120 : : RefEntity *other_entity =
121 : 5288 : GeometryQueryTool::instance()->get_ref_entity(attribOwnerEntity->class_name(),
122 : 5288 : entityId+id_inc);
123 : :
124 : : // Check to make sure the other entity has a valid topology bridge. If
125 : : // it doesn't it may be a ref entity hanging around that still needs
126 : : // to be cleaned up so don't consider it in the checks below.
127 [ + + ]: 5288 : TopologyEntity *te = dynamic_cast<TopologyEntity*>(other_entity);
128 [ + + ][ + + ]: 5288 : if(te && !te->bridge_manager()->topology_bridge())
[ + + ]
129 : 22 : other_entity = NULL;
130 : :
131 : : // 2) already an entity with the new id;
132 [ + + ]: 5288 : if (other_entity) {
133 : : // 2a) if other entity has a CAMP attribute, this owner has one too,
134 : : // and they both have the same unique id, these entities will
135 : : // get merged together; need to make sure we assign the lower id
136 : : // to the entity with the correct sense or direction
137 [ + - ]: 5016 : DLIList<CubitAttrib*> att_list;
138 [ + - ]: 5016 : other_entity->find_cubit_attrib_type(CA_MERGE_PARTNER, att_list);
139 : 5016 : CAMergePartner *camp_ptr_other = NULL;
140 : 5016 : CAMergePartner *camp_ptr_this = NULL;
141 [ + - ][ - + ]: 5016 : if (att_list.size() > 0) camp_ptr_other = CAST_TO(att_list.get(), CAMergePartner);
[ # # ][ # # ]
142 [ + - ]: 5016 : att_list.clean_out();
143 [ + - ]: 5016 : attribOwnerEntity->find_cubit_attrib_type(CA_MERGE_PARTNER, att_list);
144 [ + - ][ + + ]: 5016 : if (att_list.size() > 0) camp_ptr_this = CAST_TO(att_list.get(), CAMergePartner);
[ + - ][ - + ]
145 : :
146 [ - + ][ # # ]: 5016 : if (camp_ptr_other && camp_ptr_this &&
[ # # ][ - + ]
147 [ # # ][ # # ]: 0 : camp_ptr_other->merge_id()+id_inc == camp_ptr_this->merge_id()+id_inc) {
148 [ # # ][ # # ]: 0 : PRINT_DEBUG_102("CAEntityId::actuate: another entity with same id & merge partner,"
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
149 : : " this = %s %d, other = %s %d\n",
150 : : attribOwnerEntity->class_name(), this_owner_id+id_inc, other_entity->class_name(),
151 [ # # ]: 0 : entityId+id_inc);
152 : :
153 [ # # ]: 0 : if (boundingUid != CUBIT_INT_MIN) {
154 : : // check the sense of the *other* entity; can't check sense of this
155 : : // entity yet, because the topology hasn't been filled yet
156 [ # # ]: 0 : RefEdge *edge = CAST_TO(other_entity, RefEdge);
157 [ # # ]: 0 : RefFace *face = CAST_TO(other_entity, RefFace);
158 : 0 : CubitBoolean switch_ids = CUBIT_FALSE;
159 : :
160 [ # # ]: 0 : if (edge) {
161 : :
162 [ # # ][ # # ]: 0 : if (edge->start_vertex() != edge->end_vertex()) {
[ # # ]
163 : : // check the start vertex of the other entity
164 [ # # ]: 0 : ToolDataUser *tdu = TDUniqueId::find_td_unique_id(boundingUid, other_entity);
165 [ # # ]: 0 : RefVertex *vert = CAST_TO(tdu, RefVertex);
166 [ # # ]: 0 : assert(vert != 0);
167 [ # # ][ # # ]: 0 : if (vert != edge->start_vertex())
168 : : // other entity doesn't have the right sense, so we'll have to switch
169 : : // (we don't know whether this one will have the right sense, and can't
170 : : // check 'cuz this one's topology hasn't been completed yet)
171 : :
172 : : // only switch if other entity's id is lower, so that it's not the one kept
173 [ # # ]: 0 : if (entityId+id_inc > this_owner_id+id_inc) switch_ids = CUBIT_TRUE;
174 : : }
175 [ # # ]: 0 : else if (boundingXYZ) {
176 : : // else we have a single-vertex curve and an xyz value;
177 : : // check position of 1/3 parameter
178 : 0 : const double ONE_THIRD = 1.0/3.0;
179 [ # # ]: 0 : CubitVector test_vec;
180 : : /*CubitStatus result = */
181 [ # # ]: 0 : edge->position_from_fraction( ONE_THIRD, test_vec);
182 : :
183 [ # # ][ # # ]: 0 : if (!GeometryQueryTool::instance()->about_spatially_equal(*boundingXYZ, test_vec)) {
[ # # ]
184 : :
185 : : // only switch if other entity's id is lower, so that it's not the one kept
186 [ # # ]: 0 : if (entityId+id_inc > this_owner_id+id_inc) switch_ids = CUBIT_TRUE;
187 : : }
188 : : }
189 : : }
190 : :
191 [ # # ]: 0 : else if (face) {
192 : : // check sense of other face wrt bounding uid entity; other face should be
193 : : // fully constructed by now
194 [ # # ]: 0 : ToolDataUser *tdu = TDUniqueId::find_td_unique_id(boundingUid, other_entity);
195 : :
196 [ # # ]: 0 : edge = CAST_TO(tdu, RefEdge);
197 [ # # ]: 0 : if (!edge)
198 [ # # ][ # # ]: 0 : PRINT_WARNING("CAEntityId::actuate: didn't find edge with uid %d for face %d.\n",
[ # # ][ # # ]
199 [ # # ]: 0 : boundingUid, face->id());
200 [ # # ][ # # ]: 0 : else if (edge->sense(face) != boundingSense && entityId+id_inc > this_owner_id+id_inc)
[ # # ][ # # ]
201 : 0 : switch_ids = CUBIT_TRUE;
202 : : }
203 : :
204 [ # # ]: 0 : if (switch_ids) {
205 [ # # ]: 0 : attribOwnerEntity->set_id(0, CUBIT_FALSE);
206 [ # # ]: 0 : other_entity->set_id(this_owner_id+id_inc);
207 [ # # ][ # # ]: 0 : PRINT_DEBUG_102("CAEntityId::actuate: other entity with same id, merge partner, and correct sense;"
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
208 : : " switching id's, this = %s %d, other = %s %d\n",
209 : : attribOwnerEntity->class_name(), this_owner_id+id_inc, other_entity->class_name(),
210 [ # # ]: 0 : entityId+id_inc);
211 [ # # ]: 0 : attribOwnerEntity->set_id (entityId+id_inc, CUBIT_FALSE);
212 : : // attribOwnerEntity->color(CUBIT_DEFAULT_COLOR_INDEX);
213 : : }
214 : : }
215 : :
216 : 0 : hasActuated = CUBIT_TRUE;
217 : 0 : return CUBIT_SUCCESS;
218 : : }
219 : :
220 : : // 2b) if other entity has a CAEID attribute, check to make sure it's not
221 : : // the same, and if not, switch real ids with it (it will get changed later);
222 : : // otherwise, print a warning
223 [ + - ]: 5016 : other_entity->find_cubit_attrib_type(CA_ENTITY_ID, att_list);
224 [ + - ][ + - ]: 6006 : CAEntityId *other_caeid = (att_list.size() ? CAST_TO(att_list.get(), CAEntityId)
225 [ + + ][ - + ]: 6006 : : NULL);
226 [ - + ][ # # ]: 5016 : if (other_caeid && other_caeid->id()+id_inc != entityId+id_inc)
[ # # ][ - + ]
227 : : {
228 : : // need to reset owner entity id first, so that we don't have
229 : : // two identical ids active at the same time (messes up the
230 : : // graphics)
231 : :
232 [ # # ]: 0 : attribOwnerEntity->set_id(0, CUBIT_FALSE);
233 [ # # ]: 0 : other_entity->set_id(this_owner_id+id_inc);
234 [ # # ][ # # ]: 0 : PRINT_DEBUG_102("CAEntityId::actuate: other entity with same id, NO merge partner;"
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
235 : : " switching id's, this = %s %d, other = %s %d\n",
236 : : attribOwnerEntity->class_name(), this_owner_id+id_inc, other_entity->class_name(),
237 [ # # ]: 0 : entityId+id_inc);
238 : : }
239 : :
240 [ - + ]: 5016 : else if( camp_ptr_other )
241 : : {
242 [ # # ]: 0 : DLIList<RefEntity*> merge_partners;
243 [ # # ]: 0 : camp_ptr_other->merge_prepare( merge_partners );
244 : 0 : int lowest_id = entityId + id_inc;
245 [ # # ][ # # ]: 0 : for( int i = merge_partners.size(); i--; )
246 [ # # ][ # # ]: 0 : if( merge_partners.step_and_get()->id() < lowest_id )
[ # # ]
247 [ # # ][ # # ]: 0 : lowest_id = merge_partners.get()->id();
248 : :
249 [ # # ]: 0 : if( lowest_id < entityId+id_inc )
250 : : // Entity will merge later and loose its current Id,
251 : : // so we can take the Id for this entity.
252 : : {
253 [ # # ]: 0 : attribOwnerEntity->set_id(0, CUBIT_FALSE);
254 [ # # ]: 0 : other_entity->set_id( this_owner_id + id_inc );
255 [ # # ][ + - ]: 5016 : }
[ + - ]
256 : :
257 : 5016 : }
258 : : }
259 : :
260 : : // 2b) else print an error and don't actuate
261 [ + + ][ + - ]: 5288 : if( other_entity && other_entity->id() == (entityId+id_inc) )
[ + + ]
262 : : {
263 : : // PRINT_WARNING ( "Duplicate entity id attribute on %s %d; duplicated id = %d.\n"
264 : : // "This sometimes happens when id attributes are exported without exporting"
265 : : // " merge attribute.\n",
266 : : // attribOwnerEntity->class_name(), this_owner_id+id_inc, entityId+id_inc);
267 : : // hasActuated = CUBIT_TRUE;
268 : 5016 : CADeferredAttrib::add_unactuated_ca(this);
269 : 5016 : return CUBIT_FAILURE;
270 : : }
271 : :
272 [ - + ][ # # ]: 272 : else PRINT_DEBUG_102("CAEntityId::actuate: setting id of %s %d; new id = %d\n",
273 [ # # ]: 0 : attribOwnerEntity->class_name(), this_owner_id+id_inc, entityId+id_inc);
274 : :
275 : : // ok, now set the id and return
276 : 272 : attribOwnerEntity->set_id (entityId+id_inc, CUBIT_FALSE);
277 : : // attribOwnerEntity->color(CUBIT_DEFAULT_COLOR_INDEX);
278 [ - + ]: 272 : BasicTopologyEntity *bte = CAST_TO( attribOwnerEntity, BasicTopologyEntity );
279 [ + + ]: 272 : if( bte )
280 : : {
281 : : //if doesn't already have an id, set it, otherwise, leave it alone.
282 [ - + ]: 242 : if( 0 == bte->get_geometry_entity_ptr()->get_saved_id() )
283 : 0 : bte->get_geometry_entity_ptr()->set_saved_id(entityId+id_inc);
284 : : }
285 : :
286 : 272 : hasActuated = CUBIT_TRUE;
287 : :
288 : 6561 : return CUBIT_SUCCESS;
289 : : }
290 : :
291 : 13018 : CubitStatus CAEntityId::update()
292 : : {
293 [ - + ]: 13018 : if ( hasUpdated )
294 : 0 : return CUBIT_SUCCESS;
295 : :
296 [ - + ]: 13018 : if ( !attribOwnerEntity)
297 : 0 : return CUBIT_FAILURE;
298 : :
299 : 13018 : entityId = attribOwnerEntity->id ( );
300 : :
301 : : // set the updated flag
302 : 13018 : hasUpdated = CUBIT_TRUE;
303 : :
304 : : // set the sense data
305 [ - + ]: 13018 : TopologyEntity *topo_entity = CAST_TO(attribOwnerEntity, TopologyEntity);
306 [ - + ]: 13018 : assert(topo_entity != 0);
307 [ + + ]: 13018 : if (MergeTool::instance()->entity_merged(topo_entity) == CUBIT_FALSE)
308 : 12262 : return CUBIT_SUCCESS;
309 : :
310 : : // get the uid of the first child entity
311 : : RefEdge *edge;
312 : : RefFace *face;
313 [ - + ][ + + ]: 756 : if ((edge = CAST_TO(attribOwnerEntity, RefEdge)) != NULL) {
314 : 356 : RefVertex *vert = edge->start_vertex();
315 [ + - ]: 356 : boundingUid = TDUniqueId::get_unique_id(vert);
316 : 356 : boundingSense = CUBIT_FORWARD;
317 : :
318 : : // need to check for single-vertex curves
319 [ + + ]: 356 : if (vert == edge->end_vertex()) {
320 : : // if it is one, store the xyz of 1/3 down the curve
321 : 40 : const double ONE_THIRD = 1.0/3.0;
322 : : // Find the point 1/3 along *this*
323 [ + - ][ + - ]: 40 : if (!boundingXYZ) boundingXYZ = new CubitVector();
324 : : CubitStatus result = edge->position_from_fraction( ONE_THIRD,
325 : 40 : *boundingXYZ);
326 [ - + ]: 40 : if ( result != CUBIT_SUCCESS )
327 : : {
328 [ # # ]: 0 : PRINT_ERROR("Error in CAEntityId::update;"
329 [ # # ]: 0 : "Can't find position 1/3 along curve.\n");
330 : 356 : return CUBIT_FAILURE;
331 : : }
332 : : }
333 : : }
334 : :
335 [ - + ][ + + ]: 400 : else if ((face = CAST_TO(attribOwnerEntity, RefFace)) != NULL) {
336 [ + - ]: 104 : DLIList<RefEdge*> edges;
337 [ + - ]: 104 : face->ref_edges(edges);
338 [ + - ][ + - ]: 104 : if (edges.size()) {
339 [ + - ]: 104 : edge = edges.get_and_step();
340 [ + - ][ + - ]: 104 : boundingUid = TDUniqueId::get_unique_id(edge);
341 [ + - ]: 104 : boundingSense = edge->sense(face);
342 [ + - ][ - + ]: 104 : return CUBIT_SUCCESS;
343 : 104 : }
344 : : }
345 : :
346 : 13018 : return CUBIT_SUCCESS;
347 : : }
348 : :
349 : 0 : void CAEntityId::merge_owner(CubitAttrib *deletable_attrib)
350 : : {
351 : : // take the id with the lowest value
352 [ # # ]: 0 : CAEntityId *other_caeid = CAST_TO(deletable_attrib, CAEntityId);
353 : :
354 [ # # ][ # # ]: 0 : if (other_caeid &&
[ # # ]
355 [ # # ]: 0 : (entityId == 0 || entityId > other_caeid->id()))
356 : 0 : entityId = other_caeid->id();
357 : 0 : }
358 : :
359 : 23823 : CubitSimpleAttrib CAEntityId::cubit_simple_attrib()
360 : : {
361 [ + - ]: 23823 : std::vector<CubitString> cs_list;
362 [ + - ][ + - ]: 47646 : std::vector<double> d_list;
363 [ + - ][ + - ]: 47646 : std::vector<int> i_list;
364 : :
365 [ + - ]: 23823 : i_list.push_back ( entityId );
366 [ + - ]: 23823 : i_list.push_back ( boundingUid );
367 [ + - ]: 23823 : i_list.push_back ( boundingSense );
368 [ + + ]: 23823 : if (boundingXYZ) {
369 [ + - ][ + - ]: 160 : d_list.push_back ( boundingXYZ->x() );
370 [ + - ][ + - ]: 160 : d_list.push_back ( boundingXYZ->y() );
371 [ + - ][ + - ]: 160 : d_list.push_back ( boundingXYZ->z() );
372 : : }
373 : :
374 [ + - ][ + - ]: 23823 : cs_list.push_back(att_internal_name());
[ + - ][ + - ]
375 : :
376 [ + - ][ + - ]: 47646 : return CubitSimpleAttrib(&cs_list, &d_list, &i_list);
377 : : }
378 : :
379 : 0 : void CAEntityId::print()
380 : : {
381 : : // print info on this attribute
382 : :
383 [ # # ]: 0 : PRINT_INFO("CAEntityId: owner = %s %d: id=%d, color=%d\n",
384 : : attribOwnerEntity->class_name(), attribOwnerEntity->id(),
385 [ # # ]: 0 : entityId, 0);
386 [ + - ][ + - ]: 6540 : }
|