cgma
OCCHistory.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines