cgma
|
00001 //- Class: CAMergePartner 00002 //- Owner: Greg Nielson 00003 //- Description: Cubit Attribute for merge partners. 00004 //- Checked By: 00005 //- Version: 00006 00007 #include "CAMergePartner.hpp" 00008 #include "DLIList.hpp" 00009 #include "SDLCAMergePartnerList.hpp" 00010 #include "RefEntity.hpp" 00011 #include "RefFace.hpp" 00012 #include "RefEdge.hpp" 00013 #include "RefVertex.hpp" 00014 #include "TDCompare.hpp" 00015 #include "TDUniqueId.hpp" 00016 #include "MergeTool.hpp" 00017 #include "CastTo.hpp" 00018 #include "CubitAttribUser.hpp" 00019 #include "GeometryQueryTool.hpp" 00020 #include "RefVolume.hpp" 00021 #include "TopologyBridge.hpp" 00022 00023 #include <stdlib.h> 00024 #include <time.h> 00025 00026 // factory function 00027 CubitAttrib* CAMergePartner_creator(RefEntity* entity, const CubitSimpleAttrib &p_csa) 00028 { 00029 return new CAMergePartner(entity, p_csa); 00030 } 00031 00032 CAMergePartner::CAMergePartner(RefEntity* new_attrib_owner, 00033 const CubitSimpleAttrib &csa_ptr) 00034 : CubitAttrib(new_attrib_owner) 00035 { 00036 initialize(); 00037 00038 if(!csa_ptr.isEmpty()) 00039 { 00040 int i_temp = csa_ptr.int_data_list()[0]; 00041 mergeID = i_temp; 00042 if( csa_ptr.int_data_list().size() > 1 ) 00043 { 00044 i_temp = csa_ptr.int_data_list()[1]; 00045 switch( i_temp ) { 00046 case -1: bridge_sense_ = CUBIT_REVERSED; break; 00047 case 1: bridge_sense_ = CUBIT_FORWARD; break; 00048 case 0: bridge_sense_ = CUBIT_UNKNOWN; break; 00049 default: bridge_sense_ = CUBIT_UNKNOWN; assert(0); 00050 } 00051 } 00052 } 00053 } 00054 00055 CAMergePartner::~CAMergePartner() 00056 { 00057 // 00058 mergeID = 0; 00059 } 00060 00061 00062 void CAMergePartner::initialize() 00063 { 00064 mergeID = -1; 00065 bridge_sense_ = CUBIT_UNKNOWN; 00066 isSurvivor = 0; 00067 } 00068 00069 00070 CubitStatus CAMergePartner::actuate() 00071 { 00072 hasActuated = CUBIT_TRUE; 00073 return CUBIT_SUCCESS; 00074 //We don't need to actuate this attribute here since the merging 00075 //happens in GeometryQueryTool::check_mergeable_refentity. 00076 00077 /* 00078 if (hasActuated == CUBIT_TRUE) return CUBIT_SUCCESS; 00079 00080 BasicTopologyEntity * bte_ptr = CAST_TO(attribOwnerEntity,BasicTopologyEntity); 00081 if (bte_ptr == NULL || bte_ptr->deactivated() == CUBIT_TRUE) 00082 return CUBIT_FAILURE; 00083 00084 DLIList<RefEntity*> merge_list; 00085 //merge_prepare(merge_list); 00086 merge_list.append_unique(attribOwnerEntity); 00087 00088 CubitStatus result = CUBIT_SUCCESS; 00089 00090 if (merge_list.size() > 1) 00091 result = (NULL == MergeTool::instance()->force_merge(merge_list)) 00092 ? CUBIT_FAILURE : CUBIT_SUCCESS; 00093 00094 if( result ) 00095 { 00096 hasActuated = CUBIT_TRUE; 00097 } 00098 00099 return result; */ 00100 } 00101 00102 void CAMergePartner::merge_prepare(DLIList<RefEntity*> &merge_list) 00103 { 00104 DLIList<CubitAttrib*> my_ca_list; 00105 CAMergePartner *my_camp_ptr; 00106 RefEntity* re_ptr; 00107 00108 // get all the merge partner attributes that are on my owner 00109 attribOwnerEntity->find_cubit_attrib_type(CA_MERGE_PARTNER, my_ca_list); 00110 merge_list.clean_out(); 00111 DLIList<ToolDataUser*> td_list, temp_td_list; 00112 int i; 00113 for (i = my_ca_list.size(); i > 0; i--) 00114 { 00115 my_camp_ptr = CAST_TO(my_ca_list.get(),CAMergePartner); 00116 my_ca_list.step(); 00117 td_list.clean_out(); 00118 // get all the objects with this unique id (which is also the merge id) 00119 TDUniqueId::find_td_unique_id(my_camp_ptr->merge_id(), temp_td_list); 00120 td_list += temp_td_list; 00121 } 00122 00123 // now put those entities into the merge_list 00124 for (i = td_list.size(); i > 0; i--) 00125 { 00126 re_ptr = CAST_TO(td_list.get(), RefEntity); 00127 if (re_ptr) 00128 { 00129 CubitAttrib *tmp_attrib = re_ptr->get_cubit_attrib( CA_MERGE_PARTNER, CUBIT_FALSE ); 00130 if( tmp_attrib ) 00131 merge_list.append(re_ptr); 00132 } 00133 td_list.step(); 00134 } 00135 00136 // Now get bridge sense for each entity in list. 00137 // Add this entity to list, too. 00138 merge_list.append( attribOwnerEntity ); 00139 for( i = merge_list.size(); i--; ) 00140 { 00141 RefEntity* ent = merge_list.get_and_step(); 00142 TopologyEntity* te = dynamic_cast<TopologyEntity*>(ent); 00143 if( te->bridge_manager()->number_of_bridges() != 1 ) 00144 continue; 00145 00146 my_ca_list.clean_out(); 00147 ent->find_cubit_attrib_type(CA_MERGE_PARTNER, my_ca_list); 00148 assert( my_ca_list.size() < 2); 00149 if( !my_ca_list.size() ) 00150 continue; 00151 00152 my_camp_ptr = dynamic_cast<CAMergePartner*>(my_ca_list.get()); 00153 if( my_camp_ptr->bridge_sense() == CUBIT_UNKNOWN ) 00154 continue; 00155 } 00156 merge_list.pop(); // take attribOwnerEntity back off list 00157 00158 return; 00159 } 00160 00161 CubitStatus CAMergePartner::actuate_list(DLIList<RefEntity*> entity_list) 00162 { 00163 00164 // given a list of ref entities (usually all entities of a given type), 00165 // actuate the camp's on those entities 00166 RefEntity *ref_ent, *keeper; 00167 DLIList<CubitAttrib*> ca_list; 00168 DLIList<TopologyBridge*> bridge_list(entity_list.size()); 00169 SDLCAMergePartnerList sorted_camp_list; 00170 int i; 00171 for(i = entity_list.size(); i > 0; i--) 00172 { 00173 ref_ent = entity_list.get_and_step(); 00174 ca_list.clean_out(); 00175 ref_ent->find_cubit_attrib_type(CA_MERGE_PARTNER, ca_list); 00176 assert(ca_list.size() < 2); // There should only be one 00177 // merge partner per entity 00178 if(ca_list.size() > 0) 00179 { 00180 CAMergePartner* attrib = dynamic_cast<CAMergePartner*>(ca_list.get()); 00181 sorted_camp_list.append( attrib ); 00182 TopologyEntity* te = dynamic_cast<TopologyEntity*>(ref_ent); 00183 TopologyBridge* bridge = te->bridge_manager()->topology_bridge(); 00184 bridge_list.append(bridge); 00185 } 00186 } 00187 sorted_camp_list.sort(); 00188 sorted_camp_list.reset(); 00189 00190 if (DEBUG_FLAG(90)) { 00191 for (i = sorted_camp_list.size(); i > 0; i--) { 00192 CAMergePartner *camp_ptr = sorted_camp_list.get_and_step(); 00193 ref_ent = camp_ptr->attrib_owner(); 00194 PRINT_DEBUG_90("%s %d, unique id = %d\n", ref_ent->class_name(), 00195 ref_ent->id(), camp_ptr->merge_id()); 00196 } 00197 } 00198 00199 // now go through all the camp's for the entity list; peel off 00200 // camp's with the same id, and merge the associated entities together 00201 while (sorted_camp_list.size() > 0) 00202 { 00203 DLIList<RefEntity*> refent_list; 00204 DLIList<CubitAttrib*> camp_list; 00205 keeper = NULL; 00206 00207 // get the next list of entities with the same camp id 00208 sorted_camp_list.last(); 00209 CAMergePartner *camp_ptr = sorted_camp_list.remove(); 00210 sorted_camp_list.back(); 00211 camp_list.append(camp_ptr); 00212 int current_id = camp_ptr->merge_id(); 00213 while (sorted_camp_list.size() > 0 && 00214 sorted_camp_list.get()->merge_id() == current_id) { 00215 camp_list.append(sorted_camp_list.remove()); 00216 sorted_camp_list.back(); 00217 } 00218 00219 if (camp_list.size() == 1) continue; 00220 00221 CubitBoolean has_actuated = camp_list.get()->has_actuated(); 00222 00223 // check the has actuated flag; if one is set, they all should be; 00224 // also, compile list of ref entities while we're at it 00225 for (current_id = camp_list.size(); current_id > 0; current_id--) { 00226 ref_ent = camp_list.get()->attrib_owner(); 00227 refent_list.append(ref_ent); 00228 if (!keeper || ref_ent->id() < keeper->id()) keeper = ref_ent; 00229 assert(camp_list.get()->has_actuated() == has_actuated); 00230 camp_list.step(); 00231 } 00232 00233 // if they have already actuated, go on to next ones 00234 if (has_actuated == CUBIT_TRUE) continue; 00235 00236 // otherwise merge 00237 if(refent_list.size() > 1) 00238 MergeTool::instance()->force_merge(refent_list); 00239 00240 // remove the cubit attribute from the surviving parent 00241 keeper->remove_cubit_attrib(CA_MERGE_PARTNER); 00242 00243 } // loop over existing camp's 00244 00245 return CUBIT_SUCCESS; 00246 } 00247 00248 CubitStatus CAMergePartner::update() 00249 { 00250 if (hasUpdated) return CUBIT_SUCCESS; 00251 00252 // set the updated flag 00253 hasUpdated = CUBIT_TRUE; 00254 BasicTopologyEntity* bte_ptr = CAST_TO(attribOwnerEntity, BasicTopologyEntity); 00255 00256 if( (bte_ptr == NULL) || (dynamic_cast<RefVolume*>(bte_ptr) != NULL)) 00257 { 00258 delete_attrib(CUBIT_TRUE); 00259 } 00260 else if( (bte_ptr->bridge_manager()->number_of_bridges() == 1) && 00261 (bte_ptr->bridge_manager()->topology_bridge()->bridge_sense() != CUBIT_REVERSED) ) 00262 { 00263 delete_attrib(CUBIT_TRUE); 00264 } 00265 else 00266 { 00267 // get the merge id from the TDUniqueId for the owner entity 00268 mergeID = TDUniqueId::get_unique_id(attribOwnerEntity); 00269 bridge_sense_ = CUBIT_UNKNOWN; 00270 isSurvivor = 0; 00271 } 00272 00273 return CUBIT_SUCCESS; 00274 } 00275 00276 CubitSimpleAttrib CAMergePartner::cubit_simple_attrib() 00277 { 00278 std::vector<CubitString> cs_list; 00279 std::vector<double> d_list; 00280 std::vector<int> i_list; 00281 00282 i_list.push_back(mergeID); 00283 cs_list.push_back(att_internal_name()); 00284 00285 return CubitSimpleAttrib(&cs_list, &d_list, &i_list); 00286 } 00287 00288 void CAMergePartner::set_survivor( CubitSimpleAttrib& csa, int is_survivor ) 00289 { 00290 //get the list we want to modify from the CSA 00291 std::vector<int>& data = csa.int_data_list(); 00292 00293 //change or append? 00294 if( data.size() >= 4 ) 00295 { 00296 data[3] = is_survivor; 00297 } 00298 else 00299 { 00300 assert( data.size() == 3 ); 00301 data.push_back(is_survivor); 00302 } 00303 } 00304 00305 void CAMergePartner::set_bridge_sense( CubitSimpleAttrib& csa, CubitSense sense ) 00306 { 00307 //encode/decode sense as: 00308 // CUBIT_FORWARD : 1 00309 // CUBIT_REVERSE : -1 00310 // CUBIT_UNKNOWN : 0 00311 int i = 0; 00312 switch( sense ) { 00313 case CUBIT_FORWARD : i = 1; break; 00314 case CUBIT_REVERSED : i = -1; break; 00315 case CUBIT_UNKNOWN : i = 0; break; 00316 default: assert(0); 00317 } 00318 00319 //get the list we want to modify from the CSA 00320 std::vector<int>& data = csa.int_data_list(); 00321 00322 //change or append? 00323 if( data.size() >= 2 ) 00324 { 00325 data[1] = i; 00326 } 00327 else 00328 { 00329 assert( data.size() == 1 ); 00330 data.push_back(i); 00331 } 00332 } 00333 CubitBoolean CAMergePartner::is_survivor( const CubitSimpleAttrib& csa ) 00334 { 00335 const std::vector<int>& data = csa.int_data_list(); 00336 if( data.size() >= 4) 00337 { 00338 int i = data[3]; 00339 if( i == 1 ) 00340 return true; 00341 } 00342 return false; 00343 } 00344 00345 00346 CubitSense CAMergePartner::get_bridge_sense( const CubitSimpleAttrib& csa ) 00347 { 00348 const std::vector<int>& data = csa.int_data_list(); 00349 if( data.size() >= 2) 00350 { 00351 int i = data[1]; 00352 switch(i) { 00353 case 1: return CUBIT_FORWARD; 00354 case -1: return CUBIT_REVERSED; 00355 default: assert(0); // if -DNDEBUG, fall through to unknown 00356 case 0: return CUBIT_UNKNOWN; 00357 } 00358 } 00359 00360 return CUBIT_UNKNOWN; 00361 } 00362 00363 void CAMergePartner::set_saved_id( CubitSimpleAttrib& csa, int id ) 00364 { 00365 //get the list we want to modify from the CSA 00366 std::vector<int>& data = csa.int_data_list(); 00367 00368 // ID goes after bridge sense, so save bridge sense first 00369 if (data.size() == 1) 00370 set_bridge_sense( csa, CUBIT_UNKNOWN ); 00371 00372 // change? 00373 if (data.size() > 2 ) 00374 { 00375 data[2] = id; 00376 } 00377 // set? 00378 else 00379 { 00380 assert(data.size() == 2); 00381 data.push_back(id); 00382 } 00383 } 00384 00385 int CAMergePartner::get_saved_id( const CubitSimpleAttrib& csa ) 00386 { 00387 //get the list we want to modify from the CSA 00388 const std::vector<int>& data = csa.int_data_list(); 00389 00390 if (data.size() < 3) 00391 return 0; 00392 00393 return data[2]; 00394 } 00395 00396 00397 00398 void CAMergePartner::print() 00399 { 00400 PRINT_INFO("Attribute MERGE_PARTNER, %s %d: mergeId = %d, sense = %d.\n", 00401 attribOwnerEntity->class_name(), attribOwnerEntity->id(), 00402 mergeID, bridge_sense_); 00403 }