cgma
|
00001 //- File: CAEntityId.cpp 00002 //- Owner: Dong Zhu 00003 //- Description: Cubit Attribute for entity ids. 00004 //- Checked By: 00005 //- Version: 00006 00007 00008 #include "CAEntityId.hpp" 00009 #include "CAMergePartner.hpp" 00010 #include "TDUniqueId.hpp" 00011 #include "TopologyBridge.hpp" 00012 #include "RefEntity.hpp" 00013 #include "RefVertex.hpp" 00014 #include "RefEdge.hpp" 00015 #include "RefFace.hpp" 00016 #include "CastTo.hpp" 00017 #include "MergeTool.hpp" 00018 #include "RefEntityFactory.hpp" 00019 #include "GeometryQueryTool.hpp" 00020 #include "GSaveOpen.hpp" 00021 #include "CADeferredAttrib.hpp" 00022 #include "BasicTopologyEntity.hpp" 00023 #include "GeometryEntity.hpp" 00024 00025 CubitAttrib* CAEntityId_creator(RefEntity* entity, const CubitSimpleAttrib &p_csa) 00026 { 00027 return new CAEntityId(entity, p_csa); 00028 } 00029 00030 CAEntityId::CAEntityId(RefEntity* new_attrib_owner, 00031 const CubitSimpleAttrib &csa_ptr) 00032 : CubitAttrib(new_attrib_owner) 00033 { 00034 entityId = 0; 00035 boundingUid = CUBIT_INT_MIN; 00036 boundingSense = CUBIT_UNKNOWN; 00037 boundingXYZ = NULL; 00038 00039 if(!csa_ptr.isEmpty()) 00040 { 00041 PRINT_DEBUG_94( "Creating ENTITY_ID attribute from CSA for %s %d\n", 00042 (attribOwnerEntity ? attribOwnerEntity->class_name() : "(none)"), 00043 (attribOwnerEntity ? attribOwnerEntity->id() : 0)); 00044 00045 const std::vector<int>& i_list = csa_ptr.int_data_list(); 00046 00047 assert(i_list.size() > 0); 00048 entityId = i_list[0]; 00049 00050 if (i_list.size() > 1) { 00051 boundingUid = i_list[1]; 00052 boundingSense = (CubitSense) (i_list[2]); 00053 } 00054 else { 00055 boundingUid = CUBIT_INT_MIN; 00056 boundingSense = CUBIT_UNKNOWN; 00057 } 00058 00059 const std::vector<double>& d_list = csa_ptr.double_data_list(); 00060 if (d_list.size() > 0) { 00061 assert(d_list.size() == 3); 00062 RefEdge *edge = CAST_TO(new_attrib_owner, RefEdge); 00063 if (edge) { 00064 assert(edge->start_vertex() == edge->end_vertex()); 00065 } 00066 else { 00067 PRINT_ERROR("Unexpected NULL pointer for edge.\n"); 00068 } 00069 boundingXYZ = new CubitVector(d_list[0], 00070 d_list[1], 00071 d_list[2]); 00072 } 00073 else boundingXYZ = NULL; 00074 } 00075 } 00076 00077 CAEntityId::~CAEntityId() 00078 { 00079 if ( boundingXYZ ) delete boundingXYZ; 00080 } 00081 00082 00083 CubitStatus CAEntityId::actuate() 00084 { 00085 if ( hasActuated) 00086 return CUBIT_SUCCESS; 00087 00088 if ( !attribOwnerEntity ) 00089 return CUBIT_FAILURE; 00090 00091 int this_owner_id = attribOwnerEntity->id(); 00092 00093 deleteAttrib = CUBIT_FALSE; 00094 00095 // First, check to see if we are importing a Cubit file, in which 00096 // case we may need to add an increment to the CAEntityId id, for 00097 // consistency. In the Cubit file restore, mesh gets reattached to 00098 // geometry based on the geometry id. When importing into an 00099 // existing session of Cubit (where a model already exists), we 00100 // need to use a consistent id increment so that the mesh gets 00101 // restored to the proper geometry entity. 00102 int id_inc = 0; 00103 if( GSaveOpen::gso_sets_ids() ) 00104 { 00105 id_inc = GSaveOpen::get_id_inc( attribOwnerEntity ); 00106 if( id_inc == -1 ) 00107 id_inc = 0; 00108 } 00109 00110 // three possibilities: 00111 00112 // 1) owner entity id is the same as this attrib id 00113 if (entityId == this_owner_id+id_inc) { 00114 hasActuated = CUBIT_TRUE; 00115 PRINT_DEBUG_102("CAEntityId::actuate: already have id for %s %d\n", 00116 attribOwnerEntity->class_name(), this_owner_id+id_inc); 00117 return CUBIT_SUCCESS; 00118 } 00119 00120 RefEntity *other_entity = 00121 GeometryQueryTool::instance()->get_ref_entity(attribOwnerEntity->class_name(), 00122 entityId+id_inc); 00123 00124 // Check to make sure the other entity has a valid topology bridge. If 00125 // it doesn't it may be a ref entity hanging around that still needs 00126 // to be cleaned up so don't consider it in the checks below. 00127 TopologyEntity *te = dynamic_cast<TopologyEntity*>(other_entity); 00128 if(te && !te->bridge_manager()->topology_bridge()) 00129 other_entity = NULL; 00130 00131 // 2) already an entity with the new id; 00132 if (other_entity) { 00133 // 2a) if other entity has a CAMP attribute, this owner has one too, 00134 // and they both have the same unique id, these entities will 00135 // get merged together; need to make sure we assign the lower id 00136 // to the entity with the correct sense or direction 00137 DLIList<CubitAttrib*> att_list; 00138 other_entity->find_cubit_attrib_type(CA_MERGE_PARTNER, att_list); 00139 CAMergePartner *camp_ptr_other = NULL; 00140 CAMergePartner *camp_ptr_this = NULL; 00141 if (att_list.size() > 0) camp_ptr_other = CAST_TO(att_list.get(), CAMergePartner); 00142 att_list.clean_out(); 00143 attribOwnerEntity->find_cubit_attrib_type(CA_MERGE_PARTNER, att_list); 00144 if (att_list.size() > 0) camp_ptr_this = CAST_TO(att_list.get(), CAMergePartner); 00145 00146 if (camp_ptr_other && camp_ptr_this && 00147 camp_ptr_other->merge_id()+id_inc == camp_ptr_this->merge_id()+id_inc) { 00148 PRINT_DEBUG_102("CAEntityId::actuate: another entity with same id & merge partner," 00149 " this = %s %d, other = %s %d\n", 00150 attribOwnerEntity->class_name(), this_owner_id+id_inc, other_entity->class_name(), 00151 entityId+id_inc); 00152 00153 if (boundingUid != CUBIT_INT_MIN) { 00154 // check the sense of the *other* entity; can't check sense of this 00155 // entity yet, because the topology hasn't been filled yet 00156 RefEdge *edge = CAST_TO(other_entity, RefEdge); 00157 RefFace *face = CAST_TO(other_entity, RefFace); 00158 CubitBoolean switch_ids = CUBIT_FALSE; 00159 00160 if (edge) { 00161 00162 if (edge->start_vertex() != edge->end_vertex()) { 00163 // check the start vertex of the other entity 00164 ToolDataUser *tdu = TDUniqueId::find_td_unique_id(boundingUid, other_entity); 00165 RefVertex *vert = CAST_TO(tdu, RefVertex); 00166 assert(vert != 0); 00167 if (vert != edge->start_vertex()) 00168 // other entity doesn't have the right sense, so we'll have to switch 00169 // (we don't know whether this one will have the right sense, and can't 00170 // check 'cuz this one's topology hasn't been completed yet) 00171 00172 // only switch if other entity's id is lower, so that it's not the one kept 00173 if (entityId+id_inc > this_owner_id+id_inc) switch_ids = CUBIT_TRUE; 00174 } 00175 else if (boundingXYZ) { 00176 // else we have a single-vertex curve and an xyz value; 00177 // check position of 1/3 parameter 00178 const double ONE_THIRD = 1.0/3.0; 00179 CubitVector test_vec; 00180 /*CubitStatus result = */ 00181 edge->position_from_fraction( ONE_THIRD, test_vec); 00182 00183 if (!GeometryQueryTool::instance()->about_spatially_equal(*boundingXYZ, test_vec)) { 00184 00185 // only switch if other entity's id is lower, so that it's not the one kept 00186 if (entityId+id_inc > this_owner_id+id_inc) switch_ids = CUBIT_TRUE; 00187 } 00188 } 00189 } 00190 00191 else if (face) { 00192 // check sense of other face wrt bounding uid entity; other face should be 00193 // fully constructed by now 00194 ToolDataUser *tdu = TDUniqueId::find_td_unique_id(boundingUid, other_entity); 00195 00196 edge = CAST_TO(tdu, RefEdge); 00197 if (!edge) 00198 PRINT_WARNING("CAEntityId::actuate: didn't find edge with uid %d for face %d.\n", 00199 boundingUid, face->id()); 00200 else if (edge->sense(face) != boundingSense && entityId+id_inc > this_owner_id+id_inc) 00201 switch_ids = CUBIT_TRUE; 00202 } 00203 00204 if (switch_ids) { 00205 attribOwnerEntity->set_id(0, CUBIT_FALSE); 00206 other_entity->set_id(this_owner_id+id_inc); 00207 PRINT_DEBUG_102("CAEntityId::actuate: other entity with same id, merge partner, and correct sense;" 00208 " switching id's, this = %s %d, other = %s %d\n", 00209 attribOwnerEntity->class_name(), this_owner_id+id_inc, other_entity->class_name(), 00210 entityId+id_inc); 00211 attribOwnerEntity->set_id (entityId+id_inc, CUBIT_FALSE); 00212 // attribOwnerEntity->color(CUBIT_DEFAULT_COLOR_INDEX); 00213 } 00214 } 00215 00216 hasActuated = CUBIT_TRUE; 00217 return CUBIT_SUCCESS; 00218 } 00219 00220 // 2b) if other entity has a CAEID attribute, check to make sure it's not 00221 // the same, and if not, switch real ids with it (it will get changed later); 00222 // otherwise, print a warning 00223 other_entity->find_cubit_attrib_type(CA_ENTITY_ID, att_list); 00224 CAEntityId *other_caeid = (att_list.size() ? CAST_TO(att_list.get(), CAEntityId) 00225 : NULL); 00226 if (other_caeid && other_caeid->id()+id_inc != entityId+id_inc) 00227 { 00228 // need to reset owner entity id first, so that we don't have 00229 // two identical ids active at the same time (messes up the 00230 // graphics) 00231 00232 attribOwnerEntity->set_id(0, CUBIT_FALSE); 00233 other_entity->set_id(this_owner_id+id_inc); 00234 PRINT_DEBUG_102("CAEntityId::actuate: other entity with same id, NO merge partner;" 00235 " switching id's, this = %s %d, other = %s %d\n", 00236 attribOwnerEntity->class_name(), this_owner_id+id_inc, other_entity->class_name(), 00237 entityId+id_inc); 00238 } 00239 00240 else if( camp_ptr_other ) 00241 { 00242 DLIList<RefEntity*> merge_partners; 00243 camp_ptr_other->merge_prepare( merge_partners ); 00244 int lowest_id = entityId + id_inc; 00245 for( int i = merge_partners.size(); i--; ) 00246 if( merge_partners.step_and_get()->id() < lowest_id ) 00247 lowest_id = merge_partners.get()->id(); 00248 00249 if( lowest_id < entityId+id_inc ) 00250 // Entity will merge later and loose its current Id, 00251 // so we can take the Id for this entity. 00252 { 00253 attribOwnerEntity->set_id(0, CUBIT_FALSE); 00254 other_entity->set_id( this_owner_id + id_inc ); 00255 } 00256 00257 } 00258 } 00259 00260 // 2b) else print an error and don't actuate 00261 if( other_entity && other_entity->id() == (entityId+id_inc) ) 00262 { 00263 // PRINT_WARNING ( "Duplicate entity id attribute on %s %d; duplicated id = %d.\n" 00264 // "This sometimes happens when id attributes are exported without exporting" 00265 // " merge attribute.\n", 00266 // attribOwnerEntity->class_name(), this_owner_id+id_inc, entityId+id_inc); 00267 // hasActuated = CUBIT_TRUE; 00268 CADeferredAttrib::add_unactuated_ca(this); 00269 return CUBIT_FAILURE; 00270 } 00271 00272 else PRINT_DEBUG_102("CAEntityId::actuate: setting id of %s %d; new id = %d\n", 00273 attribOwnerEntity->class_name(), this_owner_id+id_inc, entityId+id_inc); 00274 00275 // ok, now set the id and return 00276 attribOwnerEntity->set_id (entityId+id_inc, CUBIT_FALSE); 00277 // attribOwnerEntity->color(CUBIT_DEFAULT_COLOR_INDEX); 00278 BasicTopologyEntity *bte = CAST_TO( attribOwnerEntity, BasicTopologyEntity ); 00279 if( bte ) 00280 { 00281 //if doesn't already have an id, set it, otherwise, leave it alone. 00282 if( 0 == bte->get_geometry_entity_ptr()->get_saved_id() ) 00283 bte->get_geometry_entity_ptr()->set_saved_id(entityId+id_inc); 00284 } 00285 00286 hasActuated = CUBIT_TRUE; 00287 00288 return CUBIT_SUCCESS; 00289 } 00290 00291 CubitStatus CAEntityId::update() 00292 { 00293 if ( hasUpdated ) 00294 return CUBIT_SUCCESS; 00295 00296 if ( !attribOwnerEntity) 00297 return CUBIT_FAILURE; 00298 00299 entityId = attribOwnerEntity->id ( ); 00300 00301 // set the updated flag 00302 hasUpdated = CUBIT_TRUE; 00303 00304 // set the sense data 00305 TopologyEntity *topo_entity = CAST_TO(attribOwnerEntity, TopologyEntity); 00306 assert(topo_entity != 0); 00307 if (MergeTool::instance()->entity_merged(topo_entity) == CUBIT_FALSE) 00308 return CUBIT_SUCCESS; 00309 00310 // get the uid of the first child entity 00311 RefEdge *edge; 00312 RefFace *face; 00313 if ((edge = CAST_TO(attribOwnerEntity, RefEdge)) != NULL) { 00314 RefVertex *vert = edge->start_vertex(); 00315 boundingUid = TDUniqueId::get_unique_id(vert); 00316 boundingSense = CUBIT_FORWARD; 00317 00318 // need to check for single-vertex curves 00319 if (vert == edge->end_vertex()) { 00320 // if it is one, store the xyz of 1/3 down the curve 00321 const double ONE_THIRD = 1.0/3.0; 00322 // Find the point 1/3 along *this* 00323 if (!boundingXYZ) boundingXYZ = new CubitVector(); 00324 CubitStatus result = edge->position_from_fraction( ONE_THIRD, 00325 *boundingXYZ); 00326 if ( result != CUBIT_SUCCESS ) 00327 { 00328 PRINT_ERROR("Error in CAEntityId::update;" 00329 "Can't find position 1/3 along curve.\n"); 00330 return CUBIT_FAILURE; 00331 } 00332 } 00333 } 00334 00335 else if ((face = CAST_TO(attribOwnerEntity, RefFace)) != NULL) { 00336 DLIList<RefEdge*> edges; 00337 face->ref_edges(edges); 00338 if (edges.size()) { 00339 edge = edges.get_and_step(); 00340 boundingUid = TDUniqueId::get_unique_id(edge); 00341 boundingSense = edge->sense(face); 00342 return CUBIT_SUCCESS; 00343 } 00344 } 00345 00346 return CUBIT_SUCCESS; 00347 } 00348 00349 void CAEntityId::merge_owner(CubitAttrib *deletable_attrib) 00350 { 00351 // take the id with the lowest value 00352 CAEntityId *other_caeid = CAST_TO(deletable_attrib, CAEntityId); 00353 00354 if (other_caeid && 00355 (entityId == 0 || entityId > other_caeid->id())) 00356 entityId = other_caeid->id(); 00357 } 00358 00359 CubitSimpleAttrib CAEntityId::cubit_simple_attrib() 00360 { 00361 std::vector<CubitString> cs_list; 00362 std::vector<double> d_list; 00363 std::vector<int> i_list; 00364 00365 i_list.push_back ( entityId ); 00366 i_list.push_back ( boundingUid ); 00367 i_list.push_back ( boundingSense ); 00368 if (boundingXYZ) { 00369 d_list.push_back ( boundingXYZ->x() ); 00370 d_list.push_back ( boundingXYZ->y() ); 00371 d_list.push_back ( boundingXYZ->z() ); 00372 } 00373 00374 cs_list.push_back(att_internal_name()); 00375 00376 return CubitSimpleAttrib(&cs_list, &d_list, &i_list); 00377 } 00378 00379 void CAEntityId::print() 00380 { 00381 // print info on this attribute 00382 00383 PRINT_INFO("CAEntityId: owner = %s %d: id=%d, color=%d\n", 00384 attribOwnerEntity->class_name(), attribOwnerEntity->id(), 00385 entityId, 0); 00386 }