cgma
|
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