cgma
CAPartitionVG.cpp
Go to the documentation of this file.
00001 // CAPartitionVG class
00002 
00003 #include <vector>
00004 #include <utility>
00005 #include <algorithm>
00006 
00007 #include "CAPartitionVG.hpp"
00008 #include "TDUniqueId.hpp"
00009 #include "CastTo.hpp"
00010 #include "RefFace.hpp"
00011 #include "RefEdge.hpp"
00012 #include "RefVertex.hpp"
00013 #include "PartitionEntity.hpp"
00014 #include "PartitionTool.hpp"
00015 #include "BasicTopologyEntity.hpp"
00016 #include "PartitionCurve.hpp"
00017 #include "PartitionSurface.hpp"
00018 #include "CAVirtualVG.hpp"
00019 #include "MergeTool.hpp"
00020 
00021 struct my_sort : public std::binary_function< std::pair<double, int>, std::pair<double, int>, bool> {
00022   bool operator() (std::pair<double, int> const& x, std::pair<double, int> const & y ) { return x.first < y.first; }
00023 };
00024 
00025 CubitAttrib* CAPartitionVG_creator(RefEntity* entity, const CubitSimpleAttrib &p_csa)
00026 {
00027   return new CAPartitionVG(entity, p_csa);
00028 }
00029 
00030 CAPartitionVG::CAPartitionVG(RefEntity *owner, const CubitSimpleAttrib &simple_attrib)
00031         : CubitAttrib(owner)
00032 {
00033   numPC = 0;
00034   numPS = 0;
00035 
00036   if(!simple_attrib.isEmpty())
00037   {
00038       // generate a simple attribute containing the data in this CA
00039     const std::vector<int> &i_list = simple_attrib.int_data_list();
00040 
00041     int ioffset = 0;
00042 
00043       // now the integers
00044       // numVP, numVC
00045     numPC = i_list[ioffset++];
00046     numPS = i_list[ioffset++];
00047 
00048       // numBdyCurves
00049     int temp, i, sum = 0;
00050     for (i = numPS; i > 0; i--) {
00051       temp = i_list[ioffset++];
00052       numBdyCurves.append(temp);
00053       sum += temp;
00054     }
00055 
00056       // vgUIDs: 3 for each PC, numPS+sum for PS
00057     for (i = 3*numPC+sum+numPS; i > 0; i--)
00058       vgUIDs.append(i_list[ioffset++]);
00059 
00060 
00061      // If the CubitSimpleAttrib already exists,
00062      // then this attribute is already written
00063     has_written(CUBIT_TRUE);
00064   }
00065 }
00066 
00067 CubitStatus CAPartitionVG::update()
00068 {
00069 /*
00070     // this attribute behaves in a peculiar way: it detects whether the owner
00071     // is itself a partition entity, and if so, adds data about this partition
00072     // entity to the underlying entity
00073 
00074   if (hasUpdated) return CUBIT_SUCCESS;
00075   
00076   assert(attrib_owner() != 0);
00077 
00078   TopologyEntity *topo_entity = CAST_TO(attrib_owner(), TopologyEntity);
00079   assert(topo_entity != 0);
00080   DLIList<TopologyBridge*> bridge_list;
00081   topo_entity->bridge_manager()->get_bridge_list( bridge_list );
00082   for( int i = bridge_list.size(); i--; )
00083   {
00084     TopologyBridge *topo_bridge = bridge_list.get_and_step();
00085     PartitionEntity *partition_entity = CAST_TO(topo_bridge, PartitionEntity);
00086 
00087   if (partition_entity == NULL) {
00088       // this entity isn't a partition entity - if this entity doesn't have any virtual
00089       // entities registered, set delete flag, then exit
00090     if (numPC == 0 && numPS == 0)
00091       delete_attrib(CUBIT_TRUE);
00092     else {
00093       PRINT_INFO("Keeping CA_PARTITION_VG for %s %d\n",
00094                  attrib_owner()->class_name(), attrib_owner()->id());
00095       hasUpdated = CUBIT_TRUE;
00096     }
00097     
00098     continue;
00099   }
00100   
00101     // ok, we have a partition entity; first get the underlying entity, and a CAPVG 
00102     // for that entity
00103   BasicTopologyEntity* bte_ptr = partition_entity->get_underlying_BTE_ptr();
00104   if (!bte_ptr) {
00105     PRINT_ERROR("Couldn't find bound_to\n");
00106     return CUBIT_FAILURE;
00107   }
00108   
00109   CAPartitionVG *other_CAPVG = (CAPartitionVG *) bte_ptr->get_cubit_attrib(CA_PARTITION_VG);
00110 
00111     // if that other CAPVG's written flag is set, it's an old one from a
00112     // previous write and needs to be reset
00113   if (other_CAPVG->has_written() == CUBIT_TRUE) {
00114     other_CAPVG->reset();
00115     other_CAPVG->has_written(CUBIT_FALSE);
00116   }
00117 
00118     // now put virtual geometry-specific data on the attribute
00119   PartitionCurve *partition_curve = CAST_TO(partition_entity, PartitionCurve);
00120   PartitionSurface *partition_surface = CAST_TO(partition_entity, PartitionSurface);
00121   
00122   if (partition_curve != NULL) {
00123     other_CAPVG->add_pcurve(partition_curve);
00124     other_CAPVG->delete_attrib(CUBIT_FALSE);
00125   }
00126 
00127   else if (partition_surface != NULL) {
00128     other_CAPVG->add_psurface(partition_surface);
00129     other_CAPVG->delete_attrib(CUBIT_FALSE);
00130   }
00131 
00132   else {
00133     PRINT_ERROR("Shouldn't get here in CAPartitionVG::update.\n");
00134     return CUBIT_FAILURE;
00135   }
00136   }
00137 
00138   hasUpdated = CUBIT_TRUE;
00139   if (numPC == 0 && numPS == 0) delete_attrib(CUBIT_TRUE);
00140   
00141   return CUBIT_SUCCESS;
00142 */ 
00143   delete_attrib(CUBIT_TRUE);
00144   return CUBIT_SUCCESS;
00145 }
00146 
00147 
00148 CubitStatus CAPartitionVG::reset()
00149 {
00150   numPC = 0;
00151   numPS = 0;
00152   
00153   vgUIDs.clean_out();
00154   numBdyCurves.clean_out();
00155   
00156   return CUBIT_SUCCESS;
00157 }
00158 
00159 CubitSimpleAttrib CAPartitionVG::cubit_simple_attrib()
00160 {
00161     // generate a simple attribute containing the data in this CA
00162   std::vector<CubitString> cs_list;
00163   std::vector<double> d_list;
00164   std::vector<int> i_list;
00165 
00166     // first the string
00167   cs_list.push_back(att_internal_name());
00168 
00169     // now the integers
00170     // numVP, numVC
00171   i_list.push_back(numPC);
00172   i_list.push_back(numPS);
00173 
00174     // numBdyCurves
00175   int i;
00176   for (i = numBdyCurves.size(); i > 0; i--)
00177     i_list.push_back(numBdyCurves.get_and_step());
00178 
00179     // vgUIDs
00180   vgUIDs.reset();
00181   for (i = vgUIDs.size(); i > 0; i--)
00182     i_list.push_back(vgUIDs.get_and_step());
00183 
00184   return CubitSimpleAttrib(&cs_list, &d_list, &i_list);
00185 }
00186 
00187 CubitStatus CAPartitionVG::actuate()
00188 {
00189     // actuate this CA
00190 
00191     // actuate partition VG attributes on next-lower order entities
00192   RefEntity *owner = CAST_TO(attrib_owner(), RefEntity);
00193   if (owner->dimension() > 1) {
00194     DLIList<RefEntity*> lower_entities;
00195     owner->get_child_ref_entities(lower_entities);
00196 
00197       // don't check return values here - there may be other CA's hanging
00198       // around unactuated, but we may still be able to actuate later
00199     CubitAttribUser::actuate_cubit_attrib(lower_entities, CA_PARTITION_VG);
00200     CubitAttribUser::actuate_cubit_attrib(lower_entities, CA_VIRTUAL_VG);
00201   }
00202 
00203   //actuate it
00204 
00205     // if this is an edge, now partition it
00206   RefEdge *owner_edge = CAST_TO(owner, RefEdge);
00207   RefFace *owner_face = CAST_TO(owner, RefFace);
00208 
00209   //have to get some of the data from CAVirtualVG in order to partition
00210   //get CA_VIRTUAL_VG attrib associated with this entity
00211   DLIList<CubitAttrib*> vg_attribs;
00212   attrib_owner()->find_cubit_attrib_type( CA_VIRTUAL_VG, vg_attribs );
00213   CAVirtualVG *ca_vg_ptr = NULL;
00214   if( vg_attribs.size() != 0 )
00215     ca_vg_ptr = CAST_TO( vg_attribs.get(), CAVirtualVG );
00216 
00217   DLIList<RefFace*> new_faces;
00218   DLIList<RefEdge*> new_edges;
00219 
00220   int i,j,k;
00221   if (owner_edge) //if an edge has been partitioned 
00222   {
00223     DLIList<RefVertex*> new_vertices;
00224     DLIList<RefEdge*> new_edges;
00225     DLIList<CubitVector*> split_points;
00226       
00227     if( !ca_vg_ptr ) //if NO virtual geometry has been used to partiton this curve
00228     {
00229       //get vertices of curve
00230       DLIList<RefEntity*> lower_entities;
00231       owner->get_child_ref_entities(lower_entities);
00232 
00233       //get the points that are not owned by a vertex  
00234       vgUIDs.reset();
00235       DLIList<RefVertex*> vertices;
00236       for(i=vgUIDs.size()/3; i--;)
00237       {
00238         ToolDataUser *tdu = TDUniqueId::find_td_unique_id(vgUIDs.get_and_step());
00239         RefVertex *s_vert = CAST_TO( tdu, RefVertex ); 
00240         tdu = TDUniqueId::find_td_unique_id(vgUIDs.get_and_step());
00241         RefVertex *e_vert = CAST_TO( tdu, RefVertex ); 
00242       
00243         //get vertices owned by this curve 
00244         if( !lower_entities.move_to( s_vert ) )
00245           vertices.append_unique( s_vert );
00246         if( !lower_entities.move_to( e_vert ) )
00247           vertices.append_unique( e_vert );
00248 
00249         vgUIDs.step();
00250       }
00251       //convert vertices to vectors to split curve
00252       for(i=vertices.size(); i--;)
00253       {
00254         RefVertex *cur_vertex = vertices.get_and_step();
00255         split_points.append( new CubitVector( cur_vertex->coordinates() ) );
00256       }
00257 
00258       //partition the curve with these split points 
00259       split_points.reset(); 
00260       PartitionTool::instance()->partition( owner_edge, split_points,
00261                                             new_vertices, new_edges );
00262       //may need to merge some vertices
00263       vertices += new_vertices;
00264       MergeTool::instance()->merge_refvertices( vertices );
00265 
00266     }
00267     else //virtual geometry HAS been used to partiton this curve
00268     {
00269       split_points = ca_vg_ptr->posVector;
00270       DLIList<int>vertex_unique_ids = ca_vg_ptr->vgUIDs;
00271       std::vector< std::pair<double, int> > list_of_pairs;
00272 
00273       //before partitioning edge, reorder split points, from lowest u to 
00274       //highest u; we use a pair so that the corresponding uids are reordered as well 
00275       for( i=split_points.size(); i--;)
00276       {
00277         CubitVector *split_point = split_points.get_and_step();
00278         double u_param = owner_edge->u_from_position( *split_point );
00279         int uuid = vertex_unique_ids.get_and_step();
00280         std::pair<double, int> my_pair;
00281         my_pair.first = u_param;
00282         my_pair.second = uuid;
00283         list_of_pairs.push_back( my_pair );
00284       }
00285       
00286       std::sort(list_of_pairs.begin(), list_of_pairs.end(), my_sort() ); 
00287 
00288       //partition the curve with these split points 
00289       split_points.reset(); 
00290       PartitionTool::instance()->partition( owner_edge, split_points,
00291                                             new_vertices, new_edges );
00292          
00293       assert( list_of_pairs.size() == (unsigned int)new_vertices.size() );
00294       //associate the vertex uuids with the new vertices 
00295       new_vertices.reset();
00296       vertex_unique_ids.reset();
00297       std::vector< std::pair<double, int> >::iterator iter = list_of_pairs.begin();
00298       for( i=new_vertices.size(); i--; )
00299       {
00300         new TDUniqueId( new_vertices.get_and_step(), (*iter).second );
00301         iter++;
00302       }
00303     }
00304 
00305     //associate the curve uuids with the new curve 
00306     new_edges.reset();
00307     RefEdge* ref_edge;
00308     vgUIDs.reset();
00309     for( i=new_edges.size(); i--; )
00310     {
00311       ref_edge = new_edges.get_and_step();
00312       //get uuids of start and end vertices on curve
00313       RefVertex *start_vertex = ref_edge->start_vertex();
00314       RefVertex *end_vertex = ref_edge->end_vertex();
00315 
00316       int s_vert_uuid = TDUniqueId::get_unique_id( start_vertex );
00317       int e_vert_uuid = TDUniqueId::get_unique_id( end_vertex );
00318       
00319       for( j=vgUIDs.size(); j--;)
00320       { 
00321         int s_uuid = vgUIDs.get_and_step();
00322         int e_uuid = vgUIDs.get_and_step();
00323         if( (s_vert_uuid == s_uuid && e_vert_uuid == e_uuid ) ||
00324             (e_vert_uuid == s_uuid && s_vert_uuid == e_uuid ) )
00325         {
00326          new TDUniqueId( ref_edge, vgUIDs.get_and_step() );
00327          break;
00328         }
00329         else
00330           vgUIDs.step();
00331       }
00332     }
00333   }
00334   else if (owner_face)  //partition a surface
00335   {
00336     DLIList<RefFace*> input_faces;
00337     input_faces.append( owner_face );
00338     DLIList<CubitVector*> segments;
00339 
00340     //for each virtual curve used to partition surface
00341     ca_vg_ptr->numVCPoints.reset();
00342     ca_vg_ptr->posVector.reset();
00343     ca_vg_ptr->vgUIDs.step( ca_vg_ptr->numVV );
00344     for( i=ca_vg_ptr->numVC; i--;)
00345     {
00346       //get coordinates of start/end vertices of virtual curve
00347       ToolDataUser *tdu = TDUniqueId::find_td_unique_id(ca_vg_ptr->vgUIDs.get_and_step());
00348       RefVertex *s_vert = CAST_TO( tdu, RefVertex ); 
00349       tdu = TDUniqueId::find_td_unique_id(ca_vg_ptr->vgUIDs.get_and_step());
00350       RefVertex *e_vert = CAST_TO( tdu, RefVertex ); 
00351       DLIList<RefVertex*> vertices;
00352 
00353       CubitVector *vec1, *vec2;
00354       if( s_vert)
00355       {
00356         vec1 = new CubitVector(s_vert->coordinates());
00357         vertices.append( s_vert );
00358       }
00359 
00360       else
00361         vec1 = new CubitVector( *(ca_vg_ptr->posVector.get() ));
00362       
00363       segments.append( vec1 );
00364 
00365       if( e_vert)
00366       {
00367         vec2 = new CubitVector(e_vert->coordinates());
00368         vertices.append( e_vert );
00369       }
00370       else
00371         vec2 = new CubitVector( *(ca_vg_ptr->posVector.get() ));
00372 
00373       //append any intermediate segments
00374       for( j=ca_vg_ptr->numVCPoints.get_and_step(); j--; ) 
00375         segments.append( ca_vg_ptr->posVector.get_and_step() );
00376 
00377       segments.append( vec2 );
00378       //partition the surf
00379       new_edges.clean_out();
00380       new_faces.clean_out();
00381       PartitionTool::instance()->insert_edge( input_faces, segments,
00382                                               new_faces, new_edges);
00383 
00384       //may need to merge some vertices
00385       DLIList<RefVertex*> verts_to_merge;
00386       for( j=new_edges.size(); j--;)
00387       {
00388         verts_to_merge.append( new_edges.get()->start_vertex() );
00389         verts_to_merge.append( new_edges.get()->end_vertex() );
00390       }
00391       verts_to_merge += vertices;
00392       verts_to_merge.uniquify_unordered();
00393 
00394       MergeTool::instance()->merge_refvertices( verts_to_merge  );
00395 
00396       //give new edge uuids
00397       new_edges.reset();
00398       for( j=new_edges.size(); j--;)
00399         new TDUniqueId( new_edges.get_and_step(), ca_vg_ptr->vgUIDs.get_and_step() );
00400       
00401       delete vec1;
00402       delete vec2;
00403       segments.clean_out();
00404     
00405     
00406     //associate the face uuids with the new faces
00407     new_faces.reset();
00408     RefFace* ref_face;
00409     vgUIDs.reset();
00410     for( j=new_faces.size(); j--; )
00411     {
00412       ref_face = new_faces.get_and_step();
00413 
00414       //get uuids of each edge in surface   
00415       DLIList<RefEdge*> edges;
00416       ref_face->ref_edges( edges );
00417       DLIList<int> edge_uuids;
00418 
00419       edges.reset();
00420       for( k=edges.size(); k--;)
00421         edge_uuids.append( TDUniqueId::get_unique_id( edges.get_and_step() ));
00422 
00423       //look at all the groups of boundary edges of each surface
00424       vgUIDs.reset();
00425       for( k=numBdyCurves.size(); k--;)
00426       {
00427         int kk;
00428         DLIList<int> bdy_curve_uuids;
00429         int num_bdy_curves = numBdyCurves.get_and_step();
00430         if( edge_uuids.size() != num_bdy_curves )
00431           continue;
00432         for( kk=num_bdy_curves; kk--;)
00433           bdy_curve_uuids.append( vgUIDs.get_and_step());
00434               
00435         CubitBoolean match = CUBIT_TRUE;
00436         kk=num_bdy_curves;
00437         while( kk && match )
00438         {
00439           kk--;
00440           if( !bdy_curve_uuids.move_to( edge_uuids.get_and_step() ) )
00441           {
00442             match = CUBIT_FALSE; 
00443             break;
00444           }
00445         }
00446         if( match )
00447         {
00448           new TDUniqueId( ref_face, vgUIDs.get() );
00449           break;
00450         }
00451         vgUIDs.step();
00452       }
00453     }
00454 
00455     input_faces.clean_out();
00456     input_faces += new_faces;
00457 
00458     }
00459   }
00460  
00461   hasActuated = CUBIT_TRUE;
00462  
00463    // otherwise, we're done
00464   return CUBIT_SUCCESS;
00465 }
00466 
00467 
00468 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines