cgma
|
00001 00002 #include "OCCHistory.hpp" 00003 #include "OCCQueryEngine.hpp" 00004 #include "CubitMessage.hpp" 00005 #include "RefEntity.hpp" 00006 //#include "occ_attrib_history.hpp" 00007 #include "CGMHistory.hpp" 00008 #include "GeometryQueryTool.hpp" 00009 00010 /*Here's a brief description of how the history is created in the 00011 * OCC port: 00012 * 1. Create an OCCHistory object. 00013 * 00014 * 2. TopologyBridges are given to the port for modification. From 00015 * the TopologyBridges, get all associated parent and child TopologyBridges. 00016 * From each TopologyBridge, get a) the corresponding RefEntity 00017 * and b) the corresponding TopoDS_Shape(s). 00018 * 00019 * 3. On every OCC TopoDS_Shape, attach an attrib_history attribute. 00020 * The attrib_history basically holds a unique 'tracking' integer. 00021 * 00022 * 4. Populate the refentity_tracking_id_map in the OCCHistory object, with 00023 * pairs, where each pair consists of a RefEntity pointer and it's associated 00024 * tracking id, in #3. 00025 * 00026 * 5. OCC performs the operation(s), making callbacks into the 00027 * occ_attrib_history's overloaded functions. It does the following: 00028 * -For split_owner callbacks, where A is split into A and B, 00029 * put a history attrib on B and add A's tracking integer to B. 00030 * -For merge_owner callbacks, where A and B are merged into A, 00031 * add B's tracking id to A. Now A will have 2 tracking ids 00032 * associated with it. 00033 * -In the copying callback macros, if B has been copied from A, give B 00034 * the tracking id that was in A. 00035 * -For the other callbacks, replace_owner, lop_change_owner, and 00036 * replace_owner_geometry, add an OCCEvent to the OCCHistory object's 00037 * event list. 00038 * 00039 * 6. Once the operation has ended and TopologyBridges have been created 00040 * from the new TopoDS_Shape's (populate_topology_bridges has been called), for 00041 * each TopologyBridge, create a pair consisting of 00042 * a set of tracking ids and a TopologyBridge pointer. 00043 * 00044 * 7. Find pairs in #6 that have any tracking id in common in their sets. 00045 * If you find multiple pairs who's sets in size, you have a subdivision-absorption 00046 * event (n->m). If you only find a single pair that has a set with 00047 * multiple tracking ids in it, you have an absorption event (n->1). If you find 00048 * multiple pairs that all have a single tracking id in their set, you have 00049 * a subdivision event(1->n). And if you only find a single pair with a single 00050 * tracking id in it's set, you have a geometry modified event. 00051 * 00052 * 8. Everytime you gather one of these pair group, in #7, you create a PortEvent 00053 * which ties the original RefEntity pointer(s) to the new TopologyBridge(s). 00054 */ 00055 00056 OCCHistory::OCCHistory() 00057 { 00058 trackingId = -1; 00059 highLevelCopying = false; 00060 } 00061 00062 OCCHistory::~OCCHistory() 00063 { 00064 //OCC_ATTRIB_HISTORY::remove_all_attribs(); 00065 } 00066 00067 void OCCHistory::add_event( const OCCEvent &event ) 00068 { 00069 eventList.push_back( event ); 00070 } 00071 00072 void OCCHistory::add_refentity_tracking_id_pair( RefEntity *ref_ent, int tracking_id ) 00073 { 00074 refentity_tracking_id_map.push_back( 00075 std::pair<RefEntity*, int>( ref_ent, tracking_id)); 00076 } 00077 00078 00079 void OCCHistory::print() 00080 { 00081 /* 00082 std::vector<CGMEvent>::iterator iter = cgmEventList.begin(); 00083 for(; iter != cgmEventList.end(); iter++ ) 00084 { 00085 CGMEvent cgm_event = *iter; 00086 PRINT_INFO("Event type = %s RefEntities ", event_names[ cgm_event.eventType ]); 00087 00088 int i; 00089 for( i=0; i<cgm_event.RefEnts.size(); i++ ) 00090 { 00091 RefEntity *ref_ent = cgm_event.RefEnts[i]; 00092 PRINT_INFO(" %s %d ", ref_ent->class_name(), ref_ent->id() ); 00093 } 00094 PRINT_INFO(" ---> "); 00095 for( i=0; i<cgm_event.TopologyBridges.size(); i++ ) 00096 { 00097 TopologyBridge *tb = cgm_event.TopologyBridges[i]; 00098 PRINT_INFO(" %p", tb ); 00099 } 00100 PRINT_INFO("\n"); 00101 } */ 00102 } 00103 00104 int OCCHistory::generate_next_tracking_id() 00105 { 00106 trackingId++; 00107 return trackingId; 00108 } 00109 00110 void OCCHistory::add_to_tracking_ids_tb_map( std::set<int> &tracking_ids, TopologyBridge *tb ) 00111 { 00112 tracking_ids_to_tb_map.push_back( std::pair< std::set<int>, TopologyBridge*>( tracking_ids, tb ) ); 00113 } 00114 00115 void OCCHistory::create_cgm_history_objects() 00116 { 00117 //look for subdivision-absorption events. 00118 //Look in tracking_ids_to_tb_map for a pair whose vector 00119 //has multiple integers in it. If you find another pair with the 00120 //same integers in it, you've found a subdivision-absorption event. 00121 00122 std::vector< std::pair< std::set<int>, TopologyBridge*> > unrelated_pairs; 00123 std::list< std::pair< std::set<int>, TopologyBridge*> >::iterator iter; 00124 00125 if( highLevelCopying ) 00126 { 00127 while( tracking_ids_to_tb_map.size() ) 00128 { 00129 iter = tracking_ids_to_tb_map.begin(); 00130 00131 std::pair< std::set<int>, TopologyBridge*> pair1 = *iter; 00132 00133 std::vector< std::pair< std::set<int>, TopologyBridge*> > found_pairs; 00134 found_pairs.push_back( pair1 ); 00135 00136 create_port_event( CGMHistory::COPY, found_pairs ); 00137 tracking_ids_to_tb_map.erase( iter++ ); 00138 } 00139 } 00140 else 00141 { 00142 00143 while( tracking_ids_to_tb_map.size() ) 00144 { 00145 iter = tracking_ids_to_tb_map.begin(); 00146 00147 std::pair< std::set<int>, TopologyBridge*> pair1 = *iter; 00148 std::set<int> set1 = pair1.first; 00149 00150 //find all pairs that have a vector that contains any integer in set1, 00151 //and at the same time recursively do the same for the found pairs 00152 //get back a 'found_pairs' list 00153 00154 std::vector< std::pair< std::set<int>, TopologyBridge*> > found_pairs; 00155 found_pairs.push_back( pair1 ); 00156 tracking_ids_to_tb_map.erase( iter++ ); 00157 collect_relevant_pairs( set1, found_pairs ); 00158 00159 //if the found_pairs just contains the original pair 00160 //it's a simple absorption 00161 std::vector< std::pair< std::set<int>, TopologyBridge*> >::iterator vec_iter; 00162 std::pair< std::set<int>, TopologyBridge*> tmp_pair; 00163 if( found_pairs.size() == 1 ) 00164 { 00165 //if the single set contains multiple integers, 00166 //it's a simple absorption 00167 00168 vec_iter = found_pairs.begin(); 00169 tmp_pair = *vec_iter; 00170 std::set<int> tmp_set = tmp_pair.first; 00171 if( tmp_set.size() > 1 ) 00172 create_port_event( CGMHistory::ABSORPTION, found_pairs ); 00173 else 00174 unrelated_pairs.push_back( pair1 ); 00175 } 00176 else 00177 { 00178 //if the found_pairs all have exactly one integer in their sets, 00179 //it's a simple subdivision 00180 vec_iter = found_pairs.begin(); 00181 tmp_pair = *vec_iter; 00182 std::set<int> tmp_set = tmp_pair.first; 00183 int size_of_set = tmp_set.size(); 00184 vec_iter++; 00185 bool varying_sizes = false; 00186 for(; vec_iter != found_pairs.end(); vec_iter++ ) 00187 { 00188 tmp_pair = *vec_iter; 00189 tmp_set = tmp_pair.first; 00190 if( size_of_set != tmp_set.size() ) 00191 { 00192 varying_sizes = true; 00193 break; 00194 } 00195 } 00196 00197 if( varying_sizes ) 00198 create_port_event( CGMHistory::SUBDIVISION_ABSORPTION, found_pairs ); 00199 else 00200 create_port_event( CGMHistory::SUBDIVISION, found_pairs ); 00201 } 00202 } 00203 } 00204 00205 std::vector< std::pair< std::set<int>, TopologyBridge*> >::iterator vec_iter1; 00206 vec_iter1 = unrelated_pairs.begin(); 00207 for(; vec_iter1 != unrelated_pairs.end(); vec_iter1++ ) 00208 { 00209 std::set<int> set1 = (*vec_iter1).first; 00210 if( set1.size() == 0 ) 00211 continue; 00212 int tracking_id = *set1.begin(); 00213 00214 std::vector<OCCEvent>::iterator vec_iter2 = eventList.begin(); 00215 for(; vec_iter2 != eventList.end(); vec_iter2++ ) 00216 { 00217 OCCEvent event = (*vec_iter2); 00218 if( event.eventType == CGMHistory::GEOMETRY_CHANGED || 00219 event.eventType == CGMHistory::CUT ) 00220 { 00221 int other_tracking_id = event.entities[0]; 00222 00223 if( tracking_id == other_tracking_id ) 00224 { 00225 TopologyBridge *tb = (*vec_iter1).second; 00226 std::pair<RefEntity*, int> tmp_pair = refentity_tracking_id_map[tracking_id]; 00227 RefEntity* ref_ent = tmp_pair.first; 00228 CGMHistory::PortEvent port_event( event.eventType ); 00229 port_event.RefEnts.push_back( ref_ent ); 00230 port_event.TopologyBridges.push_back( tb ); 00231 GeometryQueryTool::instance()->history().add_port_event( port_event ); 00232 break; 00233 } 00234 } 00235 } 00236 } 00237 } 00238 00239 00240 void OCCHistory::collect_relevant_pairs( std::set<int> &seed_set, 00241 std::vector< std::pair< std::set<int>, TopologyBridge*> > &found_pairs ) 00242 { 00243 00244 std::list< std::pair< std::set<int>, TopologyBridge*> >::iterator iter; 00245 iter = tracking_ids_to_tb_map.begin(); 00246 00247 for(; iter != tracking_ids_to_tb_map.end(); iter++ ) 00248 { 00249 std::pair< std::set<int>, TopologyBridge*> my_pair1 = *iter; 00250 std::set<int> set1 = my_pair1.first; 00251 00252 if( set1.empty() ) 00253 continue; 00254 00255 std::set<int>::iterator iter1, iter2; 00256 //does set1 contain any integers that are in the seed set? 00257 //if so, remove the pair from the list and add it to 'found_pairs' 00258 iter1 = set1.begin(); 00259 bool pair_found = false; 00260 for(; iter1 != set1.end(); iter1++ ) 00261 { 00262 int int1 = *iter1; 00263 00264 for( iter2 = seed_set.begin(); iter2 != seed_set.end(); iter2++ ) 00265 { 00266 int int2 = *iter2; 00267 00268 if( int2 == int1 ) 00269 { 00270 //clear out the set 00271 std::set<int> &tmp_set = (*iter).first; 00272 tmp_set.clear(); 00273 00274 found_pairs.push_back( my_pair1 ); 00275 //tracking_ids_to_tb_map.erase( iter++ ); 00276 collect_relevant_pairs( set1, found_pairs ); 00277 pair_found = true; 00278 break; 00279 } 00280 } 00281 if( pair_found ) 00282 break; 00283 } 00284 // if( pair_found == false ) 00285 // iter++; 00286 } 00287 } 00288 00289 00290 void OCCHistory::create_port_event( CGMHistory::EventType event_type, 00291 std::vector< std::pair< std::set<int>, TopologyBridge*> > &found_pairs ) 00292 { 00293 CGMHistory::PortEvent port_event( event_type ); 00294 00295 //add all TBs to the event's TB list 00296 std::vector< std::pair< std::set<int>, TopologyBridge*> >::iterator vec_iter; 00297 vec_iter = found_pairs.begin(); 00298 std::pair< std::set<int>, TopologyBridge*> tmp_pair; 00299 DLIList<RefEntity*> ref_ent_list; 00300 DLIList<TopologyBridge*> tb_list; 00301 for(; vec_iter != found_pairs.end(); vec_iter++ ) 00302 { 00303 tmp_pair = *vec_iter; 00304 TopologyBridge *tb = tmp_pair.second; 00305 tb_list.append( tb ); 00306 00307 std::set<int> tmp_set = tmp_pair.first; 00308 std::set<int>::iterator iter=tmp_set.begin(); 00309 for(; iter != tmp_set.end(); iter++ ) 00310 { 00311 int index = *iter; 00312 std::pair<RefEntity*, int> pair2 = refentity_tracking_id_map[index]; 00313 RefEntity* ref_ent = pair2.first; 00314 ref_ent_list.append( ref_ent ); 00315 } 00316 } 00317 00318 //uniquify the lists...then append them to the CGMEvent's vector 00319 ref_ent_list.uniquify_unordered(); 00320 tb_list.uniquify_unordered(); 00321 00322 int i; 00323 for(i=ref_ent_list.size(); i--; ) 00324 port_event.RefEnts.push_back( ref_ent_list.get_and_step() ); 00325 for(i=tb_list.size(); i--; ) 00326 port_event.TopologyBridges.push_back( tb_list.get_and_step() ); 00327 00328 GeometryQueryTool::instance()->history().add_port_event( port_event ); 00329 } 00330 00331 00332 void OCCHistory::add_TopoDS_Shape( TopoDS_Shape *entity ) 00333 { 00334 all_ents.push_back( entity ); 00335 } 00336 00337 void OCCHistory::remove_attributes() 00338 { 00339 /* 00340 int i; 00341 for( i=0; i<all_ents.size(); i++ ) 00342 { 00343 OCC_ATTRIB_HISTORY *att = OCC_ATTRIB_HISTORY::get_history_attrib( all_ents[i], false ); 00344 if( att ) 00345 att->lose(); 00346 } 00347 */ 00348 } 00349 00350 /* 00351 void OCCHistory::collect_events_and_find_resultant_uniqueids( int source_id, 00352 DLIList<OCCEvent*> &events, 00353 DLIList<int> &result_unique_ids ) 00354 { 00355 //get an OCCEvent w/ 'entity' in 'other_entities' list 00356 std::vector<OCCEvent>::iterator iter; 00357 bool found_entity = false; 00358 for(iter=eventList.begin(); iter != eventList.end(); iter++ ) 00359 { 00360 OCCEvent *tmp_event = &(*iter); 00361 00362 //ignore events that are already in the list 00363 if( events.is_in_list( tmp_event ) ) 00364 continue; 00365 00366 //search 'entities' list 00367 if( tmp_event->eventType == SUBDIVISION || 00368 tmp_event->eventType == ABSORPTION || 00369 tmp_event->eventType == COPY ) 00370 { 00371 int k; 00372 for(k=0; k<tmp_event->entities.size(); k++ ) 00373 { 00374 if( source_id == tmp_event->entities[k] ) 00375 { 00376 found_entity = true; 00377 //we found the ENTITY...now get ents in 'entities' list 00378 //and look for them 00379 events.append( tmp_event ); 00380 int i; 00381 for( i=0; i<tmp_event->other_entities.size(); i++ ) 00382 collect_events_and_find_resultant_uniqueids( tmp_event->other_entities[i], 00383 events, result_unique_ids ); 00384 } 00385 } 00386 } 00387 else if( tmp_event->eventType == GEOMETRY_CHANGED ) 00388 { 00389 if( source_id == tmp_event->entities[0] ) 00390 { 00391 events.append( tmp_event ); 00392 collect_events_and_find_resultant_uniqueids( tmp_event->entities[0], 00393 events, result_unique_ids); 00394 } 00395 } 00396 } 00397 00398 //so you can't go any further, traversing the events...see if this one is in 00399 //the results list...if so, append it 00400 if( false == found_entity ) 00401 { 00402 if( resultUniqueIds.find( source_id ) != resultUniqueIds.end() ) 00403 result_unique_ids.append( source_id ); 00404 } 00405 } */ 00406 00407 00408 /* 00409 void OCCHistory::collect_events_and_find_original_uniqueids( int source_id, 00410 DLIList<OCCEvent*> &events, 00411 DLIList<int> &original_unique_ids) 00412 { 00413 00414 //get an OCCEvent w/ 'entity' in 'other_entities' list 00415 std::vector<OCCEvent>::iterator iter; 00416 bool found_entity = false; 00417 for(iter=eventList.begin(); iter != eventList.end(); iter++ ) 00418 { 00419 OCCEvent *tmp_event = &(*iter); 00420 00421 //ignore events that are already in the list 00422 if( events.is_in_list( tmp_event ) ) 00423 continue; 00424 00425 //search 'other_entities' list 00426 if( tmp_event->eventType == SUBDIVISION || 00427 tmp_event->eventType == ABSORPTION || 00428 tmp_event->eventType == COPY ) 00429 { 00430 int k; 00431 for(k=0; k<tmp_event->other_entities.size(); k++ ) 00432 { 00433 if( source_id == tmp_event->other_entities[k] ) 00434 { 00435 found_entity = true; 00436 //we found the ENTITY...now get ents in 'entities' list 00437 //and look for them 00438 events.append( tmp_event ); 00439 int i; 00440 for( i=0; i<tmp_event->entities.size(); i++ ) 00441 collect_events_and_find_original_uniqueids( tmp_event->entities[i], events, original_unique_ids ); 00442 } 00443 } 00444 } 00445 else if( tmp_event->eventType == GEOMETRY_CHANGED ) 00446 { 00447 if( source_id == tmp_event->entities[0] ) 00448 { 00449 events.append( tmp_event ); 00450 collect_events_and_find_original_uniqueids( tmp_event->entities[0], events, original_unique_ids ); 00451 } 00452 } 00453 } 00454 00455 if( false == found_entity ) 00456 original_unique_ids.append( source_id ); 00457 } */ 00458 00459 00460 /* 00461 void OCCHistory::map_back_to_ref_entity( TopologyBridge *topology_bridge, 00462 RefEntity *ref_entity, 00463 OCCHistory::EventType event_type ) 00464 { 00465 00466 ENTITY *entity = OCCQueryEngine::instance()->get_ENTITY_of_entity( topology_bridge ); 00467 00468 ATTRIB_HISTORY *tmp_attrib = ATTRIB_HISTORY::get_history_attrib( entity ); 00469 if( !tmp_attrib ) 00470 return; 00471 00472 int source_id = tmp_attrib->get_unique_id(); 00473 00474 DLIList<OCCEvent*> events; 00475 DLIList<int> original_unique_ids; 00476 00477 //starting from the result ENTITY, work your waying up the events, 00478 // to the original ENTITY 00479 collect_events_and_find_original_uniqueids( source_id, events, original_unique_ids ); 00480 00481 //PRINT_INFO("source entity = %p ", entity ); 00482 00483 //PRINT_INFO("target_ents = "); 00484 int i; 00485 //for( i=original_ents.size(); i--; ) 00486 // PRINT_INFO("%p ", original_ents.get_and_step() ); 00487 //PRINT_INFO("\n"); 00488 00489 00490 EventType my_event_type = NO_EVENT; 00491 DLIList<RefEntity*> original_ref_ents; 00492 00493 //from the supposed original ENTITY, 00494 //find the corresponding RefEntity in refentity_ENTITY_multimap 00495 for( i=original_unique_ids.size(); i--; ) 00496 { 00497 int original_id = original_unique_ids.get_and_step(); 00498 00499 std::multimap<RefEntity*, int>::iterator iter = refentity_uniqueid_multimap.begin(); 00500 for( ; iter != refentity_uniqueid_multimap.end(); iter++ ) 00501 { 00502 int tmp_id = (*iter).second; 00503 if( original_id == tmp_id ) 00504 { 00505 //determine what type of event you have 00506 int j; 00507 for( j=events.size(); j--; ) 00508 { 00509 OCCEvent *event = events.get_and_step(); 00510 00511 //ignore copy events for now 00512 if( event->eventType != COPY && 00513 event->eventType != NO_EVENT ) 00514 { 00515 00516 //split events take priority over 00517 if( event->eventType > my_event_type ) 00518 my_event_type = event->eventType; 00519 } 00520 } 00521 RefEntity *original_ref_ent = (*iter).first; 00522 original_ref_ents.append( original_ref_ent ); 00523 } 00524 } 00525 } 00526 00527 if( my_event_type != NO_EVENT ) 00528 { 00529 PRINT_INFO("Event type = %s RefEntity = %s %d Result ENTITY = %p\n", 00530 event_names[my_event_type], original_ref_ents.get()->class_name(), 00531 original_ref_ents.get()->id(), entity ); 00532 00533 CGMEvent tmp_event; 00534 tmp_event.eventType = my_event_type; 00535 for( i=original_ref_ents.size(); i--; ) 00536 tmp_event.RefEnts.push_back( original_ref_ents.get_and_step() ); 00537 00538 tmp_event.TopologyBridges.push_back( topology_bridge ); 00539 00540 cgmEventList.push_back( tmp_event ); 00541 } 00542 00543 }*/ 00544 00545 /*Here's a brief description of how the history is created in the 00546 * OCC port: 00547 * 1. Create an OCCHistory object. 00548 * 00549 * 2. Create a RefEnity to ENTITY multimap in the OCCHistory object: 00550 * TopologyBridges are given to the port for modification. From 00551 * the TopologyBridges, get all associated parent and child TopologyBridges. 00552 * From each TopologyBridge, get a) the corresponding RefEntity and b) the 00553 * corresponding TopoDS_Shape(s). Put them in 'refentity_ENTITY_multimap', 00554 * where the RefEntity is the key and the TopoDS_Shape(s) is the data. 00555 * 00556 * 3. Attach an occ_attrib_history attribute to every OCC TopoDS_Shape. 00557 * 00558 * 4. OCC preforms the operation(s), making callbacks into the 00559 * occ_attrib_history's overloaded functions. Within these functions, OCCEvents 00560 * are created and added to the OCCHistory object's event list. 00561 * 00562 * 5. Once the operation has ended and TopologyBridges have been created 00563 * from the new TopoDS_Shape, get all TopoDS_Shape off the resulting bodies and 00564 * add them to the OCCHistory's 'resultTopoDS_Shape's' list. 00565 * 00566 * 6. Remove (ignore) any SUBDIVISION events that don't result in multiple 00567 * TopoDS_Shape's in the result body. 00568 * 00569 * 7. For each TopologyBridge, trace your way back through the OCCEvents until 00570 * you can't go any further. With this 'leaf' entity, try to find a 00571 * corresponding RefEntity in the 'refentity_ENTITY_multimap'. 00572 * 00573 * 8. If you found a corresponding RefEntity, create a CGMEvent. 00574 * 00575 * 9. Consolidate CGMEvents of type SUBIDIVISION and ABSORPTION. 00576 * 00577 */ 00578 00579 00580