cgma
|
00001 //------------------------------------------------------------------------- 00002 // Filename : PartitionEngine.cpp 00003 // 00004 // Purpose : 00005 // 00006 // Special Notes : 00007 // 00008 // Creator : Jason Kraftcheck 00009 // 00010 // Creation Date : 04/23/02 00011 //------------------------------------------------------------------------- 00012 00013 #include "PartitionEngine.hpp" 00014 #include "CompositeEngine.hpp" 00015 00016 #include "SubCurve.hpp" 00017 #include "SubSurface.hpp" 00018 #include "SegmentedCurve.hpp" 00019 #include "PartitionPoint.hpp" 00020 #include "PartitionCoEdge.hpp" 00021 #include "PartitionLoop.hpp" 00022 #include "PartitionSurface.hpp" 00023 #include "PartitionLump.hpp" 00024 #include "PartitionBody.hpp" 00025 #include "PartPTCurve.hpp" 00026 #include "PartitionShell.hpp" 00027 #include "BodySM.hpp" 00028 00029 00030 #include "GMem.hpp" 00031 #include "GeometryQueryEngine.hpp" 00032 #include "GeometryModifyEngine.hpp" 00033 #include "GeometryModifyTool.hpp" 00034 00035 #include "VGLoopTool.hpp" 00036 00037 #include "FacetProjectTool.hpp" 00038 #include "CubitFacetData.hpp" 00039 #include "CubitFacetEdgeData.hpp" 00040 #include "CubitPointData.hpp" 00041 #include "TDVGFacetOwner.hpp" 00042 #include "TDVGFacetSplit.hpp" 00043 #include "FacetEvalTool.hpp" 00044 #include "FacetDataUtil.hpp" 00045 #include "PartSurfFacetTool.hpp" 00046 #include "PartitionTool.hpp" 00047 00048 #include "CompositeSurface.hpp" 00049 #include "CompositePoint.hpp" 00050 #include "CompositeCurve.hpp" 00051 #include "PartitionLumpImprint.hpp" 00052 #include "GfxDebug.hpp" 00053 #include "BridgeManager.hpp" 00054 00055 #include "CADefines.hpp" 00056 00057 #include <set> 00058 #include "GeometryQueryTool.hpp" 00059 00060 #include "CubitTransformMatrix.hpp" 00061 #include "CubitObservable.hpp" 00062 #include "AppUtil.hpp" 00063 #include "GeometryEvent.hpp" 00064 00065 const char* const PARTITION_GEOM_ATTRIB_NAME = "PARTITION_GEOM"; 00066 00067 static CubitStatus get_edge_replacements( 00068 std::vector<CubitFacetData*> &facet_list, 00069 std::vector<CubitFacetEdgeData*> replacement_edges[3]); 00070 00071 00072 PartitionEngine* PartitionEngine::instance_ = NULL; 00073 00074 00075 PartitionEngine::~PartitionEngine() 00076 { 00077 GeometryQueryTool::instance()->unregister_intermediate_engine(this); 00078 } 00079 00080 void PartitionEngine::delete_instance() 00081 { 00082 if( NULL != instance_ ) 00083 { 00084 delete instance_; 00085 instance_ = NULL; 00086 } 00087 } 00088 00089 00090 //------------------------------------------------------------------------- 00091 // Purpose : Constructor 00092 // 00093 // Special Notes : 00094 // 00095 // Creator : Jason Kraftcheck 00096 // 00097 // Creation Date : 08/25/03 00098 //------------------------------------------------------------------------- 00099 PartitionEngine::PartitionEngine() 00100 { 00101 CubitStatus r = GeometryQueryTool::instance()->register_intermediate_engine(this); 00102 assert(r == CUBIT_SUCCESS); 00103 if (CUBIT_SUCCESS != r) { 00104 PRINT_ERROR("Failed to register intermediate engine.\n"); 00105 } 00106 } 00107 00108 //------------------------------------------------------------------------- 00109 // Purpose : Get instance 00110 // 00111 // Special Notes : 00112 // 00113 // Creator : Jason Kraftcheck 00114 // 00115 // Creation Date : 02/23/03 00116 //------------------------------------------------------------------------- 00117 PartitionEngine& PartitionEngine::instance() 00118 { 00119 if( instance_ == NULL ) 00120 { 00121 instance_ = new PartitionEngine(); 00122 assert( instance_ != NULL ); 00123 } 00124 00125 return *instance_; 00126 } 00127 00128 //------------------------------------------------------------------------- 00129 // Purpose : Used by SubEntitySet to update ID map. 00130 // 00131 // Special Notes : 00132 // 00133 // Creator : Jason Kraftcheck 00134 // 00135 // Creation Date : 02/23/03 00136 //------------------------------------------------------------------------- 00137 CubitStatus PartitionEngine::add_to_id_map( SubEntitySet* set, int unique_id ) 00138 { 00139 if( uniqueIdMap.find(unique_id) != uniqueIdMap.end() ) 00140 { assert(0); return CUBIT_FAILURE; } 00141 uniqueIdMap[unique_id] = set; 00142 return CUBIT_SUCCESS; 00143 } 00144 00145 //------------------------------------------------------------------------- 00146 // Purpose : Used by SubEntitySet to update ID map. 00147 // 00148 // Special Notes : 00149 // 00150 // Creator : Jason Kraftcheck 00151 // 00152 // Creation Date : 02/23/03 00153 //------------------------------------------------------------------------- 00154 CubitStatus PartitionEngine::remove_from_id_map( SubEntitySet* set, int id ) 00155 { 00156 std::map<int,SubEntitySet*>::iterator itor = uniqueIdMap.find(id); 00157 if( itor == uniqueIdMap.end() || itor->second != set ) 00158 { assert(0); return CUBIT_FAILURE; } 00159 uniqueIdMap.erase(itor); 00160 return CUBIT_SUCCESS; 00161 } 00162 00163 //------------------------------------------------------------------------- 00164 // Purpose : Retreive an entity from the ID map 00165 // 00166 // Special Notes : 00167 // 00168 // Creator : Jason Kraftcheck 00169 // 00170 // Creation Date : 02/23/03 00171 //------------------------------------------------------------------------- 00172 SubEntitySet* PartitionEngine::get_from_id_map( int id ) 00173 { 00174 std::map<int,SubEntitySet*>::iterator itor = uniqueIdMap.find(id); 00175 return itor == uniqueIdMap.end() ? 0 : itor->second; 00176 } 00177 00178 //------------------------------------------------------------------------- 00179 // Purpose : Replicate solid model topology in partition layer 00180 // 00181 // Special Notes : 00182 // 00183 // Creator : Jason Kraftcheck 00184 // 00185 // Creation Date : 02/23/03 00186 //------------------------------------------------------------------------- 00187 SubCurve* PartitionEngine::replace_curve( Curve* curve ) 00188 { 00189 SubCurve* result = dynamic_cast<SubCurve*>(curve); 00190 if( result ) 00191 return result; 00192 00193 if( dynamic_cast<SegmentedCurve*>(curve) ) 00194 return 0; 00195 00196 DLIList<TopologyBridge*> list; 00197 //curve->get_children_virt( list ); 00198 //fix_up_query_results( list ); 00199 curve->get_children(list, false, layer()); 00200 PartitionPoint *start_pt = 0, *end_pt = 0; 00201 bool new_start = false, new_end = false; 00202 list.reset(); 00203 TopologyBridge* bridge = list.get_and_step(); 00204 start_pt = dynamic_cast<PartitionPoint*>(bridge); 00205 if( ! start_pt ) 00206 { 00207 start_pt = replace_point( dynamic_cast<TBPoint*>(bridge) ); 00208 if( ! start_pt ) 00209 return 0; 00210 new_start = true; 00211 } 00212 if( list.size() == 1 ) 00213 { 00214 end_pt = start_pt; 00215 } 00216 else if( list.size() == 2 ) 00217 { 00218 bridge = list.get(); 00219 end_pt = dynamic_cast<PartitionPoint*>(bridge); 00220 if( !end_pt ) 00221 { 00222 end_pt = replace_point( dynamic_cast<TBPoint*>(bridge) ); 00223 new_end = true; 00224 if( !end_pt ) 00225 { 00226 if( new_start ) 00227 restore_point( start_pt ); 00228 return 0; 00229 } 00230 } 00231 } 00232 00233 assert( start_pt && end_pt ); 00234 00235 result = new SubCurve( curve ); 00236 if( ! result->start_point( start_pt ) || 00237 ! result->end_point( end_pt ) ) 00238 { 00239 result->start_point(0); 00240 result->end_point(0); 00241 delete result; 00242 if( new_start ) 00243 restore_point( start_pt ); 00244 if( new_end ) 00245 restore_point( end_pt ); 00246 return 0; 00247 } 00248 if( curve->owner() ) 00249 { 00250 curve->owner()->swap_bridge(curve, result, false); 00251 } 00252 curve->owner(&(result->sub_entity_set())); 00253 00254 list.clean_out(); 00255 curve->get_parents_virt( list ); 00256 //fix_up_query_results( list ); 00257 00258 for( int i = list.size(); i--; ) 00259 { 00260 bridge = list.get_and_step(); 00261 CoEdgeSM* coedge = dynamic_cast<CoEdgeSM*>(bridge); 00262 assert( coedge != NULL ); 00263 PartitionCoEdge* pcoedge = new PartitionCoEdge( coedge ); 00264 CubitStatus s = result->add( pcoedge ); 00265 assert( s ); 00266 if (CUBIT_SUCCESS != s) { 00267 PRINT_ERROR("Failed to add coedge to SubCurve.\n"); 00268 return NULL; 00269 } 00270 if( coedge->owner() ) 00271 coedge->owner()->swap_bridge(coedge, pcoedge, false); 00272 coedge->owner(&(pcoedge->sub_entity_set())); 00273 } 00274 00275 00276 PartitionBody* body = 0; 00277 if( result->start_point()->sub_entity_set().body() ) 00278 body = result->start_point()->sub_entity_set().body(); 00279 else if( result->end_point()->sub_entity_set().body() ) 00280 body = result->end_point()->sub_entity_set().body(); 00281 else 00282 body = make_body(result); 00283 00284 if( body ) 00285 { 00286 if( !result->start_point()->sub_entity_set().body() ) 00287 body->add(result->start_point()->sub_entity_set()); 00288 if( !result->end_point()->sub_entity_set().body() ) 00289 body->add(result->end_point()->sub_entity_set()); 00290 body->add(result->sub_entity_set()); 00291 PartitionCoEdge* coedge = 0; 00292 while ( (coedge = result->next_coedge(coedge)) ) 00293 if ( !coedge->sub_entity_set().body() ) 00294 body->add(coedge->sub_entity_set()); 00295 } 00296 00297 // we must notify the graphics of the modify from "real" to virtual -- KGM 00298 // I realize that this is not where the other notifies are completed but there 00299 // is no knowledge of the change later on. 00300 CubitObservable* observable = dynamic_cast<CubitObservable*>(result->topology_entity()); 00301 if (observable) 00302 { 00303 AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, dynamic_cast<RefEntity*>(result->topology_entity()))); 00304 } 00305 00306 return result; 00307 } 00308 00309 //------------------------------------------------------------------------- 00310 // Purpose : Replicate solid model topology in partition layer 00311 // 00312 // Special Notes : 00313 // 00314 // Creator : Jason Kraftcheck 00315 // 00316 // Creation Date : 02/23/03 00317 //------------------------------------------------------------------------- 00318 SubSurface* PartitionEngine::replace_surface( Surface* surface ) 00319 { 00320 int i, j; 00321 00322 // check if the input surface is already a SubSurface 00323 SubSurface* result = dynamic_cast<SubSurface*>(surface); 00324 if( result ) 00325 return result; 00326 00327 // check if the input surface is already a PartitionSurface 00328 if( dynamic_cast<PartitionSurface*>(surface) ) 00329 return 0; 00330 00331 // create a new SubSurface, swap out the TBOwner if it 00332 // exists and reset the input surface TBOwner. 00333 DLIList<TopologyBridge*> loop_list, coe_list, curve_list; 00334 surface->get_children( loop_list, false, layer() ); 00335 result = new SubSurface( surface ); 00336 if( surface->owner() ) 00337 surface->owner()->swap_bridge(surface, result, false); 00338 surface->owner(&(result->sub_entity_set())); 00339 00340 // Add the loop onto the new surface 00341 loop_list.reset(); 00342 for( i = loop_list.size(); i--; ) 00343 { 00344 LoopSM* loop = dynamic_cast<LoopSM*>(loop_list.get_and_step()); 00345 PartitionLoop* partloop = new PartitionLoop(); 00346 result->add( partloop ); 00347 if( loop->owner() ) 00348 loop->owner()->swap_bridge( loop, partloop, false ); 00349 loop->owner(0); 00350 00351 // Take care of the curves in the loop 00352 coe_list.clean_out(); 00353 loop->get_children( coe_list, false, layer() ); 00354 00355 coe_list.reset(); 00356 for( j = coe_list.size(); j--; ) 00357 { 00358 CoEdgeSM* coedge = dynamic_cast<CoEdgeSM*>(coe_list.get_and_step()); 00359 if(!dynamic_cast<PartitionCoEdge*>(coedge) && 00360 !dynamic_cast<SubEntitySet*>(coedge->owner()) ) 00361 { 00362 curve_list.clean_out(); 00363 coedge->get_children_virt( curve_list ); 00364 assert( curve_list.size() == 1 ); 00365 00366 Curve* curve = dynamic_cast<Curve*>(curve_list.get()); 00367 assert(! dynamic_cast<PartitionCurve*>(curve) ); 00368 SubCurve* pcurve = replace_curve( curve ); 00369 assert(pcurve != NULL); 00370 if (NULL == pcurve) { 00371 PRINT_ERROR("Failed to replace curve.\n"); 00372 return NULL; 00373 } 00374 } 00375 } 00376 00377 coe_list.clean_out(); 00378 loop->get_children( coe_list, false, layer() ); 00379 00380 coe_list.reset(); 00381 PartitionCoEdge *curr, *prev = 0; 00382 coe_list.reset(); 00383 for( j = coe_list.size(); j--; ) 00384 { 00385 curr = dynamic_cast<PartitionCoEdge*>(coe_list.get_and_step()); 00386 assert( curr != NULL ); 00387 partloop->insert_after( curr, prev ); 00388 prev = curr; 00389 } 00390 00391 } 00392 00393 // If the facet data is incorrect put everything back 00394 if (!result->init_facet_data()) { 00395 restore_surface( result ); 00396 return 0; 00397 } 00398 00399 // finalize by making the body 00400 PartitionBody* body = make_body(result); 00401 if( body ) 00402 body->add(result->sub_entity_set()); 00403 00404 return result; 00405 } 00406 00407 //------------------------------------------------------------------------- 00408 // Purpose : Replicate solid model topology in partition layer 00409 // 00410 // Special Notes : 00411 // 00412 // Creator : Jason Kraftcheck 00413 // 00414 // Creation Date : 02/23/03 00415 //------------------------------------------------------------------------- 00416 PartitionLump* PartitionEngine::replace_lump( Lump* lump ) 00417 { 00418 int i, j; 00419 PartitionLump* result = dynamic_cast<PartitionLump*>(lump); 00420 if( result ) 00421 return result; 00422 00423 DLIList<TopologyBridge*> shell_list, surface_list; 00424 lump->get_children( shell_list, false, layer() ); 00425 00426 DLIList<PartitionShell*> new_shells; 00427 shell_list.reset(); 00428 for( i = shell_list.size(); i--; ) 00429 { 00430 ShellSM* shell = dynamic_cast<ShellSM*>(shell_list.get_and_step()); 00431 PartitionShell* pshell = new PartitionShell(); 00432 new_shells.append(pshell); 00433 if( shell->owner() ) 00434 shell->owner()->swap_bridge( shell, pshell, false ); 00435 shell->owner(0); 00436 00437 surface_list.clean_out(); 00438 shell->get_children( surface_list, false, layer() ); 00439 00440 surface_list.reset(); 00441 for( j = surface_list.size(); j--; ) 00442 { 00443 Surface* surface = dynamic_cast<Surface*>(surface_list.get_and_step()); 00444 PartitionSurface* psurf = dynamic_cast<PartitionSurface*>(surface); 00445 if( !psurf ) 00446 { 00447 psurf = replace_surface( surface ); 00448 if (!psurf) 00449 { 00450 while (new_shells.size()) 00451 destroy_shell(new_shells.pop()); 00452 return 0; 00453 } 00454 } 00455 00456 Surface* real_surf = dynamic_cast<Surface*>(psurf->partitioned_entity()); 00457 assert(!!real_surf); 00458 CubitSense sense = real_surf->get_shell_sense(shell); 00459 assert(sense == CUBIT_FORWARD || sense == CUBIT_REVERSED); 00460 pshell->add( psurf, sense ); 00461 } 00462 } 00463 00464 result = new PartitionLump( lump ); 00465 if( lump->owner() ) 00466 lump->owner()->swap_bridge(lump, result, false); 00467 lump->owner(&(result->sub_entity_set())); 00468 new_shells.reverse(); 00469 while( new_shells.size() ) 00470 result->add(new_shells.pop()); 00471 00472 PartitionBody* body = make_body(result); 00473 if( body ) 00474 body->add( result->sub_entity_set() ); 00475 00476 return result; 00477 } 00478 00479 //------------------------------------------------------------------------- 00480 // Purpose : Replicate solid model topology in partition layer 00481 // 00482 // Special Notes : 00483 // 00484 // Creator : Jason Kraftcheck 00485 // 00486 // Creation Date : 02/23/03 00487 //------------------------------------------------------------------------- 00488 PartitionPoint* PartitionEngine::replace_point( TBPoint* point ) 00489 { 00490 PartitionPoint* result = dynamic_cast<PartitionPoint*>(point); 00491 if( !result ) 00492 { 00493 result = new PartitionPoint( point ); 00494 } 00495 00496 if( result ) 00497 { 00498 if( point->owner() ) 00499 point->owner()->swap_bridge( point, result, false ); 00500 point->owner( &(result->sub_entity_set()) ); 00501 } 00502 00503 return result; 00504 } 00505 00506 //------------------------------------------------------------------------- 00507 // Purpose : Restore original solid model topology. (Inverse of 00508 // replace_point.) 00509 // 00510 // Special Notes : 00511 // 00512 // Creator : Jason Kraftcheck 00513 // 00514 // Creation Date : 02/23/03 00515 //------------------------------------------------------------------------- 00516 TBPoint* PartitionEngine::restore_point( PartitionPoint* point ) 00517 { 00518 if( point->num_curves() ) 00519 return 0; 00520 00521 TBPoint* result = point->real_point(); 00522 if( result ) 00523 { 00524 point->sub_entity_set().unwrap_attributes(); 00525 point->sub_entity_set().remove_bridge(result); 00526 if( point->owner() ) 00527 point->owner()->swap_bridge( point, result, false ); 00528 delete point; 00529 } 00530 00531 return result; 00532 } 00533 00534 //------------------------------------------------------------------------- 00535 // Purpose : Restore original solid model topology. (Inverse of 00536 // replace_curve.) 00537 // 00538 // Special Notes : 00539 // 00540 // Creator : Jason Kraftcheck 00541 // 00542 // Creation Date : 02/23/03 00543 //------------------------------------------------------------------------- 00544 Curve* PartitionEngine::restore_curve( SubCurve* curve ) 00545 { 00546 if( curve->num_partitions() > 1 ) 00547 return 0; 00548 00549 PartitionCoEdge* coedge = 0; 00550 while( (coedge = curve->next_coedge( coedge )) ) 00551 if( coedge->get_loop() ) 00552 return 0; 00553 00554 while( (coedge = curve->next_coedge(0)) ) 00555 { 00556 curve->remove( coedge ); 00557 CoEdgeSM* real_coedge = coedge->real_coedge(); 00558 if( real_coedge ) 00559 { 00560 coedge->sub_entity_set().remove_bridge( real_coedge ); 00561 if( coedge->owner() ) 00562 coedge->owner()->swap_bridge( coedge, real_coedge, false ); 00563 } 00564 delete coedge; 00565 } 00566 00567 PartitionPoint* start = curve->start_point(); 00568 curve->start_point( 0 ); 00569 if( start->num_curves() == 0 ) 00570 { 00571 if( start->real_point() ) 00572 restore_point( start ); 00573 else 00574 delete start; 00575 } 00576 00577 PartitionPoint* end = curve->end_point(); 00578 curve->end_point(0); 00579 if( end->num_curves() == 0 ) 00580 { 00581 if( end->real_point() ) 00582 restore_point( end ); 00583 else 00584 delete end; 00585 } 00586 00587 Curve* result = curve->real_curve(); 00588 curve->sub_entity_set().unwrap_attributes(); 00589 curve->sub_entity_set().remove_bridge( result ); 00590 if( curve->owner() ) 00591 curve->owner()->swap_bridge( curve, result, false ); 00592 delete curve; 00593 00594 // we must notify the graphics of the modify from "real" to virtual -- KGM 00595 // I realize that this is not where the other notifies are completed but there 00596 // is no knowledge of the change later on. 00597 CubitObservable* observable = dynamic_cast<CubitObservable*>(result->topology_entity()); 00598 if (observable) 00599 { 00600 AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, dynamic_cast<RefEntity*>(result->topology_entity()))); 00601 } 00602 00603 return result; 00604 } 00605 00606 00607 //------------------------------------------------------------------------- 00608 // Purpose : Restore original solid model topology. (Inverse of 00609 // replace_surface.) 00610 // 00611 // Special Notes : 00612 // 00613 // Creator : Jason Kraftcheck 00614 // 00615 // Creation Date : 02/23/03 00616 //------------------------------------------------------------------------- 00617 Surface* PartitionEngine::restore_surface( SubSurface* surface ) 00618 { 00619 if( surface->sub_entity_set().has_lower_order() || surface->next_co_surface() ) 00620 return 0; 00621 00622 while( PartitionLoop* loop = surface->next_loop() ) 00623 // while surface has loops... 00624 { 00625 surface->remove( loop ); 00626 00627 while( loop->first_coedge() ) 00628 { 00629 PartitionCoEdge* coedge = loop->first_coedge(); 00630 loop->remove( coedge ); 00631 00632 SubCurve* curve = dynamic_cast<SubCurve*>(coedge->get_curve()); 00633 if( !curve || curve->sub_entity_set().has_lower_order() ) 00634 continue; 00635 00636 bool remove = true; 00637 coedge = 0; 00638 while( (coedge = curve->next_coedge( coedge )) ) 00639 { 00640 if( coedge->get_loop() ) 00641 { 00642 remove = false; 00643 break; 00644 } 00645 } 00646 00647 if( remove ) 00648 { 00649 restore_curve( curve ); 00650 } 00651 00652 } 00653 00654 delete loop; 00655 } 00656 00657 00658 Surface* result = surface->partitioned_surface(); 00659 surface->sub_entity_set().unwrap_attributes(); 00660 surface->sub_entity_set().remove_bridge( result ); 00661 if( surface->owner() ) 00662 surface->owner()->swap_bridge( surface, result, false ); 00663 delete surface; 00664 return result; 00665 } 00666 00667 //------------------------------------------------------------------------- 00668 // Purpose : Destroy a single partition of a volume. 00669 // 00670 // Special Notes : Will restore original volume if this is the last/only 00671 // partition. 00672 // 00673 // Creator : Jason Kraftcheck 00674 // 00675 // Creation Date : 02/11/03 00676 //------------------------------------------------------------------------- 00677 CubitStatus PartitionEngine::destroy_lump( PartitionLump* lump ) 00678 { 00679 /* only partition lump? */ 00680 if ( ! lump->sub_entity_set().has_multiple_sub_entities() ) 00681 { 00682 DLIList<PartitionEntity*> child_entities; 00683 lump->sub_entity_set().get_lower_order( child_entities ); 00684 DLIList<PartitionSurface*> surf_list; 00685 CAST_LIST( child_entities, surf_list, PartitionSurface ); 00686 00687 while( surf_list.size() ) 00688 if( ! remove_surface( surf_list.pop() ) ) 00689 return CUBIT_FAILURE; 00690 00691 return restore_lump(lump) ? CUBIT_SUCCESS : CUBIT_FAILURE; 00692 } 00693 00694 PartitionShell* shell; 00695 while ( (shell = lump->next_shell(0)) ) 00696 { 00697 lump->remove(shell); 00698 destroy_shell(shell); 00699 } 00700 delete lump; 00701 00702 return CUBIT_SUCCESS; 00703 } 00704 00705 00706 00707 //------------------------------------------------------------------------- 00708 // Purpose : Restore original solid model topology. (Inverse of 00709 // replace_lump.) 00710 // 00711 // Special Notes : 00712 // 00713 // Creator : Jason Kraftcheck 00714 // 00715 // Creation Date : 02/23/03 00716 //------------------------------------------------------------------------- 00717 Lump* PartitionEngine::restore_lump( PartitionLump* lump ) 00718 { 00719 if( lump->sub_entity_set().has_lower_order() ) 00720 return 0; 00721 00722 while( PartitionShell* shell = lump->next_shell() ) 00723 // while surface has loops... 00724 { 00725 lump->remove( shell ); 00726 destroy_shell( shell ); 00727 } 00728 00729 00730 Lump* result = lump->real_lump(); 00731 lump->sub_entity_set().unwrap_attributes(); 00732 lump->sub_entity_set().remove_bridge( result ); 00733 if( lump->owner() ) 00734 lump->owner()->swap_bridge( lump, result, false ); 00735 delete lump; 00736 return result; 00737 } 00738 00739 bool PartitionEngine::is_partition(TBOwner *bridge_owner) 00740 { 00741 bool ret = false; 00742 if(bridge_owner) 00743 { 00744 if(dynamic_cast<SubEntitySet*>(bridge_owner)) 00745 { 00746 ret = true; 00747 } 00748 } 00749 return ret; 00750 } 00751 00752 bool PartitionEngine::is_composite(TBOwner *bridge_owner) 00753 { 00754 return false; 00755 } 00756 00757 bool PartitionEngine::is_composite(TopologyBridge *bridge) 00758 { 00759 return false; 00760 } 00761 00762 //------------------------------------------------------------------------- 00763 // Purpose : Destroy a shell 00764 // 00765 // Special Notes : 00766 // 00767 // Creator : Jason Kraftcheck 00768 // 00769 // Creation Date : 03/11/04 00770 //------------------------------------------------------------------------- 00771 CubitStatus PartitionEngine::destroy_shell( PartitionShell* shell ) 00772 { 00773 if (shell->get_lump()) 00774 { 00775 assert(0); 00776 return CUBIT_FAILURE; 00777 } 00778 00779 while( PartitionCoSurf* cosurf = shell->next_co_surface() ) 00780 { 00781 shell->remove( cosurf ); 00782 00783 SubSurface* psurf = dynamic_cast<SubSurface*>(cosurf->get_surface()); 00784 if (psurf) 00785 { 00786 psurf->remove(cosurf); 00787 00788 // If PartitionSurface is the same as the underlying surface 00789 // and is not part of any other PartitionLumps, remove it. 00790 if( !psurf->sub_entity_set().has_lower_order() && 00791 psurf->next_co_surface() == 0 ) 00792 restore_surface( psurf ); 00793 } 00794 00795 delete cosurf; 00796 } 00797 00798 delete shell; 00799 return CUBIT_SUCCESS; 00800 } 00801 00802 00803 00804 //------------------------------------------------------------------------- 00805 // Purpose : Partition a curve 00806 // 00807 // Special Notes : public interface to curve partitioning 00808 // 00809 // Creator : Jason Kraftcheck 00810 // 00811 // Creation Date : 02/23/03 00812 //------------------------------------------------------------------------- 00813 TBPoint* PartitionEngine::insert_point( Curve* curve, double u ) 00814 { 00815 PartitionCurve* pcurve = dynamic_cast<PartitionCurve*>(curve); 00816 bool replaced_curve = false; 00817 00818 if( !pcurve ) 00819 { 00820 if( CompositeCurve* comp = dynamic_cast<CompositeCurve*>(curve) ) 00821 { 00822 return CompositeEngine::instance().insert_point( comp, u ); 00823 } 00824 00825 pcurve = replace_curve( curve ); 00826 if( !pcurve ) 00827 return 0; 00828 replaced_curve = true; 00829 } 00830 00831 CubitVector coords; 00832 if( ! pcurve->position_from_u( u, coords ) ) 00833 { 00834 if( replaced_curve ) 00835 restore_curve( dynamic_cast<SubCurve*>(pcurve) ); 00836 return 0; 00837 } 00838 00839 PartitionPoint* npoint = new PartitionPoint( coords, pcurve ); 00840 PartitionCurve* ncurve = insert_point(pcurve, npoint); 00841 00842 if( !ncurve ) 00843 { 00844 if( replaced_curve ) 00845 restore_curve( dynamic_cast<SubCurve*>(pcurve) ); 00846 delete npoint; 00847 return 0; 00848 } 00849 00850 return npoint; 00851 } 00852 00853 00854 //------------------------------------------------------------------------- 00855 // Purpose : Partition a curve 00856 // 00857 // Special Notes : not public 00858 // 00859 // Creator : Jason Kraftcheck 00860 // 00861 // Creation Date : 02/23/03 00862 //------------------------------------------------------------------------- 00863 PartitionCurve* PartitionEngine::insert_point( PartitionCurve* pcurve, 00864 PartitionPoint* npoint ) 00865 { 00866 const double TOLSQR = GEOMETRY_RESABS * GEOMETRY_RESABS; 00867 CubitVector coords = npoint->coordinates(); 00868 double u = pcurve->u_from_position(coords); 00869 double u_min, u_max; 00870 pcurve->get_param_range( u_min, u_max ); 00871 00872 if(u_min > u_max) 00873 { 00874 double dtemp = u_min; 00875 u_min = u_max; 00876 u_max = dtemp; 00877 } 00878 00879 if( u - u_min < CUBIT_RESABS || u_max - u < CUBIT_RESABS ) 00880 return 0; 00881 00882 if( (pcurve->start_point()->coordinates() - coords).length_squared() < TOLSQR 00883 || (pcurve->end_point()->coordinates() - coords).length_squared() < TOLSQR ) 00884 return 0; 00885 00886 PartitionCurve* ncurve = pcurve->split( u ); 00887 if( !ncurve ) 00888 return 0; 00889 00890 ncurve->end_point( pcurve->end_point() ); 00891 pcurve->end_point( npoint ); 00892 ncurve->start_point( npoint ); 00893 pcurve->fix_facet_data( ncurve ); 00894 00895 PartitionCoEdge *pcoedge = 0, *ncoedge = 0; 00896 while( (pcoedge = pcurve->next_coedge( pcoedge )) ) 00897 { 00898 ncoedge = new PartitionCoEdge( pcoedge ); 00899 ncurve->add( ncoedge ); 00900 if( pcoedge->get_loop() ) 00901 { 00902 if( pcoedge->sense() == CUBIT_FORWARD ) 00903 pcoedge->get_loop()->insert_after( ncoedge, pcoedge ); 00904 else 00905 pcoedge->get_loop()->insert_before( ncoedge, pcoedge ); 00906 } 00907 } 00908 00909 if( pcurve->owner() ) 00910 pcurve->owner()->notify_split( ncurve, pcurve ); 00911 00912 return ncurve; 00913 } 00914 00915 //------------------------------------------------------------------------- 00916 // Purpose : un-partition a curve 00917 // 00918 // Special Notes : 00919 // 00920 // Creator : Jason Kraftcheck 00921 // 00922 // Creation Date : 02/23/03 00923 //------------------------------------------------------------------------- 00924 Curve* PartitionEngine::remove_point( PartitionPoint* point, 00925 PartitionCurve* dead_curves[2] ) 00926 { 00927 if( dead_curves ) 00928 dead_curves[0] = dead_curves[1] = 0; 00929 00930 if( point->num_curves() > 2 ) 00931 return 0; 00932 00933 DLIList<TopologyBridge*> curve_bridges; 00934 point->get_parents_virt( curve_bridges ); 00935 if( curve_bridges.size() > 2 ) 00936 return 0; 00937 00938 if( curve_bridges.size() == 1 ) 00939 { 00940 PartPTCurve* point_curve = dynamic_cast<PartPTCurve*>(curve_bridges.get()); 00941 if( ! point_curve ) 00942 return 0; 00943 00944 if( dead_curves ) 00945 dead_curves[0] = point_curve; 00946 remove_point_curve( point ); 00947 return 0; 00948 } 00949 00950 /* 00951 TopologyBridge* real = point->partitioned_entity(); 00952 if( dynamic_cast<TBPoint*>(real) ) 00953 { 00954 Curve* curve1 = dynamic_cast<Curve*>(curve_bridges.get()); 00955 Curve* curve2 = dynamic_cast<Curve*>(curve_bridges.next()); 00956 PartitionCurve* pc1 = dynamic_cast<PartitionCurve*>(curve1); 00957 PartitionCurve* pc2 = dynamic_cast<PartitionCurve*>(curve2); 00958 assert( pc1 || pc2 ); 00959 if( !pc1 ) 00960 pc1 = replace_curve( curve1 ); 00961 if( !pc2 ) 00962 pc2 = replace_curve( curve2 ); 00963 00964 CompositeEngine::instance()->remove_point( dynamic_cast<TBPoint*>(real) ); 00965 bool reverse = ( pc1->start_point() == pc2->start_point() || 00966 pc2->end_point() == pc2->end_point() ); 00967 if( pc1->partitioned_entity() == 0 ) 00968 { 00969 bool prepend = false; 00970 if( pc1->other_point( pc2->start_point() ) ) 00971 prepend = true; 00972 pc2->sub_entity_set().merge( pc1->sub_entity_set(), reverse, prepend ); 00973 } 00974 else if( pc2->partitioned_entity() == 0 ) 00975 { 00976 bool prepend = false; 00977 if( pc2->other_point( pc1->start_point() ) ) 00978 prepend = true; 00979 pc1->sub_entity_set().merge( pc2->sub_entity_set(), reverse, prepend ); 00980 } 00981 else 00982 return 0; 00983 } 00984 */ 00985 if( point->num_curves() != 2 ) 00986 return 0; 00987 00988 PartitionCurve* survivor = point->next_curve(0); 00989 PartitionCurve* casualty = point->next_curve(survivor); 00990 if( survivor->start_point() == point && 00991 casualty->end_point() == point ) 00992 { 00993 // swap 00994 survivor = casualty; 00995 casualty = point->next_curve(0); 00996 } 00997 00998 if( ! survivor->combine( casualty ) ) 00999 return 0; 01000 01001 PartitionPoint* other_pt = 01002 casualty->start_point() == point ? 01003 casualty->end_point() : casualty->start_point(); 01004 casualty->start_point(0); 01005 casualty->end_point(0); 01006 01007 if( survivor->start_point() == point ) 01008 survivor->start_point( other_pt ); 01009 else 01010 survivor->end_point( other_pt ); 01011 01012 delete point; 01013 01014 while( PartitionCoEdge* coedge = casualty->next_coedge(0) ) 01015 { 01016 if( coedge->get_loop() ) 01017 coedge->get_loop()->remove( coedge ); 01018 casualty->remove( coedge ); 01019 delete coedge; 01020 } 01021 delete casualty; 01022 if( dead_curves ) 01023 dead_curves[0] = casualty; 01024 01025 Curve* result = survivor; 01026 SubCurve* subcurve = dynamic_cast<SubCurve*>(survivor); 01027 if( subcurve && !survivor->sub_entity_set().has_multiple_sub_entities() ) 01028 { 01029 Curve* real_curve = restore_curve( subcurve ); 01030 if (real_curve) 01031 { 01032 result = real_curve; 01033 if (dead_curves) 01034 dead_curves[1] = survivor; 01035 } 01036 } 01037 01038 return result; 01039 } 01040 01041 //------------------------------------------------------------------------- 01042 // Purpose : Remove a point-curve (point imprinted on a surface) 01043 // 01044 // Special Notes : 01045 // 01046 // Creator : Jason Kraftcheck 01047 // 01048 // Creation Date : 02/23/03 01049 //------------------------------------------------------------------------- 01050 CubitStatus PartitionEngine::remove_point_curve( PartitionPoint* point ) 01051 { 01052 if( point->num_curves() != 1 ) 01053 return CUBIT_FAILURE; 01054 01055 PartPTCurve* curve = dynamic_cast<PartPTCurve*>(point->next_curve(0)); 01056 if( !curve ) 01057 return CUBIT_FAILURE; 01058 01059 PartitionSurface* surf = 0; 01060 if( curve->num_coedges() ) 01061 { 01062 assert( curve->num_coedges() == 1 ); 01063 PartitionCoEdge* coedge = curve->next_coedge(0); 01064 PartitionLoop* loop = coedge->get_loop(); 01065 if( loop ) 01066 { 01067 surf = loop->get_surface(); 01068 surf->remove( loop ); 01069 loop->remove( coedge ); 01070 assert( loop->num_coedges() == 0 ); 01071 delete loop; 01072 } 01073 curve->remove( coedge ); 01074 delete coedge; 01075 } 01076 01077 curve->start_point(0); 01078 curve->end_point(0); 01079 delete curve; 01080 delete point; 01081 01082 if( surf && surf->owner() ) 01083 surf->owner()->notify_topology_modified( surf ); 01084 01085 return CUBIT_SUCCESS; 01086 } 01087 01088 //------------------------------------------------------------------------- 01089 // Purpose : Topological modifications for surface partitioning 01090 // 01091 // Special Notes : non-public, assumes surface facets have already been 01092 // imprinted and the polyline of the imprint is already 01093 // associated with the passed curve. 01094 // 01095 // Creator : Jason Kraftcheck 01096 // 01097 // Creation Date : 02/23/03 01098 //------------------------------------------------------------------------- 01099 PartitionSurface* PartitionEngine::insert_curve( PartitionSurface* surface, 01100 SegmentedCurve* curve ) 01101 { 01102 PartitionSurface* new_surface = 0; 01103 assert( &(curve->sub_entity_set()) == &(surface->sub_entity_set()) ); 01104 01105 PartitionPoint *start_point = curve->start_point(); 01106 PartitionPoint *end_point = curve->end_point(); 01107 PartitionLoop *start_loop = 0, *end_loop = 0; 01108 PartitionCoEdge *start_prev_coedge = 0, *start_next_coedge = 0; 01109 PartitionCoEdge *end_prev_coedge = 0, *end_next_coedge = 0; 01110 01111 // find where to insert new curve in loop 01112 if ( !find_coedges( surface, curve, start_point, start_prev_coedge, start_next_coedge ) ) 01113 return 0; 01114 if ( !find_coedges( surface, curve, end_point, end_prev_coedge, end_next_coedge )) 01115 return 0; 01116 01117 assert((!start_prev_coedge && !start_next_coedge) || 01118 (start_prev_coedge && start_next_coedge && 01119 start_prev_coedge->get_loop() == start_next_coedge->get_loop())); 01120 assert((!end_prev_coedge && !end_next_coedge) || 01121 (end_prev_coedge && end_next_coedge && 01122 end_prev_coedge->get_loop() == end_next_coedge->get_loop())); 01123 if ( start_prev_coedge ) 01124 start_loop = start_prev_coedge->get_loop(); 01125 if ( end_prev_coedge ) 01126 end_loop = end_prev_coedge->get_loop(); 01127 01128 01129 // remove any point-curves 01130 PartitionCurve* pt_curve; 01131 PartPTCurve* point_curve; 01132 for ( int i = 0; i < 2; i++ ) // do once for each end point 01133 { 01134 PartitionPoint* pt = i ? end_point : start_point; 01135 pt_curve = pt->next_curve(0); 01136 while ( pt_curve ) 01137 { 01138 point_curve = dynamic_cast<PartPTCurve*>(pt_curve); 01139 pt_curve = pt->next_curve(pt_curve); 01140 if (point_curve && point_curve->next_coedge(0)->get_loop()->get_surface() == surface) 01141 { 01142 point_curve->start_point(0); 01143 point_curve->end_point(0); 01144 01145 PartitionCoEdge* coedge = point_curve->next_coedge(0); 01146 point_curve->remove(coedge); 01147 assert( !point_curve->next_coedge(0) ); 01148 PartitionLoop* loop = coedge->get_loop(); 01149 loop->remove(coedge); 01150 assert( !loop->first_coedge() ); 01151 surface->remove(loop); 01152 delete loop; 01153 delete coedge; 01154 delete point_curve; 01155 } 01156 } 01157 } 01158 01159 01160 PartitionCoEdge* forward = new PartitionCoEdge( surface, CUBIT_FORWARD ); 01161 PartitionCoEdge* reverse = new PartitionCoEdge( surface, CUBIT_REVERSED ); 01162 curve->add(forward); 01163 curve->add(reverse); 01164 01165 // new one-curve loop? 01166 if( !start_loop && !end_loop ) 01167 { 01168 PartitionLoop* new_loop = new PartitionLoop(); 01169 surface->add( new_loop ); 01170 new_loop->insert_after( forward, 0 ); 01171 01172 if( curve->start_point() == curve->end_point() ) 01173 { 01174 PartitionLoop* loop2 = new PartitionLoop(); 01175 loop2->insert_after( reverse, 0 ); 01176 01177 if( VGLoopTool 01178 <PartitionSurface,PartitionLoop,PartitionCoEdge,PartitionCurve,PartitionPoint> 01179 ::loop_angle_metric( forward ) > 0 ) 01180 { 01181 new_loop = loop2; 01182 } 01183 else 01184 { 01185 surface->remove(new_loop); 01186 surface->add( loop2 ); 01187 } 01188 01189 new_surface = split_surface( surface, new_loop->first_coedge() ); 01190 new_surface->add( new_loop ); 01191 } 01192 else 01193 { 01194 new_loop->insert_after( reverse, forward ); 01195 } 01196 } 01197 01198 // sipe 01199 else if( !start_loop || !end_loop ) 01200 { 01201 PartitionCoEdge* prev; 01202 PartitionLoop* loop; 01203 if( start_loop ) 01204 { 01205 loop = start_loop; 01206 prev = start_prev_coedge; 01207 } 01208 else 01209 { 01210 loop = end_loop; 01211 prev = end_prev_coedge; 01212 } 01213 01214 if( forward->start_point() == prev->end_point() ) 01215 { 01216 loop->insert_after( forward, prev ); 01217 loop->insert_after( reverse, forward ); 01218 } 01219 else 01220 { 01221 assert( reverse->start_point() == prev->end_point() ); 01222 loop->insert_after( reverse, prev ); 01223 loop->insert_after( forward, reverse ); 01224 } 01225 } 01226 01227 // join loops 01228 else if( start_loop != end_loop ) 01229 { 01230 PartitionCoEdge* prev = start_prev_coedge; 01231 PartitionCoEdge* coedge = end_next_coedge; 01232 PartitionCoEdge* next = 0, *other_coedge; 01233 01234 if( forward->start_point() == prev->end_point() ) 01235 { 01236 start_loop->insert_after( forward, prev ); 01237 prev = forward; 01238 other_coedge = reverse; 01239 } 01240 else 01241 { 01242 assert( reverse->start_point() == prev->end_point() ); 01243 start_loop->insert_after( reverse, prev ); 01244 prev = reverse; 01245 other_coedge = forward; 01246 } 01247 01248 while ( end_loop->first_coedge() ) 01249 { 01250 next = end_loop->next_coedge( coedge ); 01251 end_loop->remove( coedge ); 01252 start_loop->insert_after( coedge, prev ); 01253 prev = coedge; 01254 coedge = next; 01255 } 01256 01257 // The other coedge for the curve we are restoring... 01258 start_loop->insert_after( other_coedge, prev ); 01259 01260 assert( end_loop->num_coedges() == 0 ); 01261 surface->remove( end_loop ); 01262 delete end_loop; 01263 } 01264 01265 // split a loop (and create a new surface) 01266 else 01267 { 01268 assert( start_loop == end_loop ); 01269 01270 // If the curve we are adding results in a hole that 01271 // intersects the loop we are splitting at a single 01272 // vertex, we need to figure out which of the coedges 01273 // goes in the hole and which is added to the loop 01274 // we are splitting. 01275 if( forward->start_point() == forward->end_point() ) 01276 { 01277 assert( start_next_coedge == end_next_coedge ); 01278 assert( start_prev_coedge == end_prev_coedge ); 01279 01280 CubitVector prev_tan, forward_tan, reverse_tan, normal, junk; 01281 CubitVector point = forward->start_point()->coordinates(); 01282 start_prev_coedge->get_curve()->closest_point( point, junk, &prev_tan ); 01283 if( start_prev_coedge->sense() == CUBIT_FORWARD ) // yes, forward!!! 01284 prev_tan *= -1.0; 01285 forward->get_curve()->closest_point( point, junk, &forward_tan ); 01286 reverse_tan = forward_tan * -1.0; 01287 surface->closest_point( point, 0, &normal ); 01288 01289 double angle1 = normal.vector_angle( prev_tan, forward_tan ); 01290 double angle2 = normal.vector_angle( prev_tan, reverse_tan ); 01291 01292 if( angle2 < angle1 ) 01293 { 01294 PartitionCoEdge* temp = reverse; 01295 reverse = forward; 01296 forward = temp; 01297 } 01298 } 01299 01300 else 01301 { 01302 if( forward->end_point() == end_next_coedge->start_point() ) 01303 { 01304 PartitionCoEdge* temp = reverse; 01305 reverse = forward; 01306 forward = temp; 01307 } 01308 } 01309 01310 end_loop = new PartitionLoop(); 01311 start_loop->insert_after( forward, end_prev_coedge ); 01312 end_loop->insert_after( reverse, 0 ); 01313 01314 PartitionCoEdge* coedge = end_next_coedge; 01315 PartitionCoEdge* prev = reverse; 01316 while( coedge != start_next_coedge ) 01317 { 01318 PartitionCoEdge* next = start_loop->next_coedge( coedge ); 01319 start_loop->remove( coedge ); 01320 end_loop->insert_after( coedge, prev ); 01321 prev = coedge; 01322 coedge = next; 01323 } 01324 01325 new_surface = split_surface( surface, reverse ); 01326 new_surface->add( end_loop ); 01327 } 01328 01329 if( new_surface ) 01330 { 01331 PartitionCoSurf* cos = 0; 01332 while( (cos = surface->next_co_surface( cos )) ) 01333 cos->get_shell()->add( new_surface, cos->sense() ); 01334 if( surface->owner() ) 01335 surface->owner()->notify_split( new_surface, surface ); 01336 return new_surface; 01337 } 01338 else 01339 { 01340 if( surface->owner() ) 01341 surface->owner()->notify_topology_modified( surface ); 01342 return surface; 01343 } 01344 } 01345 01346 01347 //------------------------------------------------------------------------- 01348 // Purpose : Find where to insert a curve in a loop 01349 // 01350 // Special Notes : 01351 // 01352 // Creator : Jason Kraftcheck 01353 // 01354 // Creation Date : 03/24/03 01355 //------------------------------------------------------------------------- 01356 CubitStatus PartitionEngine::find_coedges( PartitionSurface* surface, 01357 PartitionCurve* curve, 01358 PartitionPoint* point, 01359 PartitionCoEdge*& previous, 01360 PartitionCoEdge*& next ) 01361 { 01362 const char* const bad_loop_message = "Internal error: Invalid loop. (%s:%d)\n"; 01363 01364 // Find list of all coedges around passed point 01365 // and in passed surface. 01366 DLIList<PartitionCoEdge*> point_coedges; 01367 PartitionCoEdge* coedge; 01368 PartitionCurve* pt_curve = 0; 01369 while ( (pt_curve = point->next_curve(pt_curve)) ) 01370 { 01371 coedge = 0; 01372 while ( (coedge = pt_curve->next_coedge(coedge)) ) 01373 { 01374 if (coedge->get_loop() && 01375 coedge->get_loop()->get_surface() == surface && 01376 !dynamic_cast<PartPTCurve*>(coedge->get_curve())) 01377 point_coedges.append(coedge); 01378 } 01379 } 01380 01381 // TBPoint is at end of a sipe/hardline 01382 if ( point_coedges.size() == 0 ) 01383 { 01384 previous = next = 0; 01385 return CUBIT_SUCCESS; 01386 } 01387 01388 // One coedge - closed curve 01389 if ( point_coedges.size() == 1 && 01390 point_coedges.get()->start_point() == 01391 point_coedges.get()->end_point() ) 01392 { 01393 previous = next = point_coedges.get(); 01394 return CUBIT_SUCCESS; 01395 } 01396 01397 // Broken loop? 01398 if ( point_coedges.size() % 2 != 0 ) 01399 { 01400 PRINT_ERROR(bad_loop_message,__FILE__,__LINE__); 01401 assert(0); 01402 return CUBIT_FAILURE; 01403 } 01404 01405 // If only two coedges, then we're done 01406 // If closed curve, the answer may be the same coedge for both 01407 // prev and next. E.g. A torus cracked along the outside major 01408 // radius and a sipe that intersects that crack curve. Need 01409 // to fall though to the more complex check below in that case. 01410 if ( point_coedges.size() == 2 && 01411 point_coedges.get()->get_curve()->start_point() != 01412 point_coedges.get()->get_curve()->end_point() && 01413 point_coedges.next()->get_curve()->start_point() != 01414 point_coedges.next()->get_curve()->end_point() ) 01415 { 01416 previous = point_coedges.get(); 01417 next = point_coedges.next(); 01418 01419 if ( previous->start_point() == point ) 01420 std::swap(previous, next); 01421 01422 return CUBIT_SUCCESS; 01423 } 01424 01425 // Find previous/next coedges by using order of 01426 // facet edges about point in surface facetting. 01427 CubitPointData* facet_point = point->facet_point(); 01428 DLIList<CubitFacetEdgeData*> curve_edges; 01429 curve->get_facet_data(curve_edges); 01430 01431 CubitFacetEdgeData* edge; 01432 //bool edge_reversed; 01433 if ( point == curve->start_point() ) 01434 { 01435 curve_edges.reset(); 01436 edge = curve_edges.get(); 01437 } 01438 else 01439 { 01440 assert(curve->end_point() == point); 01441 curve_edges.last(); 01442 edge = curve_edges.get(); 01443 } 01444 01445 PartitionCurve *prev_curve, *next_curve; 01446 prev_curve = next_curve_around_point( surface, edge, facet_point, true ); 01447 next_curve = next_curve_around_point( surface, edge, facet_point, false ); 01448 01449 if ( !prev_curve || !next_curve ) 01450 { 01451 PRINT_ERROR(bad_loop_message,__FILE__,__LINE__); 01452 assert(0); 01453 return CUBIT_FAILURE; 01454 } 01455 01456 coedge = 0; 01457 while ( (coedge = prev_curve->next_coedge(coedge)) ) 01458 { 01459 if ( coedge->get_loop() && // parent not a partition surface? 01460 coedge->get_loop()->get_surface() == surface && 01461 coedge->end_point() == point ) 01462 { 01463 previous = coedge; 01464 break; 01465 } 01466 } 01467 coedge = 0; 01468 while ( (coedge = next_curve->next_coedge(coedge)) ) 01469 { 01470 if ( coedge->get_loop() && 01471 coedge->get_loop()->get_surface() == surface && 01472 coedge->start_point() == point ) 01473 { 01474 next = coedge; 01475 break; 01476 } 01477 } 01478 01479 return CUBIT_SUCCESS; 01480 } 01481 01482 PartitionCurve* PartitionEngine::next_curve_around_point( 01483 PartitionSurface *const surface, 01484 CubitFacetEdgeData *const start_edge, 01485 CubitPointData *const point, 01486 const bool backwards ) 01487 { 01488 //PartitionCoEdge* result = 0; 01489 CubitFacetEdge* edge = start_edge; 01490 01491 while ( edge->num_adj_facets() == 2 ) 01492 { 01493 CubitFacet* facet1 = edge->adj_facet(0); 01494 CubitFacet* facet2 = edge->adj_facet(1); 01495 assert (TDVGFacetOwner::get(facet1) == surface); 01496 assert (TDVGFacetOwner::get(facet2) == surface); 01497 01498 bool edge_reversed = edge->point(1) == point; 01499 int facet_sense = edge_reversed == backwards ? -1 : 1; 01500 int facet1_index = facet1->edge_index(edge); 01501 #ifndef NDEBUG 01502 int facet2_index = facet2->edge_index(edge); 01503 assert(facet1->edge_use(facet1_index) == -facet2->edge_use(facet2_index)); 01504 #endif 01505 01506 if ( facet_sense == facet1->edge_use(facet1_index) ) 01507 edge = facet1->next_edge_at_point( edge, point ); 01508 else 01509 edge = facet2->next_edge_at_point( edge, point ); 01510 01511 assert(edge != start_edge); 01512 01513 PartitionEntity* edge_owner = TDVGFacetOwner::get(edge); 01514 PartitionCurve* curve = dynamic_cast<PartitionCurve*>(edge_owner); 01515 if ( curve ) 01516 return curve; 01517 } 01518 01519 return 0; 01520 } 01521 01522 01523 01524 //------------------------------------------------------------------------- 01525 // Purpose : Un-partition a surface 01526 // 01527 // Special Notes : 01528 // 01529 // Creator : Jason Kraftcheck 01530 // 01531 // Creation Date : 02/23/03 01532 //------------------------------------------------------------------------- 01533 Surface* PartitionEngine::remove_curve( PartitionCurve* passed_curve, 01534 PartitionSurface* dead_surfs[2] ) 01535 { 01536 if( dead_surfs ) 01537 dead_surfs[0] = dead_surfs[1] = 0; 01538 01539 PartPTCurve* point_curve = dynamic_cast<PartPTCurve*>(passed_curve); 01540 if( point_curve ) 01541 { 01542 PartitionSurface* surf = 01543 point_curve->next_coedge(0)->get_loop()->get_surface(); 01544 if( !remove_point_curve( point_curve->start_point() ) ) 01545 return 0; 01546 01547 SubSurface* subsurf = dynamic_cast<SubSurface*>(surf); 01548 if( subsurf && !subsurf->next_co_surface() && 01549 !subsurf->sub_entity_set().has_lower_order() ) 01550 { 01551 Surface* result = restore_surface( subsurf ); 01552 if( result && dead_surfs ) 01553 dead_surfs[0] = subsurf; 01554 return result; 01555 } 01556 else 01557 return surf; 01558 } 01559 01560 SegmentedCurve* curve = dynamic_cast<SegmentedCurve*>(passed_curve); 01561 01562 if( !curve ) 01563 { 01564 assert(0); 01565 } 01566 /* 01567 assert( dynamic_cast<SubCurve*>(passed_curve) ); 01568 01569 PartitionCoEdge* coedge1 = passed_curve->next_coedge(0); 01570 PartitionCoEdge* coedge2 = passed_curve->next_coedge(coedge1); 01571 if( !coedge2 || passed_curve->next_coedge(coedge2) ) 01572 return 0; 01573 01574 DLIList<TopologyBridge*> surfaces; 01575 coedge1->find_parent_loop()->get_parents_virt( surfaces ); 01576 fix_up_query_results( surfaces ); 01577 assert( surfaces.size() == 1 ); 01578 Surface* surface1 = dynamic_cast<Surface*>(surfaces.get()); 01579 surfaces.clean_out(); 01580 coedge2->find_parent_loop()->get_parents_virt( surfaces ); 01581 fix_up_query_results( surfaces ); 01582 assert( surfaces.size() == 1 ); 01583 Surface* surface2 = dynamic_cast<Surface*>(surfaces.get()); 01584 01585 SubSurface* surf1 = dynamic_cast<SubSurface*>(surface1); 01586 SubSurface* surf2 = dynamic_cast<SubSurface*>(surface2); 01587 if( surface1 == surface2 ) 01588 { 01589 if( !surf1 ) 01590 surf1 = surf2 = replace_surface( surface1 ); 01591 } 01592 else 01593 { 01594 if( !surf1 ) 01595 surf1 = replace_surface( surface1 ); 01596 if( !surf2 ) 01597 surf2 = replace_surface( surface2 ); 01598 } 01599 01600 // create SegmentedCurves from SubCurves 01601 01602 01603 CompositeEngine::instance()-> 01604 remove_curve( dynamic_cast<Curve*>(passed_curve->partitioned_entity()) ); 01605 } 01606 */ 01607 DLIList<TopologyBridge*> tb_list; 01608 01609 // get two coedges to remove 01610 curve->get_parents_virt( tb_list ); 01611 if( tb_list.size() != 2 ) 01612 return 0; 01613 PartitionCoEdge* coedge1 = dynamic_cast<PartitionCoEdge*>(tb_list.get_and_step()); 01614 PartitionCoEdge* coedge2 = dynamic_cast<PartitionCoEdge*>(tb_list.get_and_step()); 01615 assert( coedge1 && coedge2 ); 01616 01617 // get two loops and surfaces 01618 PartitionLoop* loop1 = coedge1->get_loop(); 01619 PartitionLoop* loop2 = coedge2->get_loop(); 01620 PartitionSurface* surf1 = loop1->get_surface(); 01621 PartitionSurface* surf2 = loop2->get_surface(); 01622 assert( surf1 && surf2 ); 01623 01624 // surfaces must be partitions of the same real surface 01625 if( surf1->partitioned_entity() != surf2->partitioned_entity() ) 01626 return 0; 01627 01628 // surfaces must have same parent shells 01629 PartitionCoSurf* cos = 0; 01630 while( (cos = surf1->next_co_surface( cos )) ) 01631 if( ! surf2->find_first( cos->get_shell(), cos->sense() ) ) 01632 return 0; 01633 01634 // same loop : remove a sipe or split a loop 01635 if( loop1 == loop2 ) 01636 { 01637 if( loop1->next_coedge( coedge1 ) != coedge2 && 01638 loop1->prev_coedge( coedge1 ) != coedge2 ) 01639 { 01640 loop2 = new PartitionLoop(); 01641 PartitionCoEdge* coedge = loop1->next_coedge( coedge1 ); 01642 PartitionCoEdge* prev = 0; 01643 while( coedge != coedge2 ) 01644 { 01645 loop1->remove( coedge ); 01646 loop2->insert_after( coedge, prev ); 01647 prev = coedge; 01648 coedge = loop1->next_coedge( coedge1 ); 01649 } 01650 01651 surf1->add( loop2 ); 01652 } 01653 01654 loop1->remove( coedge1 ); 01655 loop1->remove( coedge2 ); 01656 if( loop1->first_coedge() == 0 ) 01657 { 01658 surf1->remove( loop1 ); 01659 delete loop1; 01660 } 01661 } 01662 // stitch loops 01663 else 01664 { 01665 // insert coedges 01666 while( loop2->next_coedge(coedge2) != coedge2 ) // all but the dead one 01667 { 01668 PartitionCoEdge* coedge = loop2->next_coedge( coedge2 ); 01669 loop2->remove( coedge ); 01670 loop1->insert_before( coedge, coedge1 ); 01671 } 01672 loop1->remove( coedge1 ); 01673 loop2->remove( coedge2 ); 01674 assert( loop2->first_coedge() == 0 ); 01675 surf2->remove( loop2 ); 01676 if( loop1->num_coedges() == 0 ) 01677 { 01678 surf1->remove( loop1 ); 01679 delete loop1; 01680 } 01681 01682 delete loop2; 01683 } 01684 01685 curve->remove( coedge1 ); 01686 curve->remove( coedge2 ); 01687 delete coedge1; 01688 delete coedge2; 01689 PartitionPoint* start_pt = curve->start_point(); 01690 PartitionPoint* end_pt = curve->end_point(); 01691 curve->start_point(0); 01692 curve->end_point(0); 01693 delete curve; 01694 if ( !start_pt->next_curve() ) 01695 { 01696 if ( start_pt->real_point() ) 01697 restore_point(start_pt); 01698 else 01699 delete start_pt; 01700 } 01701 if ( end_pt != start_pt && !end_pt->next_curve() ) 01702 { 01703 if ( end_pt->real_point() ) 01704 restore_point(end_pt); 01705 else 01706 delete end_pt; 01707 } 01708 01709 // need to combine surfaces? 01710 if( surf1 != surf2 ) 01711 { 01712 surf1->combine( surf2 ); 01713 while( PartitionLoop* loop = surf2->next_loop() ) 01714 { 01715 surf2->remove( loop ); 01716 surf1->add( loop ); 01717 } 01718 01719 while( PartitionCoSurf* cos = surf2->next_co_surface() ) 01720 { 01721 if( cos->get_shell() ) 01722 cos->get_shell()->remove( cos ); 01723 surf2->remove( cos ); 01724 delete cos; 01725 } 01726 01727 if( dead_surfs ) 01728 dead_surfs[0] = surf2; 01729 delete surf2; 01730 } 01731 01732 // can remove partition surface? 01733 SubSurface* subsurf = dynamic_cast<SubSurface*>(surf1); 01734 if( subsurf && !subsurf->next_co_surface() && 01735 !subsurf->sub_entity_set().has_lower_order() ) 01736 { 01737 if( dead_surfs ) 01738 { 01739 if( dead_surfs[0] ) 01740 dead_surfs[1] = surf1; 01741 else 01742 dead_surfs[0] = surf1; 01743 } 01744 return restore_surface( subsurf ); 01745 } 01746 else 01747 return surf1; 01748 } 01749 01750 //------------------------------------------------------------------------- 01751 // Purpose : Find the facet that: 01752 // - contains the passed edge 01753 // - uses the passed edge in the specified orientation 01754 // - is owned by the passed entity 01755 // 01756 // Special Notes : 01757 // 01758 // Creator : Jason Kraftcheck 01759 // 01760 // Creation Date : 02/23/03 01761 //------------------------------------------------------------------------- 01762 static CubitFacetData* find_facet( CubitFacetEdge* edge, 01763 bool sense, 01764 PartitionEntity* owner ) 01765 { 01766 DLIList<CubitFacet*> facets(2); 01767 edge->facets(facets); 01768 facets.reset(); 01769 for ( int i = facets.size(); i--; ) { 01770 CubitFacet* facet = facets.get(); 01771 int edge_index = facet->edge_index(edge); 01772 assert(edge_index >= 0); 01773 bool forward = edge->point(0) == facet->point((edge_index+1)%3); 01774 if ( forward != sense || TDVGFacetOwner::get(facet) != owner ) 01775 facets.extract(); 01776 else 01777 facets.step(); 01778 } 01779 01780 return facets.size() == 1 ? dynamic_cast<CubitFacetData*>(facets.get()) : 0; 01781 } 01782 01783 //------------------------------------------------------------------------- 01784 // Purpose : Find a facet adjacent to the passed point and owned by 01785 // the passed PartitionEntity 01786 // 01787 // Special Notes : 01788 // 01789 // Creator : Jason Kraftcheck 01790 // 01791 // Creation Date : 02/23/03 01792 //------------------------------------------------------------------------- 01793 static CubitFacetData* find_facet( CubitPoint* pt, PartitionEntity* owner ) 01794 { 01795 DLIList<CubitFacet*> facets; 01796 pt->facets(facets); 01797 facets.reset(); 01798 for ( int i = facets.size(); i--; ) 01799 { 01800 if ( TDVGFacetOwner::get(facets.get()) == owner ) 01801 facets.step(); 01802 else 01803 facets.extract(); 01804 } 01805 01806 return facets.size() == 1 ? dynamic_cast<CubitFacetData*>(facets.get()) : 0; 01807 } 01808 01809 //------------------------------------------------------------------------- 01810 // Purpose : Find the facet adjacent to the passed facet on the 01811 // specified edge, and owned by the passed PartitionEntity 01812 // 01813 // Special Notes : 01814 // 01815 // Creator : Jason Kraftcheck 01816 // 01817 // Creation Date : 02/23/03 01818 //------------------------------------------------------------------------- 01819 static CubitFacetData* other_facet( CubitFacetData* facet, 01820 int edge, 01821 PartitionEntity* owner ) 01822 { 01823 DLIList<CubitFacet*> facets; 01824 facet->shared_facets( facet->point((edge+1)%3), 01825 facet->point((edge+2)%3), 01826 facets ); 01827 for ( int i = facets.size(); i--; ) 01828 { 01829 CubitFacet* facet = facets.get(); 01830 if( TDVGFacetOwner::get(facet) != owner ) 01831 facets.extract(); 01832 else 01833 facets.step(); 01834 } 01835 01836 return facets.size() == 1 ? dynamic_cast<CubitFacetData*>(facets.get()) : 0; 01837 } 01838 /* 01839 static void draw_facet_edges( CubitFacet* facet, int color ) 01840 { 01841 float x1, y1, z1, x2, y2, z2; 01842 for ( int i = 0; i < 3; i++ ) 01843 { 01844 x1 = (float)facet->point(i)->coordinates().x(); 01845 y1 = (float)facet->point(i)->coordinates().y(); 01846 z1 = (float)facet->point(i)->coordinates().z(); 01847 x2 = (float)facet->point((i+1)%3)->coordinates().x(); 01848 y2 = (float)facet->point((i+1)%3)->coordinates().y(); 01849 z2 = (float)facet->point((i+1)%3)->coordinates().z(); 01850 GfxDebug::draw_line(x1,y1,z1,x2,y2,z2,color); 01851 } 01852 GfxDebug::flush(); 01853 } 01854 01855 static void draw_facet_point( CubitPoint* pt, int color ) 01856 { 01857 float x = (float)pt->coordinates().x(); 01858 float y = (float)pt->coordinates().y(); 01859 float z = (float)pt->coordinates().z(); 01860 GfxDebug::draw_point( x, y, z, color ); 01861 GfxDebug::flush(); 01862 } 01863 01864 static void draw_facet_points( CubitFacet* facet, int color ) 01865 { 01866 draw_facet_point(facet->point(0), color); 01867 draw_facet_point(facet->point(1), color); 01868 draw_facet_point(facet->point(2), color); 01869 } 01870 */ 01871 01872 01873 //------------------------------------------------------------------------- 01874 // Purpose : Split surface using facet data, given a coedge along 01875 // the split chain. 01876 // 01877 // Special Notes : 01878 // 01879 // Creator : Jason Kraftcheck 01880 // 01881 // Creation Date : 02/23/03 01882 //------------------------------------------------------------------------- 01883 PartitionSurface* PartitionEngine::split_surface( PartitionSurface* surface, 01884 PartitionCoEdge* new_coedge ) 01885 { 01886 int i; 01887 01888 // get surface facets and make sure marks are cleared 01889 DLIList<CubitFacetData*> faces; 01890 surface->get_facet_data(faces); 01891 for( i = faces.size(); i--; ) 01892 faces.get_and_step()->marked(0); 01893 01894 01895 // get curve and curve's facet edges 01896 PartitionCurve* new_curve = dynamic_cast<PartitionCurve*>(new_coedge->get_curve()); 01897 DLIList<CubitFacetEdgeData*> edges; 01898 new_curve->get_facet_data( edges ); 01899 assert(edges.size()); 01900 01901 // get the first point in the curve's facet edges 01902 edges.reset(); 01903 CubitFacetEdgeData* edge = edges.get(); 01904 CubitPoint* pt = edge->point(0); 01905 if ( TDVGFacetOwner::get(pt) != new_curve->start_point() ) 01906 { 01907 pt = edge->point(1); 01908 assert(TDVGFacetOwner::get(pt) == new_curve->start_point()); 01909 } 01910 01911 // get the facets on the surface on the inside size of 01912 // the coedge 01913 bool coedge_forward = new_coedge->sense() == CUBIT_FORWARD; 01914 DLIList<CubitFacetData*> front( faces.size() ); 01915 for ( i = edges.size(); i--; ) 01916 { 01917 edge = edges.get_and_step(); 01918 bool edge_forward = edge->point(0) == pt; 01919 bool sense = edge_forward == coedge_forward; 01920 CubitFacetData* face = find_facet( edge, sense, surface ); 01921 if( face->marked() == 0 ) 01922 { 01923 //draw_facet_edges(face,CUBIT_RED_INDEX); 01924 face->marked(1); 01925 front.append( face ); 01926 } 01927 pt = edge->other_point(pt); 01928 } 01929 01930 // mark all adjacent facets traversing only over 01931 // edges that are in the interior of the surface 01932 while( front.size() ) 01933 { 01934 CubitFacetData* face = front.pop(); 01935 for( i = 0; i < 3; i++ ) 01936 { 01937 if( face->edge(i) && TDVGFacetOwner::get(face->edge(i)) ) 01938 continue; 01939 01940 CubitFacetData* other = other_facet( face, i, surface ); 01941 if ( other->marked() == 0 ) 01942 { 01943 //draw_facet_edges(face,CUBIT_BLUE_INDEX); 01944 other->marked(1); 01945 front.append(other); 01946 } 01947 } 01948 } 01949 01950 // reuse front to hold all the facets we marked 01951 for( i = faces.size(); i--; ) 01952 { 01953 CubitFacetData* face = faces.get_and_step(); 01954 if( face->marked() ) 01955 front.append( face ); 01956 } 01957 01958 // if we got back all the facets, then the surface 01959 // was not split! 01960 if( front.size() == faces.size() ) 01961 { 01962 for( i = faces.size(); i--; ) 01963 faces.get_and_step()->marked(0); 01964 01965 return surface; 01966 } 01967 // split off a new PartitionSurface 01968 PartitionSurface* new_surf = surface->split( front ); 01969 01970 // get list of all loops in surface 01971 DLIList<PartitionLoop*> loops( surface->num_loops() ); 01972 PartitionLoop* loop = 0; 01973 while( (loop = surface->next_loop( loop )) ) 01974 loops.append( loop ); 01975 01976 // check which loops we need to move to the new surface 01977 while( loops.size() ) 01978 { 01979 loop = loops.pop(); 01980 PartitionCoEdge* coe = loop->first_coedge(); 01981 01982 if( !coe ) 01983 continue; 01984 01985 PartitionCurve* curve = coe->get_curve(); 01986 01987 CubitFacetData* face =0; 01988 if( PartPTCurve* ptc = dynamic_cast<PartPTCurve*>(curve) ) 01989 { 01990 face = find_facet( ptc->start_point()->facet_point(), new_surf ); 01991 } 01992 else 01993 { 01994 edges.clean_out(); 01995 curve->get_facet_data( edges ); 01996 if (edges.size() > 0) // normal facet 01997 { 01998 edges.reset(); 01999 edge = edges.get(); 02000 CubitPoint* start_pt = curve->start_point()->facet_point(); 02001 bool forward = edge->point(0) == start_pt; 02002 assert( forward || edge->point(1) == start_pt ); 02003 if ( coe->sense() == CUBIT_REVERSED ) 02004 forward = !forward; 02005 face = find_facet( edge, forward, new_surf ); 02006 } 02007 else // this is a hardpoint there is a curve with no facets (length) 02008 // and the start and end points are the same 02009 { 02010 TBPoint* hardpoint = curve->start_point()->real_point(); 02011 if (hardpoint && curve->start_point() == curve->end_point() ) 02012 { 02013 CubitVector hardpoint_coord = hardpoint->coordinates(); 02014 CubitVector new_closest, old_closest; 02015 new_surf->closest_point_trimmed( hardpoint_coord, new_closest ); 02016 surface->closest_point_trimmed( hardpoint_coord, old_closest ); 02017 // It appears that the new_surf is really the original surface 02018 if ( new_closest.length_squared() > old_closest.length_squared() ) 02019 face = reinterpret_cast<CubitFacetData*>(1); // just set the point to non-zero (true) 02020 } 02021 } 02022 } 02023 02024 if( face ) 02025 { 02026 surface->remove( loop ); 02027 new_surf->add( loop ); 02028 } 02029 } 02030 /* 02031 PartitionCoSurf* cos = 0; 02032 while( (cos = surface->next_co_surface( cos )) ) 02033 cos->get_shell()->add( new_surf, cos->sense() ); 02034 */ 02035 for( i = faces.size(); i--; ) 02036 faces.get_and_step()->marked(0); 02037 02038 return new_surf; 02039 } 02040 02041 02042 //------------------------------------------------------------------------- 02043 // Purpose : Public interface to surface partitioning. 02044 // 02045 // Special Notes : 02046 // 02047 // Creator : Jason Kraftcheck 02048 // 02049 // Creation Date : 02/23/03 02050 //------------------------------------------------------------------------- 02051 Surface* PartitionEngine::insert_curve( Surface* surface, 02052 DLIList<CubitVector*>& segment_points, 02053 DLIList<Curve*>& new_curves, 02054 const double *tolerance_length) 02055 { 02056 DLIList<Surface*> input_surfs(1), output_surfs(2); 02057 input_surfs.append(surface); 02058 if ( ! insert_curve(input_surfs, segment_points, output_surfs, new_curves, 02059 tolerance_length) ) 02060 return 0; 02061 02062 return output_surfs.size() ? output_surfs.get() : surface; 02063 } 02064 02065 //------------------------------------------------------------------------- 02066 // Purpose : Public interface to surface partitioning 02067 // 02068 // Special Notes : 02069 // 02070 // Creator : Jason Kraftcheck 02071 // 02072 // Creation Date : 02/23/03 02073 //------------------------------------------------------------------------- 02074 CubitStatus PartitionEngine::insert_curve( 02075 DLIList<Surface*>& input_surfaces, 02076 DLIList<CubitVector*>& segment_points, 02077 DLIList<Surface*>& new_surfaces, 02078 DLIList<Curve*>& new_curves, 02079 const double *tolerance_length, 02080 DLIList<Surface*>* surfs_to_reverse) 02081 { 02082 int i; 02083 CubitStatus result = CUBIT_SUCCESS; 02084 02085 for ( i = input_surfaces.size(); i--; ) 02086 if ( dynamic_cast<CompositeSurface*>(input_surfaces.get_and_step()) ) 02087 return CompositeEngine::instance().insert_curve( 02088 input_surfaces, segment_points, new_surfaces, new_curves ); 02089 02090 DLIList<SubSurface*> replaced_surfaces; 02091 DLIList<PartitionSurface*> surface_list, new_part_surfs; 02092 DLIList<PartitionCurve*> curve_list; 02093 02094 // get partition surfaces 02095 for ( i = input_surfaces.size(); i--; ) 02096 { 02097 int reverse_surf = 0; 02098 Surface* surf = input_surfaces.get_and_step(); 02099 02100 // We will need to reverse the surface and its facets if it 02101 // is in the passed-in list of surfaces to reverse. 02102 if(surfs_to_reverse && surfs_to_reverse->is_in_list(surf)) 02103 reverse_surf = 1; 02104 PartitionSurface* partsurf = dynamic_cast<PartitionSurface*>(surf); 02105 if( partsurf ) 02106 { 02107 surface_list.append(partsurf); 02108 if(reverse_surf) 02109 partsurf->reverse_sense(); 02110 } 02111 else 02112 { 02113 SubSurface* subsurf = replace_surface(surf); 02114 if (!subsurf) 02115 { 02116 result = CUBIT_FAILURE; 02117 break; 02118 } 02119 02120 replaced_surfaces.append( subsurf ); 02121 surface_list.append(subsurf); 02122 if(reverse_surf) 02123 subsurf->reverse_sense(); 02124 } 02125 } 02126 02127 if (result) 02128 { 02129 result = insert_curve( surface_list, segment_points, new_part_surfs, curve_list, 02130 tolerance_length); 02131 } 02132 if (!result) 02133 { 02134 // we replaced the original surface we need to clean up also 02135 for ( i = replaced_surfaces.size(); i--; ) 02136 { 02137 SubSurface* surf = replaced_surfaces.step_and_get(); 02138 restore_surface( surf ); // this also deletes the virtual surface 02139 } 02140 02141 return result; 02142 } 02143 02144 CAST_LIST_TO_PARENT(curve_list,new_curves); 02145 CAST_LIST_TO_PARENT(new_part_surfs,new_surfaces); 02146 02147 // clean up any partition surfaces we created but didn't modify 02148 for ( i = replaced_surfaces.size(); i--; ) 02149 { 02150 SubSurface* surf = replaced_surfaces.step_and_get(); 02151 if ( !surf->sub_entity_set().has_lower_order() && 02152 !surf->next_co_surface(0) ) 02153 { 02154 restore_surface( surf ); 02155 } 02156 else 02157 { 02158 new_surfaces.append( surf ); 02159 } 02160 } 02161 02162 return result; 02163 } 02164 02165 void PartitionEngine::curves_from_surfaces( const DLIList<PartitionSurface*>& surfs, 02166 DLIList<PartitionCurve*>& curves ) 02167 { 02168 int i; 02169 02170 for (i = curves.size(); i--; ) 02171 curves.step_and_get()->mark = 1; 02172 02173 for (i = surfs.size(); i--; ) 02174 { 02175 PartitionSurface* surf = surfs.next(i); 02176 PartitionLoop* loop = 0; 02177 while ( (loop = surf->next_loop(loop)) ) 02178 { 02179 PartitionCoEdge* coedge = loop->first_coedge(); 02180 do { 02181 PartitionCurve* curve = coedge->get_curve(); 02182 if (!curve->mark) 02183 { 02184 curve->mark = 1; 02185 curves.append(curve); 02186 } 02187 02188 coedge = loop->next_coedge(coedge); 02189 } while (coedge != loop->first_coedge()); 02190 } 02191 } 02192 02193 for ( i = curves.size(); i--; ) 02194 curves.step_and_get()->mark = 0; 02195 curves.reset(); 02196 } 02197 02198 02199 CubitStatus PartitionEngine::insert_curve( DLIList<PartitionSurface*>& surface_list, 02200 DLIList<CubitVector*>& segment_points, 02201 DLIList<PartitionSurface*>& new_part_surfs, 02202 DLIList<PartitionCurve*>& curve_list, 02203 const double *tolerance_length) 02204 { 02205 int i; 02206 const double TOL_SQR = GEOMETRY_RESABS*GEOMETRY_RESABS; 02207 02208 // Get curves 02209 DLIList<PartitionCurve*> curves; 02210 curves_from_surfaces( surface_list, curves ); 02211 02212 // Check for intersections with boundary curves 02213 segment_points.reset(); 02214 curves.reset(); 02215 for ( i = segment_points.size(); i--; ) 02216 { 02217 CubitVector& pos = *segment_points.get_and_step(); 02218 bool debug = false; 02219 if (debug) 02220 { 02221 GfxDebug::draw_point(pos, CUBIT_BLUE_INDEX); 02222 GfxDebug::mouse_xforms(); 02223 } 02224 for ( int j = curves.size(); j--; ) 02225 { 02226 PartitionCurve* curve = curves.get_and_step(); 02227 if ((curve->start_point()->coordinates() - pos).length_squared() < TOL_SQR) 02228 { 02229 pos = curve->start_point()->coordinates(); 02230 break; 02231 } 02232 02233 if ((curve->end_point()->coordinates() - pos).length_squared() < TOL_SQR) 02234 { 02235 pos = curve->end_point()->coordinates(); 02236 break; 02237 } 02238 02239 CubitVector closest; 02240 curve->closest_point_trimmed( pos, closest ); 02241 02242 if ( (pos - closest).length_squared() > TOL_SQR ) 02243 continue; 02244 02245 if ((curve->start_point()->coordinates() - closest).length_squared() < TOL_SQR) 02246 { 02247 pos = curve->start_point()->coordinates(); 02248 break; 02249 } 02250 02251 if ((curve->end_point()->coordinates() - closest).length_squared() < TOL_SQR) 02252 { 02253 pos = curve->end_point()->coordinates(); 02254 break; 02255 } 02256 /* 02257 double u = curve->u_from_position(closest); 02258 TBPoint* point = insert_point( curve, u ); 02259 if (!point) 02260 { 02261 PRINT_ERROR("Error splitting curve. Aborting.\n"); 02262 return CUBIT_FAILURE; 02263 } 02264 pos = point->coordinates(); 02265 */ 02266 pos = closest; 02267 break; 02268 } 02269 } 02270 02271 02272 // get surface facets 02273 DLIList<CubitFacetData*> surf_facets, facet_list; 02274 surface_list.reset(); 02275 for ( i = surface_list.size(); i--; ) 02276 { 02277 surf_facets.clean_out(); 02278 surface_list.get_and_step()->get_facet_data( surf_facets ); 02279 facet_list += surf_facets; 02280 } 02281 02282 // Do facet projection 02283 DLIList<CubitFacetEdgeData*> polyline; 02284 DLIList<CubitPointData*> polyline_pts; 02285 project_to_surface( facet_list, segment_points, polyline, polyline_pts, tolerance_length); 02286 02287 if(segment_points.size() == polyline_pts.size()) 02288 { 02289 // Move facet points to real geometry 02290 DLIList<CubitFacetEdge*> edge_list; 02291 DLIList<CubitFacet*> pt_facets; 02292 segment_points.reset(); 02293 polyline_pts.reset(); 02294 int count = 0; 02295 for ( i = segment_points.size(); i--; ) 02296 { 02297 CubitPointData* facet_pt = polyline_pts.get_and_step(); 02298 CubitVector position( *segment_points.get_and_step() ); 02299 if ( !facet_pt ) 02300 continue; 02301 02302 PartitionPoint* point = dynamic_cast<PartitionPoint*>(TDVGFacetOwner::get(facet_pt)); 02303 if ( point ) 02304 { 02305 count++; 02306 continue; 02307 } 02308 02309 PartitionCurve* curve = 0; 02310 edge_list.clean_out(); 02311 facet_pt->edges( edge_list ); 02312 while ( edge_list.size() ) 02313 { 02314 02315 PartitionEntity* owner = TDVGFacetOwner::get(edge_list.pop()); 02316 if ( owner ) 02317 { 02318 assert(!curve || curve == owner); 02319 curve = dynamic_cast<PartitionCurve*>(owner); 02320 } 02321 } 02322 if ( curve ) 02323 { 02324 Surface* surface = dynamic_cast<Surface*>(curve->partitioned_entity()); 02325 if ( surface ) 02326 { 02327 CubitVector surf_pos; 02328 surface->closest_point( position, &surf_pos ); 02329 if (facet_pt->check_inverted_facets(surf_pos)) 02330 facet_pt->set( surf_pos ); 02331 } 02332 else 02333 curve->relax_to_geometry( facet_pt, &position ); 02334 02335 continue; 02336 } 02337 02338 PartitionSurface* surf = 0; 02339 pt_facets.clean_out(); 02340 facet_pt->facets( pt_facets ); 02341 while ( pt_facets.size() ) 02342 { 02343 PartitionEntity* owner = TDVGFacetOwner::get(pt_facets.pop()); 02344 if ( owner ) 02345 { 02346 assert(!surf || surf == owner); 02347 surf = dynamic_cast<PartitionSurface*>(owner); 02348 } 02349 } 02350 if ( surf && dynamic_cast<SubSurface*>(surf) ) 02351 { 02352 surf->relax_to_geometry( facet_pt, &position ); 02353 } 02354 } 02355 } 02356 02357 if ( !polyline.size() ) 02358 return CUBIT_FAILURE; 02359 02360 //In the following lines we see if we need to split curves on 02361 //the boundary of the surface. This is necessary when the endpoints of 02362 //the polylines used for partitioning are not coincident with 02363 //boundary curves. 02364 02365 //get all the facet points of the polyline 02366 DLIList<CubitPoint*> points_on_polyline; 02367 for( int k=polyline.size(); k--; ) 02368 { 02369 CubitFacetEdgeData *tmp_edge = polyline.get_and_step(); 02370 if( !tmp_edge ) 02371 continue; 02372 points_on_polyline.append_unique( tmp_edge->start_node() ); 02373 points_on_polyline.append_unique( tmp_edge->end_node() ); 02374 } 02375 02376 //get all the resulting facets 02377 DLIList<CubitFacet*> facets_after; 02378 for ( i = surface_list.size(); i--; ) 02379 { 02380 surf_facets.clean_out(); 02381 surface_list.get_and_step()->get_facet_data( surf_facets ); 02382 for( int s=surf_facets.size(); s--; ) 02383 facets_after.append( surf_facets.get_and_step() ); 02384 } 02385 02386 //from the facets, collect all the boundary points 02387 DLIList<CubitPoint*> boundary_pts; 02388 FacetDataUtil::get_boundary_points( facets_after, boundary_pts ); 02389 02390 //for each polyline points... 02391 for( int k=points_on_polyline.size(); k--; ) 02392 { 02393 CubitPoint *tmp_pt = points_on_polyline.get_and_step(); 02394 02395 //if the point is on the boundary... 02396 if( boundary_pts.is_in_list( tmp_pt ) ) 02397 { 02398 PartitionPoint* point = dynamic_cast<PartitionPoint*>(TDVGFacetOwner::get(tmp_pt)); 02399 if( !point ) //if the point is not already a vertex on the boundary... 02400 { 02401 //find the adjacent boundary curve that we'll insert these points into 02402 DLIList<CubitFacetEdge*> adj_edges; 02403 tmp_pt->edges( adj_edges ); 02404 02405 for( int s=adj_edges.size(); s--; ) 02406 { 02407 CubitFacetEdge *tmp_edge = adj_edges.get_and_step(); 02408 PartitionCurve* curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(tmp_edge)); 02409 if( curve ) 02410 { 02411 DLIList<TopologyBridge*> bridges; 02412 get_tbs_with_bridge_manager_as_owner(curve, bridges ); 02413 02414 if( bridges.size() == 0 ) 02415 CompositeEngine::instance().get_tbs_with_bridge_manager_as_owner( curve, bridges ); 02416 02417 RefEdge *ref_edge = dynamic_cast<RefEdge*>(bridges.get()->topology_entity()); 02418 RefEdge *edge1, *edge2; 02419 02420 //now do the split 02421 PartitionTool::instance()->partition( ref_edge, tmp_pt->coordinates(), edge1, edge2 ); 02422 break; 02423 } 02424 } 02425 } 02426 } 02427 } 02428 02429 // construct the curves 02430 DLIList<CubitFacetEdgeData*> cubit_edges; 02431 DLIList<CubitFacetEdge*> pt_edges; 02432 polyline.reset(); 02433 for ( i = polyline.size(); i > 0; ) 02434 { 02435 // get list of FacetPoints for Curve 02436 cubit_edges.clean_out(); 02437 CubitFacetEdgeData* edge = polyline.get_and_step(); 02438 if (!edge) { i--; continue; } 02439 02440 assert(!TDVGFacetOwner::get(edge) && 02441 edge->num_adj_facets() < 3 && 02442 edge->num_adj_facets() > 0); 02443 02444 PartitionEntity* owner = TDVGFacetOwner::get(edge->adj_facet(0)); 02445 assert( edge->num_adj_facets() == 1 || 02446 TDVGFacetOwner::get(edge->adj_facet(1)) == owner ); 02447 02448 cubit_edges.append( edge ); 02449 02450 while( polyline.get() ) 02451 { 02452 CubitPoint* pt = edge->shared_point(polyline.get()); 02453 edge = polyline.get(); 02454 02455 assert(!TDVGFacetOwner::get(edge) && 02456 edge->num_adj_facets() < 3 && 02457 edge->num_adj_facets() > 0 && pt); 02458 02459 PartitionEntity* tmp = TDVGFacetOwner::get(edge->adj_facet(0)); 02460 assert( edge->num_adj_facets() == 1 || 02461 TDVGFacetOwner::get(edge->adj_facet(1)) == tmp ); 02462 02463 bool edge_owner = false; 02464 pt->edges(pt_edges); 02465 while (pt_edges.size()) 02466 if (TDVGFacetOwner::get(pt_edges.pop())) 02467 edge_owner = true; 02468 02469 if ( tmp != owner || TDVGFacetOwner::get(pt) || edge_owner ) 02470 break; 02471 02472 cubit_edges.append( polyline.get_and_step() ); 02473 } 02474 if (NULL == polyline.get()) 02475 { 02476 polyline.step(); 02477 i -= 1; 02478 } 02479 i -= cubit_edges.size(); 02480 02481 // create curve and partition surface 02482 PartitionCurve* new_curve = insert_curve( cubit_edges, &segment_points ); 02483 if ( new_curve ) 02484 curve_list.append(new_curve); 02485 } 02486 02487 // find new surfaces to return 02488 for ( i = curve_list.size(); i--; ) 02489 { 02490 PartitionCurve* curve = curve_list.step_and_get(); 02491 PartitionCoEdge* coedge = 0; 02492 while( (coedge = curve->next_coedge(coedge)) ) 02493 { 02494 new_part_surfs.append( coedge->get_loop()->get_surface() ); 02495 } 02496 } 02497 02498 if ( curve_list.size() ) 02499 { 02500 // do facet cleanup 02501 for ( i = curve_list.size(); i--; ) 02502 curve_list.get_and_step()->do_facet_cleanup(); 02503 //for ( i = new_part_surfs.size(); i--; ) 02504 // new_part_surfs.get_and_step()->do_facet_cleanup(); 02505 } 02506 02507 02508 for ( i = new_part_surfs.size(); i--; ) 02509 new_part_surfs.step_and_get()->mark = 1; 02510 for ( i = surface_list.size(); i--; ) 02511 surface_list.step_and_get()->mark = 0; 02512 for ( i = new_part_surfs.size(); i--; ) 02513 if ( new_part_surfs.step_and_get()->mark ) 02514 new_part_surfs.get()->mark = 0; 02515 else 02516 new_part_surfs.change_to(0); 02517 new_part_surfs.remove_all_with_value(0); 02518 02519 return curve_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE; 02520 } 02521 02522 //------------------------------------------------------------------------- 02523 // Purpose : Given a polyline-imprint on the surface facetting, 02524 // construct a new and insert it in the surface topology. 02525 // 02526 // Special Notes : 02527 // 02528 // Creator : Jason Kraftcheck 02529 // 02530 // Creation Date : 02/23/03 02531 //------------------------------------------------------------------------- 02532 SegmentedCurve* PartitionEngine::insert_curve( 02533 DLIList<CubitFacetEdgeData*>& segments, 02534 DLIList<CubitVector*>* /*curve_geom*/ ) 02535 { 02536 int i; 02537 02538 // find surface 02539 PartitionSurface* surface = 0; 02540 DLIList<CubitFacet*> facets; 02541 for ( i = segments.size(); i--; ) 02542 { 02543 CubitFacetEdgeData* edge = segments.get_and_step(); 02544 facets.clean_out(); 02545 edge->facets(facets); 02546 assert(facets.size() == 2); 02547 for (int j = 0; j < facets.size(); j++ ) 02548 { 02549 CubitFacet* facet = facets.get_and_step(); 02550 PartitionEntity* fowner = TDVGFacetOwner::get(facet); 02551 PartitionSurface* surf = dynamic_cast<PartitionSurface*>(fowner); 02552 if ( !surf || (surface && surf != surface) ) 02553 { 02554 PRINT_ERROR("Internal Error in PartitionEngine. Corrupt facet data.\n"); 02555 assert(0); 02556 return 0; 02557 } 02558 surface = surf; 02559 } 02560 } 02561 02562 // if there is a real surface, relax facet points to surface 02563 Surface* real_surf = dynamic_cast<Surface*>(surface->partitioned_entity()); 02564 02565 // find start and end facet points 02566 CubitPointData* pts[2]; 02567 CubitPoint* pt; 02568 02569 if( segments.size() == 1 ) 02570 { 02571 pts[0] = dynamic_cast<CubitPointData*>(segments.get()->point(0)); 02572 pts[1] = dynamic_cast<CubitPointData*>(segments.get()->point(1)); 02573 } 02574 else 02575 { 02576 segments.last(); 02577 pt = segments.get()->shared_point( segments.prev() ); 02578 pt = segments.get()->other_point( pt ); 02579 pts[1] = dynamic_cast<CubitPointData*>(pt); 02580 segments.reset(); 02581 pt = segments.get()->shared_point( segments.next() ); 02582 pt = segments.get()->other_point( pt ); 02583 pts[0] = dynamic_cast<CubitPointData*>(pt); 02584 } 02585 02586 // create end points (partition curves if necessary) 02587 bool okay = true; 02588 DLIList<CubitFacetEdge*> edges; 02589 bool created_pts[2] = {false,false}; 02590 PartitionPoint* end_pts[2] = {0,0}; 02591 for ( i = 0; okay && i < 2; i++ ) 02592 { 02593 end_pts[i] = dynamic_cast<PartitionPoint*>(TDVGFacetOwner::get(pts[i])); 02594 if( end_pts[i] ) continue; 02595 02596 edges.clean_out(); 02597 pts[i]->edges(edges); 02598 PartitionCurve* curve = 0; 02599 for ( int j = edges.size(); !curve && j--; ) 02600 curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(edges.get_and_step())); 02601 02602 if( curve ) 02603 { 02604 curve->relax_to_geometry( pts[i] ); 02605 PartitionPoint* new_pt = new PartitionPoint( pts[i]->coordinates(), curve ); 02606 if ( insert_point( curve, new_pt ) ) 02607 { 02608 end_pts[i] = new_pt; 02609 created_pts[i] = true; 02610 assert( TDVGFacetOwner::get(pts[i]) == new_pt ); 02611 } 02612 else 02613 { 02614 delete new_pt; 02615 okay = false; 02616 } 02617 continue; 02618 } 02619 02620 facets.clean_out(); 02621 pts[i]->facets(facets); 02622 for ( int k = facets.size(); k--; ) 02623 if( TDVGFacetOwner::get(facets.get_and_step()) != surface ) 02624 { 02625 PRINT_ERROR("Internal Error in PartitionEngine. Corrupt facet data.\n"); 02626 okay = false; 02627 break; 02628 } 02629 02630 if( okay ) 02631 { 02632 if( real_surf ) 02633 surface->relax_to_geometry( pts[i] ); 02634 02635 end_pts[i] = new PartitionPoint( pts[i]->coordinates(), surface ); 02636 end_pts[i]->facet_point( pts[i] ); 02637 } 02638 } 02639 02640 // create curve 02641 SegmentedCurve* curve = 0; 02642 if( okay ) 02643 { 02644 DLIList<CubitVector*> vectors(segments.size()+1), *curve_geom_ptr; 02645 // if( curve_geom ) 02646 // { 02647 // curve_geom_ptr = curve_geom; 02648 // } 02649 // else 02650 { 02651 segments.reset(); 02652 pt = pts[0]; 02653 vectors.append( new CubitVector( pt->coordinates() ) ); 02654 for( i = segments.size(); i--; ) 02655 { 02656 pt = segments.get_and_step()->other_point(pt); 02657 if ( real_surf && i > 0 ) 02658 { 02659 surface->relax_to_geometry( pt ); 02660 } 02661 assert(!!pt); 02662 vectors.append( new CubitVector( pt->coordinates() ) ); 02663 } 02664 curve_geom_ptr = &vectors; 02665 } 02666 02667 curve = new SegmentedCurve( surface, *curve_geom_ptr ); 02668 02669 while( vectors.size() ) delete vectors.pop(); 02670 02671 curve->start_point( end_pts[0] ); 02672 curve->end_point( end_pts[1] ); 02673 curve->set_facet_data(segments); 02674 02675 if( insert_curve( surface, curve ) ) 02676 return curve; 02677 } 02678 02679 // If we got this far, then something went wrong. 02680 // Try to clean up. 02681 02682 if( curve ) 02683 { 02684 curve->start_point(0); 02685 curve->end_point(0); 02686 segments.clean_out(); 02687 curve->set_facet_data(segments); 02688 delete curve; 02689 } 02690 02691 for( i = 0; i < 2; i++ ) 02692 { 02693 if( ! created_pts[i] ) continue; 02694 02695 end_pts[i]->facet_point(0); 02696 if( dynamic_cast<Curve*>(end_pts[i]->partitioned_entity()) ) 02697 remove_point( end_pts[i] ); 02698 else 02699 delete end_pts[i]; 02700 } 02701 02702 return 0; 02703 } 02704 02705 /* 02706 //------------------------------------------------------------------------- 02707 // Purpose : Partition a curve using a facet point on the curve. 02708 // 02709 // Special Notes : 02710 // 02711 // Creator : Jason Kraftcheck 02712 // 02713 // Creation Date : 02/23/03 02714 //------------------------------------------------------------------------- 02715 PartitionPoint* PartitionEngine::insert_point( CubitPointData* pt ) 02716 { 02717 DLIList<CubitFacetEdge*> edges; 02718 pt->edges(edges); 02719 02720 PartitionCurve* curve = 0; 02721 for ( int i = edges.size(); i--; ) 02722 { 02723 CubitFacetEdge* edge = edges.step_and_get(); 02724 PartitionCurve* c = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(edge)); 02725 if( c ) 02726 { 02727 if( !curve ) 02728 curve = c; 02729 else if( curve != c ) 02730 { 02731 PRINT_ERROR("Internal Error in PartitionEngine. Corrupt facet data.\n"); 02732 return 0; 02733 } 02734 } 02735 } 02736 02737 DLIList<CubitFacetEdgeData*> segments, other_segments; 02738 curve->get_facet_data(segments); 02739 segments.last(); 02740 while( !segments.get()->contains( pt ) ) 02741 { 02742 other_segments.append( segments.pop() ); 02743 segments.last(); 02744 } 02745 other_segments.reverse(); 02746 02747 PartitionPoint* new_point = new PartitionPoint( pt->coordinates(), curve ); 02748 PartitionCurve* curve2 = insert_point( curve, new_point ); 02749 if( !curve2 ) 02750 { 02751 delete new_point; 02752 return 0; 02753 } 02754 02755 curve->set_facet_data(segments); 02756 curve2->set_facet_data(other_segments); 02757 new_point->facet_point(pt); 02758 return new_point; 02759 } 02760 */ 02761 02762 //------------------------------------------------------------------------- 02763 // Purpose : Add point to surface facetting. 02764 // 02765 // Special Notes : 02766 // 02767 // Creator : Jason Kraftcheck 02768 // 02769 // Creation Date : 02/23/03 02770 //------------------------------------------------------------------------- 02771 CubitPointData* PartitionEngine::project_to_surface( 02772 PartitionSurface* surface, 02773 const CubitVector& position ) 02774 { 02775 02776 CubitVector pos; 02777 CubitFacet* facet = surface->closest_facet( position, pos ); 02778 surface->closest_point( position, &pos ); 02779 CubitFacetData* facet_d = dynamic_cast<CubitFacetData*>(facet); 02780 DLIList<CubitFacetEdge*> pt_edges; 02781 assert(!!facet_d); 02782 02783 CubitVector p[3], v[3], d[3]; 02784 int i; 02785 02786 // Initialize data 02787 double dist_tol_sqr = CUBIT_DBL_MAX; 02788 for ( i = 0; i < 3; i++ ) { 02789 p[i] = facet_d->point(i)->coordinates(); 02790 v[i] = facet_d->point((i+1)%3)->coordinates() - p[i]; 02791 double dist_sqr = v[i].length_squared(); 02792 if ( dist_sqr < dist_tol_sqr ) 02793 dist_tol_sqr = dist_sqr; 02794 d[i] = pos - p[i]; 02795 } 02796 dist_tol_sqr *= 0.2; 02797 if( dist_tol_sqr < GEOMETRY_RESABS*GEOMETRY_RESABS ) 02798 dist_tol_sqr = GEOMETRY_RESABS*GEOMETRY_RESABS; 02799 02800 // Check if we are within GEOMETRY_RESABS of a vertex of the 02801 // triangle or if one of the triangle vertices can be moved 02802 // to the input location. 02803 int closest_pt = -1; 02804 double closest_dist = dist_tol_sqr; 02805 for ( i = 0; i < 3; i++ ) { 02806 double dist_sqr = d[i].length_squared(); 02807 bool has_owner = (0 != TDVGFacetOwner::get(facet->point(i))); 02808 if( !has_owner && dist_sqr < closest_dist ) { 02809 pt_edges.clean_out(); 02810 facet->point(i)->edges( pt_edges); 02811 while( pt_edges.size() ) 02812 if ( TDVGFacetOwner::get(pt_edges.pop()) ) 02813 has_owner = true; 02814 } 02815 02816 if ( (!has_owner && dist_sqr < closest_dist) || 02817 dist_sqr < GEOMETRY_RESABS*GEOMETRY_RESABS ) { 02818 closest_pt = i; 02819 closest_dist = dist_sqr; 02820 } 02821 } 02822 02823 if( closest_pt >= 0 ) 02824 { 02825 facet->point(closest_pt)->set(pos); 02826 return dynamic_cast<CubitPointData*>(facet->point(closest_pt)); 02827 } 02828 02829 // Check if the input position is within GEOMETRY_RESABS of one 02830 // of the triangle edges or if the edge can be 'bent' such that 02831 // the split point is the input position. 02832 int closest_edge = -1; 02833 for ( i = 0; i < 3; i++ ) { 02834 double t = (v[i] % d[i]) / v[i].length_squared(); 02835 double dist_sqr = (d[i] - t * v[i]).length_squared(); 02836 CubitFacetEdge* edge = facet->point(i)->shared_edge(facet->point((i+1)%3)); 02837 02838 bool has_owner = edge && TDVGFacetOwner::get(edge); 02839 02840 if( (!has_owner && dist_sqr < closest_dist) || 02841 dist_sqr < GEOMETRY_RESABS*GEOMETRY_RESABS ) 02842 { 02843 CubitFacet* other_facet = 0; 02844 for ( int j = 0; j < edge->num_adj_facets(); j++ ) 02845 { 02846 if (edge->adj_facet(j) != facet && 02847 TDVGFacetOwner::get(edge->adj_facet(j)) == surface) 02848 { 02849 other_facet = edge->adj_facet(j); 02850 break; 02851 } 02852 } 02853 02854 if (other_facet) 02855 { 02856 // check if splitting the edge will invert some other facet 02857 int edge_index = other_facet->edge_index( edge ); 02858 CubitVector other_pt = other_facet->point(edge_index)->coordinates(); 02859 CubitVector prev_pt = other_facet->point((edge_index+1)%3)->coordinates(); 02860 CubitVector next_pt = other_facet->point((edge_index+2)%3)->coordinates(); 02861 prev_pt -= other_pt; 02862 next_pt -= other_pt; 02863 CubitVector norm = prev_pt * next_pt; 02864 CubitVector new_e = pos - other_pt; 02865 02866 if ( norm.vector_angle_quick(prev_pt, new_e) > CUBIT_PI || 02867 norm.vector_angle_quick(new_e, next_pt) > CUBIT_PI ) 02868 continue; 02869 02870 // don't create adjacent sliver facets 02871 double prev_t = prev_pt % new_e / prev_pt.length_squared(); 02872 prev_pt *= prev_t; 02873 prev_pt += other_pt; 02874 if ( (prev_pt - pos).length_squared() < dist_sqr ) 02875 continue; 02876 02877 double next_t = next_pt % new_e / next_pt.length_squared(); 02878 next_pt *= next_t; 02879 next_pt += other_pt; 02880 if ( (next_pt - pos).length_squared() < dist_sqr ) 02881 continue; 02882 } 02883 02884 02885 closest_dist = dist_sqr; 02886 closest_edge = i; 02887 } 02888 } 02889 02890 if( closest_edge >= 0 ) 02891 { 02892 CubitPoint* pt1 = facet->point(closest_edge); 02893 CubitPoint* pt2 = facet->point((closest_edge+1)%3); 02894 CubitFacetEdge* edge = pt1->shared_edge(pt2); 02895 CubitFacetEdge* new_edge; 02896 CubitFacet* new_facet; 02897 CubitPoint* new_point; 02898 PartSurfFacetTool::split_edge(edge, pos, 0, new_point, new_edge, new_facet ); 02899 if (dynamic_cast<SubSurface*>(surface)) 02900 surface->relax_to_geometry( new_point, &position ); 02901 return dynamic_cast<CubitPointData*>(new_point); 02902 } 02903 02904 CubitFacet *new_tri1 = 0, *new_tri2 = 0; 02905 CubitPoint* pt1 = facet->point(0); 02906 CubitPoint* pt2 = facet->point(1); 02907 CubitPoint* pt3 = facet->point(2); 02908 CubitPoint* new_pt = facet->insert_point( pos, new_tri1, new_tri2 ); 02909 new CubitFacetEdgeData( new_pt, pt1 ); 02910 new CubitFacetEdgeData( new_pt, pt2 ); 02911 new CubitFacetEdgeData( new_pt, pt3 ); 02912 surface->notify_split( facet, new_tri1 ); 02913 surface->notify_split( facet, new_tri2 ); 02914 02915 if (dynamic_cast<SubSurface*>(surface)) 02916 surface->relax_to_geometry( new_pt, &position ); 02917 02918 return dynamic_cast<CubitPointData*>(new_pt); 02919 } 02920 02921 void PartitionEngine::delete_facet( CubitFacet* p_dead ) 02922 { 02923 assert(!TDVGFacetOwner::get(p_dead)); 02924 assert(dynamic_cast<CubitFacetData*>(p_dead) != NULL); 02925 02926 CubitFacetEdge* edges[3] = {p_dead->edge(0), p_dead->edge(1), p_dead->edge(2)}; 02927 CubitPoint* pts[3] = {p_dead->point(0), p_dead->point(1), p_dead->point(2)}; 02928 02929 int k; 02930 for( k = 0; k < 3; k++ ) 02931 { 02932 if( pts[k] ) 02933 { 02934 pts[k]->remove_facet( p_dead ); 02935 CubitFacetData *facet_data = static_cast<CubitFacetData*>(p_dead); 02936 facet_data->set_point( NULL, k); 02937 02938 if( !pts[k]->num_adj_facets() ) 02939 delete pts[k]; 02940 } 02941 } 02942 02943 for( k = 0; k < 3; k++ ) 02944 { 02945 if( edges[k] ) 02946 { 02947 edges[k]->remove_facet(p_dead); 02948 p_dead->edge(NULL, k); 02949 if(!edges[k]->num_adj_facets()) 02950 delete edges[k]; 02951 } 02952 } 02953 02954 delete p_dead; 02955 } 02956 02957 //------------------------------------------------------------------------- 02958 // Purpose : Create projection of a polyline in surface facetting. 02959 // 02960 // Special Notes : 02961 // 02962 // Creator : Jason Kraftcheck 02963 // 02964 // Creation Date : 02/23/03 02965 //------------------------------------------------------------------------- 02966 CubitStatus PartitionEngine::project_to_surface( 02967 DLIList<CubitFacetData*>& cubit_facets, 02968 DLIList<CubitVector*>& polyline, 02969 DLIList<CubitFacetEdgeData*>& polyline_out, 02970 DLIList<CubitPointData*>& polyline_points, 02971 const double *tolerance_length) 02972 { 02973 int i, j; 02974 unsigned u; 02975 PartitionSurface* p_adj_surf; 02976 PartitionCurve* p_curve = 0; 02977 PartitionEntity* p_owner; 02978 02979 DLIList<PartitionSurface*> surfaces; 02980 for (i = cubit_facets.size(); i--; ) 02981 surfaces.append_unique( dynamic_cast<PartitionSurface*>(TDVGFacetOwner::get(cubit_facets.step_and_get()))); 02982 02983 // get points 02984 02985 DLIList<CubitPoint*> cubit_points(cubit_facets.size() * 3); 02986 DLIList<CubitFacet*> orig_facets; 02987 CAST_LIST_TO_PARENT(cubit_facets, orig_facets); 02988 FacetDataUtil::get_facet_points(orig_facets, cubit_points); 02989 02990 // get bounding curves from the facets 02991 std::set<PartitionCurve*> boundary_curves; 02992 DLIList<CubitFacetEdge*> free_edges; 02993 FacetDataUtil::edges_by_count(orig_facets, 1, free_edges); 02994 free_edges.reset(); 02995 for (i=free_edges.size(); i>0; i--) 02996 { 02997 p_owner = TDVGFacetOwner::get(free_edges.get_and_step()); 02998 p_curve = CAST_TO(p_owner, PartitionCurve); 02999 assert(!!p_curve); // every bounding edge should be owned by a curve 03000 boundary_curves.insert(p_curve); 03001 } 03002 03003 std::vector<double> facet_points(cubit_points.size() * 3); 03004 std::vector<int> simple_facets(cubit_facets.size() * 3); 03005 cubit_points.reset(); 03006 for ( i = 0; i < cubit_points.size(); i++ ) 03007 { 03008 CubitPoint* pt = cubit_points.get_and_step(); 03009 pt->marked( i ); 03010 03011 int j = i * 3; 03012 facet_points[j ] = pt->coordinates().x(); 03013 facet_points[j+1] = pt->coordinates().y(); 03014 facet_points[j+2] = pt->coordinates().z(); 03015 if (DEBUG_FLAG(145)) 03016 { 03017 GfxDebug::draw_point(pt->coordinates(), CUBIT_WHITE_INDEX); 03018 GfxDebug::draw_label(i, (float)(pt->coordinates().x()), 03019 (float)(pt->coordinates().y()), 03020 (float)(pt->coordinates().z()), 03021 CUBIT_WHITE_INDEX); 03022 } 03023 } 03024 03025 cubit_facets.reset(); 03026 for ( i = 0; i < cubit_facets.size(); i++ ) 03027 { 03028 CubitFacetData* facet = cubit_facets.get_and_step(); 03029 int j = i * 3; 03030 simple_facets[j ] = facet->point(0)->marked(); 03031 simple_facets[j+1] = facet->point(1)->marked(); 03032 simple_facets[j+2] = facet->point(2)->marked(); 03033 if (DEBUG_FLAG(145)) 03034 { 03035 GfxDebug::draw_facet( facet, CUBIT_CYAN_INDEX ); 03036 CubitVector c = facet->center(); 03037 GfxDebug::draw_label( i, (float)(c.x()), 03038 (float)(c.y()), 03039 (float)(c.z()), 03040 CUBIT_CYAN_INDEX); 03041 PRINT_DEBUG_145("%2d : %2d %2d %2d\n", i, 03042 facet->point(0)->marked(), 03043 facet->point(1)->marked(), 03044 facet->point(2)->marked()); 03045 } 03046 } 03047 03048 // clear point marks 03049 for ( i = 0; i < cubit_points.size(); i++ ) 03050 cubit_points.step_and_get()->marked(0); 03051 /* 03052 // reduce polyline resolution 03053 const double dist_tol = GEOMETRY_RESABS*GEOMETRY_RESABS; 03054 const double COS15 = 0.96592582628906831; 03055 const double angle_tol = COS15*COS15; 03056 DLIList<CubitVector*> polyline2; 03057 polyline.reset(); 03058 CubitVector *prev = polyline.get_and_step(); 03059 polyline2.append(prev); 03060 for( i = polyline.size() - 2; i--; ) 03061 { 03062 CubitVector *pt = polyline.get_and_step(); 03063 CubitVector *next = polyline.get(); 03064 CubitVector v1(*pt - *prev); 03065 CubitVector v2(*next - *pt); 03066 double len1 = v1.length_squared(); 03067 double len2 = v2.length_squared(); 03068 double dot = v1 % v2; 03069 if( len1 > dist_tol && len2 > dist_tol && 03070 ((dot*dot)/(len1*len2)) < angle_tol ) 03071 { 03072 polyline2.append(pt); 03073 prev = pt; 03074 } 03075 } 03076 polyline2.append(polyline.get()); 03077 */ 03078 // Call tool to do projection 03079 03080 std::vector<double> new_facet_points; 03081 std::vector<int> dead_simple_facets, new_simple_facets, 03082 facet_replacement, new_polyline, seg_pts; 03083 FacetProjectTool tool; 03084 if ( !tool.project( polyline, facet_points, simple_facets, 03085 dead_simple_facets, new_simple_facets, 03086 facet_replacement, new_facet_points, 03087 new_polyline, seg_pts, tolerance_length ) ) 03088 { 03089 // output the map between input polyline positions and 03090 // facet points 03091 std::vector<int>::iterator iitor; 03092 for ( iitor = seg_pts.begin(); iitor != seg_pts.end(); ++iitor ) 03093 { 03094 int pt_index = *iitor; 03095 if ( pt_index == -1 ) 03096 { 03097 polyline_points.append(NULL); 03098 } 03099 else 03100 { 03101 CubitPointData* ptd = NULL; 03102 if(pt_index >= 0 && pt_index < cubit_points.size()) 03103 { 03104 CubitPoint* pt = cubit_points.next( pt_index ); 03105 ptd = dynamic_cast<CubitPointData*>(pt); 03106 } 03107 polyline_points.append(ptd); 03108 } 03109 } 03110 03111 return CUBIT_FAILURE; 03112 } 03113 03114 // Convert back to CubitFacet rep 03115 03116 // make new points 03117 assert( new_facet_points.size() % 3 == 0 ); 03118 std::vector<CubitPointData*> new_cubit_points(new_facet_points.size()/3); 03119 std::vector<CubitPointData*>::iterator cpitor = new_cubit_points.begin(); 03120 std::vector<double>::iterator ditor = new_facet_points.begin(); 03121 for ( ; cpitor != new_cubit_points.end(); ++cpitor ) 03122 { 03123 double x = *ditor++; 03124 double y = *ditor++; 03125 double z = *ditor++; 03126 *cpitor = new CubitPointData(x,y,z); 03127 cubit_points.append(*cpitor); 03128 } 03129 03130 // make new facets 03131 cubit_facets.reset(); 03132 cubit_points.reset(); 03133 int prev_index = 0; 03134 assert( new_simple_facets.size() % 3 == 0 ); 03135 03136 std::vector<CubitFacetData*> facet_list; 03137 std::vector<CubitFacetData*>::iterator fitor; 03138 std::vector<int>::iterator iitor = new_simple_facets.begin(); 03139 03140 int id=0; // dummy for CubitFacetData constructor 03141 03142 for( u = 0; u < dead_simple_facets.size(); u++ ) 03143 { 03144 // get number of replacement facets 03145 int index = facet_replacement[u]; 03146 int count = (index - prev_index) / 3; 03147 assert(((index - prev_index) % 3) == 0); 03148 03149 // make a new list to hold data 03150 facet_list.clear(); 03151 facet_list.resize(count+1); 03152 fitor = facet_list.begin(); 03153 03154 // put dead facet at beginning of list 03155 CubitFacetData* p_dead = cubit_facets.next(dead_simple_facets[u]); 03156 *fitor++ = p_dead; 03157 03158 // get the surface that owns the dead facet 03159 p_owner = TDVGFacetOwner::get(p_dead); 03160 PartitionSurface* p_dead_surf = CAST_TO(p_owner, PartitionSurface); 03161 assert(!!p_dead_surf); 03162 03163 // construct and append replacement facets 03164 for ( j=0; j < count; j++ ) 03165 { 03166 CubitPoint* pt1 = cubit_points.next( *iitor++ ); 03167 CubitPoint* pt2 = cubit_points.next( *iitor++ ); 03168 CubitPoint* pt3 = cubit_points.next( *iitor++ ); 03169 *fitor++ = new CubitFacetData(pt1, pt2, pt3, &id); 03170 } 03171 03172 // set up for next iteration 03173 assert(fitor == facet_list.end()); 03174 prev_index = index; 03175 03176 // do something with "facet_list" 03177 03178 DLIList<CubitFacetData*> old_facet_list; 03179 03180 // fill edge replacement lists 03181 std::vector<CubitFacetEdgeData*> edge_lists[3]; 03182 get_edge_replacements(facet_list, edge_lists); 03183 03184 // update edges/facets on curves and adjacent surfaces 03185 CubitFacetEdgeData* old_edge; 03186 for (j=0; j<3; j++) 03187 { 03188 DLIList<CubitFacetEdgeData*> new_edges; 03189 if (edge_lists[j].size()) // check for replacements 03190 { 03191 std::vector<CubitFacetEdgeData*>::iterator eitor = edge_lists[j].begin(); 03192 old_edge = *eitor++; 03193 03194 p_owner = TDVGFacetOwner::get(old_edge); 03195 p_curve = CAST_TO(p_owner, PartitionCurve); 03196 03197 for (; eitor != edge_lists[j].end(); eitor++) 03198 new_edges.append(*eitor); 03199 03200 assert(new_edges.size() > 1); // shouldn't ever get 1 to 1 replacement here 03201 03202 // split facets on adjacent surfaces if the split crosses a curve 03203 // on the outside boundary of the facets 03204 if (boundary_curves.find(p_curve) != boundary_curves.end()) 03205 { 03206 // get facets to be replaced on adjacent surf 03207 DLIList<CubitFacetData*> adj_facets; 03208 DLIList<CubitFacet*> tmp_list; 03209 old_edge->facets(tmp_list); 03210 CAST_LIST(tmp_list, adj_facets, CubitFacetData); 03211 03212 if (adj_facets.size() > 1) 03213 { 03214 DLIList<CubitFacetData*> adj_replacements; 03215 int i_adj; 03216 for (i_adj=adj_facets.size(); i_adj>0; i_adj--) 03217 { 03218 CubitFacetData* p_adjacent = adj_facets.get_and_step(); 03219 if (p_adjacent == p_dead) 03220 continue; 03221 03222 // create replacement facets 03223 adj_replacements.clean_out(); 03224 03225 // get the point opposite the edge being replaced 03226 int e_index = p_adjacent->edge_index(old_edge); 03227 bool old_reversed = -1 == p_adjacent->edge_use(e_index); 03228 CubitPoint* prev_pt = NULL; 03229 //if old_reversed is false, the new_edge' reversed flag is true 03230 int old_prev_pt_index; 03231 if (old_reversed) 03232 { 03233 prev_pt = old_edge->point(0); 03234 old_prev_pt_index = 0; 03235 } 03236 else 03237 { 03238 prev_pt = old_edge->point(1); 03239 old_prev_pt_index = 1; 03240 } 03241 CubitPoint* opposite_pt = p_adjacent->point(e_index); 03242 //CubitPoint* opposite_pt = p_adjacent->point(p_adjacent->edge_index(old_edge)); // opposite edge and point have same index 03243 new_edges.reset(); 03244 int i_new; 03245 for (i_new=new_edges.size(); i_new>0; i_new--) 03246 { 03247 CubitFacetEdge* p_edge = new_edges.get_and_step(); 03248 03249 prev_pt = p_edge->other_point(prev_pt); 03250 assert(!!prev_pt); 03251 bool new_reversed = p_edge->point(old_prev_pt_index) == prev_pt; 03252 int reversed = (int)(new_reversed != old_reversed); 03253 03254 CubitFacetData* p_facet = new CubitFacetData(p_edge->point(reversed), 03255 p_edge->point(1-reversed), 03256 opposite_pt, &id); 03257 adj_replacements.append(p_facet); 03258 } 03259 03260 p_owner = TDVGFacetOwner::get(p_adjacent); 03261 p_adj_surf = CAST_TO(p_owner, PartitionSurface); 03262 assert(!!p_adj_surf); 03263 old_facet_list.clean_out(); 03264 old_facet_list.append(p_adjacent); 03265 p_adj_surf->replace_facets(old_facet_list, adj_replacements); 03266 delete_facet( p_adjacent ); 03267 } 03268 } 03269 } 03270 03271 // replace the curve edges 03272 p_curve->replace_facet(old_edge, new_edges); 03273 03274 // Don't delete edge yet. It's still connected to 03275 // at least one facet. Wait 'till the facet is deleted. 03276 //delete old_edge; 03277 } 03278 } 03279 03280 // replace dead facet 03281 fitor = facet_list.begin(); 03282 fitor++; // skip dead facet 03283 DLIList<CubitFacetData*> new_facets; 03284 for (; fitor != facet_list.end(); fitor++) 03285 new_facets.append(*fitor); 03286 old_facet_list.clean_out(); 03287 old_facet_list.append(p_dead); 03288 p_dead_surf->replace_facets(old_facet_list, new_facets); 03289 delete_facet(p_dead); 03290 } 03291 03292 assert(iitor == new_simple_facets.end()); 03293 03294 // output the edges that make up the projected curve 03295 cubit_points.reset(); 03296 iitor = new_polyline.begin(); 03297 while( *iitor ) 03298 { 03299 int count = *iitor++; 03300 CubitPoint* prev_point = cubit_points.next( *iitor++ ); 03301 for ( i = 1; i < count; i++ ) { 03302 CubitPoint* pt = cubit_points.next( *iitor++ ); 03303 CubitFacetEdge* edge = prev_point->shared_edge(pt); 03304 CubitFacetEdgeData* edge_d = dynamic_cast<CubitFacetEdgeData*>(edge); 03305 assert(!!edge_d); 03306 if (TDVGFacetOwner::get(edge_d)) 03307 polyline_out.append(0); 03308 else 03309 { 03310 if (edge_d->point(0) == pt) 03311 edge_d->flip(); 03312 polyline_out.append(edge_d); 03313 } 03314 prev_point = pt; 03315 } 03316 polyline_out.append(0); 03317 } 03318 03319 // output the map between input polyline positions and 03320 // facet points 03321 for ( iitor = seg_pts.begin(); iitor != seg_pts.end(); ++iitor ) 03322 { 03323 int pt_index = *iitor; 03324 if ( pt_index == -1 ) 03325 { 03326 polyline_points.append(NULL); 03327 } 03328 else 03329 { 03330 assert(pt_index >= 0 && pt_index < cubit_points.size()); 03331 CubitPoint* pt = cubit_points.next( pt_index ); 03332 CubitPointData* ptd = dynamic_cast<CubitPointData*>(pt); 03333 assert(!!ptd); 03334 polyline_points.append(ptd); 03335 } 03336 } 03337 03338 03339 return CUBIT_SUCCESS; 03340 } 03341 03342 //------------------------------------------------------------------------- 03343 // Purpose : Create a point-curve 03344 // 03345 // Special Notes : 03346 // 03347 // Creator : Jason Kraftcheck 03348 // 03349 // Creation Date : 02/23/03 03350 //------------------------------------------------------------------------- 03351 TBPoint* PartitionEngine::insert_point_curve( Surface* surf, 03352 const CubitVector& position, 03353 Surface *&partitioned_surf ) 03354 { 03355 if ( CompositeSurface* csurf = dynamic_cast<CompositeSurface*>(surf) ) 03356 { 03357 TBPoint* result = 03358 CompositeEngine::instance().insert_point_curve(csurf, position); 03359 partitioned_surf = csurf; 03360 return result; 03361 } 03362 03363 bool replaced_surface = false; 03364 PartitionSurface* psurf = dynamic_cast<PartitionSurface*>(surf); 03365 if ( ! psurf ) { 03366 psurf = replace_surface(surf); 03367 replaced_surface = true; 03368 if ( ! psurf ) return 0; 03369 } 03370 03371 CubitPointData* facet_point = project_to_surface( psurf, position ); 03372 if ( !facet_point ) { 03373 if( replaced_surface ) 03374 restore_surface( dynamic_cast<SubSurface*>(psurf) ); 03375 partitioned_surf = NULL; 03376 return 0; 03377 } 03378 03379 PartitionPoint* result = insert_point_curve( psurf, facet_point ); 03380 if ( !result ) { 03381 if( replaced_surface ) 03382 restore_surface( dynamic_cast<SubSurface*>(psurf) ); 03383 return 0; 03384 } 03385 03386 PartitionCurve* curve = result->next_curve(0); 03387 if (replaced_surface && !dynamic_cast<PartPTCurve*>(curve)) 03388 { 03389 TBPoint* real = result->real_point(); 03390 partitioned_surf = restore_surface( dynamic_cast<SubSurface*>(psurf) ); 03391 if (real) 03392 { 03393 result = dynamic_cast<PartitionPoint*>(real->owner()); 03394 return result ? result : real; 03395 } 03396 } 03397 else 03398 partitioned_surf = psurf; 03399 03400 return result; 03401 } 03402 03403 03404 03405 //------------------------------------------------------------------------- 03406 // Purpose : Create point-curve 03407 // 03408 // Special Notes : 03409 // 03410 // Creator : Jason Kraftcheck 03411 // 03412 // Creation Date : 02/23/03 03413 //------------------------------------------------------------------------- 03414 PartitionPoint* PartitionEngine::insert_point_curve( PartitionSurface* surf, 03415 CubitPointData* point ) 03416 { 03417 // If imprint at existing vertex, just return that vertex 03418 if ( TDVGFacetOwner::get(point) ) 03419 return dynamic_cast<PartitionPoint*>(TDVGFacetOwner::get(point)); 03420 03421 // Check if imprint point is on a curve of the surface 03422 DLIList<CubitFacetEdge*> edges; 03423 point->edges(edges); 03424 PartitionEntity* owner = 0; 03425 int owner_count = 0; 03426 int owner_edges = 0; 03427 while (edges.size()) 03428 { 03429 if (PartitionEntity* ent = TDVGFacetOwner::get(edges.pop())) 03430 { 03431 if (owner != ent) 03432 owner_count++; 03433 owner = ent; 03434 owner_edges++; 03435 } 03436 } 03437 03438 // If imprint is on curve, split the curve 03439 if (owner) 03440 { 03441 PartitionCurve* curve = dynamic_cast<PartitionCurve*>(owner); 03442 03443 // check valid facet configuration. should be only one 03444 // owner, and owner should own exactly two of the adjacent 03445 // edges. And owner should be a partition curve. 03446 if (!curve || owner_count != 1 || owner_edges != 2) 03447 { 03448 PRINT_ERROR("Internal error at %s:%d\n Invalid state.\n", __FILE__, __LINE__ ); 03449 assert(0); 03450 return NULL; 03451 } 03452 03453 PartitionPoint* new_point = new PartitionPoint(point->coordinates(), curve); 03454 new_point->facet_point(point); 03455 curve = insert_point( curve, new_point ); 03456 if (!curve) 03457 { 03458 delete new_point; 03459 return 0; 03460 } 03461 03462 return new_point; 03463 } 03464 03465 // If here, point is in surface interior. Create point-curve. 03466 PartitionPoint* new_point = new PartitionPoint( point->coordinates(), surf ); 03467 new_point->facet_point(point); 03468 PartPTCurve* new_curve = new PartPTCurve( surf ); 03469 new_curve->start_point( new_point ); 03470 new_curve->end_point( new_point ); 03471 03472 insert_point_curve( surf, new_curve ); 03473 03474 return new_point; 03475 } 03476 03477 CubitStatus PartitionEngine::insert_point_curve( PartitionSurface* surf, 03478 PartPTCurve* new_curve, 03479 bool update_topology ) 03480 { 03481 PartitionCoEdge* new_coedge = new PartitionCoEdge( surf, CUBIT_FORWARD ); 03482 new_curve->add( new_coedge ); 03483 PartitionLoop* new_loop = new PartitionLoop(); 03484 new_loop->insert_after( new_coedge, 0 ); 03485 03486 surf->add( new_loop ); 03487 if ( surf->owner() && update_topology ) 03488 surf->owner()->notify_topology_modified(surf); 03489 return CUBIT_SUCCESS; 03490 } 03491 03492 03493 03494 //------------------------------------------------------------------------- 03495 // Purpose : Construct surface for volume partitioning 03496 // 03497 // Special Notes : 03498 // 03499 // Creator : Jason Kraftcheck 03500 // 03501 // Creation Date : 01/13/03 03502 //------------------------------------------------------------------------- 03503 Lump* PartitionEngine::insert_surface( Surface* surface, Lump* lump) 03504 { 03505 GMem gmem; 03506 int i; 03507 CubitStatus status = surface->get_geometry_query_engine()-> 03508 get_graphics( surface, &gmem ); 03509 03510 if( !status ) 03511 { 03512 PRINT_ERROR("PartitionEngine::insert_surface: GeometryEngine::" 03513 "get_graphics failed for surface.\n"); 03514 return 0; 03515 } 03516 03517 int num_pts = gmem.pointListCount; 03518 03519 CubitPointData** ptarray = new CubitPointData*[num_pts]; 03520 GPoint *p_itor = gmem.point_list(); 03521 GPoint *p_end = p_itor + num_pts; 03522 CubitPointData** array_itor = ptarray; 03523 for( ; p_itor < p_end; p_itor++, array_itor++ ) 03524 *array_itor = new CubitPointData(CubitVector(p_itor->x,p_itor->y,p_itor->z)); 03525 03526 DLIList<CubitFacetData*> facets; 03527 int* f_itor = gmem.facet_list(); 03528 int* f_end = f_itor + gmem.fListCount; 03529 i = 0; 03530 for( ; f_itor < f_end ; f_itor += (1 + *f_itor) ) 03531 { 03532 if( *f_itor != 3 ) 03533 PRINT_ERROR("Non-triangular facet in PartitionEngine::insert_surface\n"); 03534 else 03535 facets.append( new CubitFacetData(ptarray[f_itor[1]], 03536 ptarray[f_itor[2]], 03537 ptarray[f_itor[3]], &i) ); 03538 } 03539 03540 // clean up any unused points 03541 for( i = 0; i < num_pts; i++ ) 03542 if( ptarray[i]->num_adj_facets() == 0 ) 03543 delete ptarray[i]; 03544 delete [] ptarray; 03545 03546 03547 // create partition lump 03548 bool created_lump = false; 03549 PartitionLump* partlump = dynamic_cast<PartitionLump*>(lump); 03550 if( !partlump ) 03551 { 03552 created_lump = true; 03553 partlump = replace_lump(lump); 03554 assert(partlump != NULL); 03555 } 03556 03557 // Get vertex locations 03558 DLIList<CubitVector> coords; 03559 DLIList<TopologyBridge*> loops, coedges, curves, points, all_points; 03560 surface->get_children_virt(loops); 03561 while( loops.size() ) 03562 { 03563 loops.pop()->get_children( coedges, true, layer() - 1 ); 03564 while ( coedges.size() ) 03565 { 03566 coedges.pop()->get_children_virt(curves); 03567 assert(curves.size() == 1); 03568 TopologyBridge* curve = curves.pop(); 03569 curve->get_children( points, true, layer() - 1 ); 03570 assert ( points.size() < 3 ); 03571 all_points.merge_unique( points ); 03572 points.clean_out(); 03573 } 03574 } 03575 while( all_points.size() ) 03576 coords.append(CubitVector( dynamic_cast<TBPoint*>(all_points.pop())->coordinates() ) ); 03577 03578 PartitionLumpImprint tool( partlump ); 03579 DLIList<PartitionEntity*> new_entities; 03580 PartitionSurface* new_surf = tool.imprint( facets, coords, new_entities ); 03581 if ( !new_surf ) 03582 { 03583 if( created_lump ) restore_lump(partlump); 03584 return 0; 03585 } 03586 03587 PartitionLump* result = insert_surface( partlump, new_surf ); 03588 if( !result ) 03589 { 03590 destroy_surface( new_surf ); 03591 if( created_lump ) restore_lump( partlump ); 03592 return 0; 03593 } 03594 03595 return result; 03596 } 03597 03598 Surface* PartitionEngine::insert_surface( DLIList<CubitFacet*>& facets, Lump* lump) 03599 { 03600 03601 // create partition lump and surface 03602 bool created_lump = false; 03603 PartitionLump* partlump = dynamic_cast<PartitionLump*>(lump); 03604 if( !partlump ) 03605 { 03606 created_lump = true; 03607 partlump = replace_lump(lump); 03608 if (!partlump) 03609 return 0; 03610 } 03611 03612 PartitionLumpImprint tool( partlump ); 03613 DLIList<PartitionEntity*> new_list; 03614 PartitionSurface* new_surf = tool.imprint( facets, new_list ); 03615 if ( !new_surf ) 03616 { 03617 if( created_lump ) restore_lump(partlump); 03618 return 0; 03619 } 03620 03621 PartitionLump* result = insert_surface( partlump, new_surf ); 03622 if( !result ) 03623 { 03624 destroy_surface( new_surf ); 03625 if( created_lump ) restore_lump( partlump ); 03626 return 0; 03627 } 03628 03629 return new_surf; 03630 } 03631 03632 03633 03634 //------------------------------------------------------------------------- 03635 // Purpose : Insert a surface into a volume 03636 // 03637 // Special Notes : 03638 // 03639 // Creator : Jason Kraftcheck 03640 // 03641 // Creation Date : 01/12/03 03642 //------------------------------------------------------------------------- 03643 PartitionLump* PartitionEngine::insert_surface( PartitionLump* lump, 03644 PartitionSurface* surface ) 03645 { 03646 assert( &(lump->sub_entity_set()) == &(surface->sub_entity_set()) ); 03647 03648 // Find all affected shells. If any curve is not part of an 03649 // existing shell in the volume, set all_curves_connected to 03650 // false. If any curve does not intersect the volume, then 03651 // the volume does not need to be split into two (or the surface 03652 // forms a new void in the volume.) 03653 bool all_curves_connected = true; 03654 DLIList<PartitionShell*> modified_list; 03655 PartitionLoop* loop = 0; 03656 PartitionCoEdge *coedge, *curve_coedge; 03657 PartitionCurve* curve; 03658 PartitionShell* shell; 03659 PartitionCoSurf* cosurf; 03660 while( (loop = surface->next_loop(loop)) ) 03661 { 03662 coedge = loop->first_coedge(); 03663 do { 03664 curve = coedge->get_curve(); 03665 curve_coedge = 0; 03666 shell = 0; 03667 while( (curve_coedge = curve->next_coedge(curve_coedge)) ) 03668 { 03669 PartitionSurface* surf = curve_coedge->get_loop()->get_surface(); 03670 cosurf = 0; 03671 while( (cosurf = surf->next_co_surface( cosurf )) ) 03672 { 03673 if( cosurf->get_shell()->get_lump() == lump ) 03674 { 03675 assert( !shell || cosurf->get_shell() == shell ); 03676 shell = cosurf->get_shell(); 03677 } 03678 } 03679 } 03680 03681 if( shell ) 03682 modified_list.append_unique(shell); 03683 else 03684 all_curves_connected = false; 03685 03686 coedge = loop->next_coedge(coedge); 03687 } while( coedge != loop->first_coedge() ); 03688 } 03689 03690 // Construct CoSurfaces 03691 PartitionCoSurf* cosurf1 = new PartitionCoSurf(CUBIT_FORWARD); 03692 PartitionCoSurf* cosurf2 = new PartitionCoSurf(CUBIT_REVERSED); 03693 surface->add(cosurf1); 03694 surface->add(cosurf2); 03695 03696 // If there were no affected shells, we need to make a new 03697 // shell for a possible void in the volume. 03698 PartitionShell* shell_to_split = 0; 03699 if( modified_list.size() == 0 ) 03700 { 03701 shell_to_split = new PartitionShell(); 03702 lump->add(shell_to_split); 03703 03704 // If surface is closed, set all_curves_connected 03705 // to true to indicate that volume needs to be split. 03706 // (Creating a one-surface void in the volume.) 03707 loop = 0; 03708 all_curves_connected = true; 03709 while( (loop = surface->next_loop(loop)) ) 03710 { 03711 coedge = loop->first_coedge(); 03712 do 03713 { 03714 curve = coedge->get_curve(); 03715 curve_coedge = 0; 03716 int coedge_count = 0; 03717 while( (curve_coedge = curve->next_coedge(curve_coedge)) ) 03718 { 03719 if( curve_coedge->get_loop() == loop ) 03720 coedge_count++; 03721 else 03722 assert(curve_coedge->get_loop()->get_surface() != surface); 03723 } 03724 03725 if( coedge_count == 1 ) 03726 all_curves_connected = false; 03727 else 03728 assert(coedge_count == 2); 03729 03730 coedge = loop->next_coedge(coedge); 03731 } while( coedge != loop->first_coedge() ); 03732 } 03733 } 03734 03735 // Otherwise combine all the affected shells 03736 else 03737 { 03738 modified_list.reverse(); 03739 shell_to_split = modified_list.pop(); 03740 while( modified_list.size() ) 03741 { 03742 shell = modified_list.pop(); 03743 while( PartitionCoSurf* cosurf = shell->next_co_surface() ) 03744 { 03745 shell->remove(cosurf); 03746 shell_to_split->add(cosurf); 03747 } 03748 lump->remove(shell); 03749 delete shell; 03750 } 03751 } 03752 03753 shell_to_split->add(cosurf1); 03754 shell_to_split->add(cosurf2); 03755 03756 // If we don't need to split the volume, we are done 03757 if( !all_curves_connected ) 03758 return lump; 03759 // We probably need to split the the lump... 03760 else 03761 return split_lump( shell_to_split ); 03762 } 03763 03764 //------------------------------------------------------------------------- 03765 // Purpose : Test if a PartitionShell needs to be split, and 03766 // if so partition the shell and owning lump 03767 // 03768 // Special Notes : 03769 // 03770 // Creator : Jason Kraftcheck 03771 // 03772 // Creation Date : 01/13/03 03773 //------------------------------------------------------------------------- 03774 PartitionLump* PartitionEngine::split_lump( PartitionShell* shell_to_split ) 03775 { 03776 // Split shell 03777 PartitionShell* new_shell = split_shell(shell_to_split); 03778 if( !new_shell ) 03779 { 03780 // shell did not need to be split 03781 return shell_to_split->get_lump(); 03782 } 03783 03784 // Create the new lump and shell 03785 PartitionLump* new_lump = new PartitionLump( shell_to_split->get_lump() ); 03786 new_lump->add( new_shell ); 03787 03788 // Check for any remaining shells that need to be moved 03789 // from the old lump to the new lump. 03790 PartitionShell* shell = 0; 03791 PartitionLump* lump = shell_to_split->get_lump(); 03792 while( (shell = lump->next_shell(shell)) ) 03793 { 03794 if( shell == shell_to_split ) 03795 continue; 03796 03797 bool some_contained = false; 03798 bool all_contained = true; 03799 bool all_tested = true; 03800 PartitionCoSurf* cosurf = 0; 03801 while( (cosurf = shell->next_co_surface(cosurf)) ) 03802 { 03803 PartitionSurface* surf = cosurf->get_surface(); 03804 CubitVector pt, tmp = surf->bounding_box().center(); 03805 surf->closest_point_trimmed( tmp, pt ); 03806 switch( new_shell->point_containment(pt) ) 03807 { 03808 case CUBIT_PNT_INSIDE: 03809 some_contained = true; 03810 break; 03811 case CUBIT_PNT_OUTSIDE: 03812 all_contained = false; 03813 break; 03814 default: 03815 all_tested = false; 03816 break; 03817 } 03818 } 03819 03820 03821 if( !all_tested || (some_contained && !all_contained) ) 03822 { 03823 PRINT_ERROR("Error splitting volume. Could not determine\n" 03824 "which volume shell belongs in. Geometry may be\n" 03825 "invalid.\n"); 03826 } 03827 03828 if(some_contained && all_contained) 03829 { 03830 lump->remove(shell); 03831 new_lump->add(shell); 03832 } 03833 } 03834 03835 return new_lump; 03836 } 03837 03838 /* 03839 #include "GfxDebug.hpp" 03840 static void draw_curve( PartitionCurve* curve, int color, bool flush = true ) 03841 { 03842 GMem graphics; 03843 int i; 03844 curve->get_geometry_query_engine()->get_graphics( curve, i, &graphics ); 03845 GfxDebug::draw_polyline(graphics.point_list(), 03846 graphics.pointListCount, 03847 color); 03848 if(flush) GfxDebug::flush(); 03849 } 03850 03851 static void draw_surface( PartitionSurface* surface, int color, bool flush = true ) 03852 { 03853 // RefEntity* re = dynamic_cast<RefEntity*>(surface->owner()); 03854 // if( re ) 03855 // GfxDebug::draw_ref_entity( re, color, true, false ); 03856 // else 03857 for( PartitionLoop* loop = 0; loop = surface->next_loop(loop); ) 03858 { 03859 PartitionCoEdge* coe = loop->first_coedge(); 03860 do { 03861 draw_curve(coe->get_curve(), color, false); 03862 coe = loop->next_coedge(coe); 03863 } while(coe != loop->first_coedge()); 03864 } 03865 if(flush) GfxDebug::flush(); 03866 } 03867 03868 static void draw_cosurface( PartitionCoSurf* cosurf, int color, bool flush = true ) 03869 { 03870 //draw_surface(cosurf->get_surface(), color, false); 03871 CubitVector p, n; 03872 n = cosurf->get_surface()->bounding_box().center(); 03873 cosurf->get_surface()->closest_point_trimmed( n, p ); 03874 cosurf->get_surface()->closest_point( p, 0, &n ); 03875 double l = cosurf->get_surface()->bounding_box().diagonal().length() * 0.1; 03876 n.length(l); 03877 if(cosurf->sense() == CUBIT_REVERSED) 03878 n *= -1.0; 03879 GfxDebug::draw_vector(p, p+n, color); 03880 if(flush) GfxDebug::flush(); 03881 } 03882 */ 03883 03884 //------------------------------------------------------------------------- 03885 // Purpose : Test if a PartitionShell needs to be split, and 03886 // split it 03887 // 03888 // Special Notes : 03889 // 03890 // Creator : Jason Kraftcheck 03891 // 03892 // Creation Date : 01/13/03 03893 //------------------------------------------------------------------------- 03894 PartitionShell* PartitionEngine::split_shell( PartitionShell* shell_to_split ) 03895 { 03896 // Make sure all cosurface surface marks are cleared 03897 PartitionCoSurf* cosurf = 0; 03898 while( (cosurf = shell_to_split->next_co_surface( cosurf )) ) 03899 { 03900 cosurf->mark = 0; 03901 cosurf->get_surface()->mark = 0; 03902 } 03903 03904 // Identify non-manifold surfaces, marking them either 03905 // with a 2 if they can be used to split the volume 03906 // (if they are part of a connected patch for which the 03907 // bounadary of that patch intersects the volume boundary 03908 // at all curves) or a 3 if they are other non-manifold 03909 // surfaces. This will get a bit tricky if there are 03910 // non-manifold surfaces hanging off of the patch of 03911 // split surfaces. 03912 03913 // First for all non-manifold surfaces, if the surface has 03914 // a curve that is not shared with any other surface, mark 03915 // it with a 3. Otherwise mark it with a 2. 03916 cosurf = 0; 03917 DLIList<PartitionSurface*> surf_stack; 03918 while ( (cosurf = shell_to_split->next_co_surface(cosurf)) ) 03919 { 03920 PartitionSurface* surf = cosurf->get_surface(); 03921 // If we haven't done this surface yet and it is non-manifold 03922 if ( !surf->mark && surf->find_next(cosurf) ) 03923 { 03924 surf->mark = 2; 03925 bool no_free_curve = true; 03926 PartitionLoop* loop = 0; 03927 while( no_free_curve && (loop = surf->next_loop(loop)) ) 03928 { 03929 PartitionCoEdge* coedge = loop->first_coedge(); 03930 do 03931 { 03932 PartitionCurve* curve = coedge->get_curve(); 03933 // If the curve has more than one coedge, it 03934 // is not a free curve (this also accounts for 03935 // the case where the curve is a non-manifold 03936 // curve on the surface interioir -- e.g. a sipe) 03937 if ( !curve->next_coedge(coedge) && 03938 curve->next_coedge(0) == coedge ) 03939 { 03940 no_free_curve = false; 03941 break; 03942 } 03943 coedge = loop->next_coedge(coedge); 03944 } while( coedge != loop->first_coedge() ); 03945 } 03946 03947 if( !no_free_curve ) 03948 { 03949 surf->mark = 3; 03950 surf_stack.append( surf ); 03951 } 03952 } 03953 } 03954 03955 // Now for each surface we marked with a three, traverse 03956 // and mark adjacent surfaces until we come to a curve 03957 // connected to more that two surfaces. 03958 while( surf_stack.size() ) 03959 { 03960 PartitionSurface* surf = surf_stack.pop(); 03961 PartitionLoop* loop = 0; 03962 while ( (loop = surf->next_loop(loop)) ) 03963 { 03964 PartitionCoEdge* coedge = loop->first_coedge(); 03965 do 03966 { 03967 PartitionCurve* curve = coedge->get_curve(); 03968 int split_count = 0; 03969 int boundary_count = 0; 03970 PartitionCoEdge* curve_coe = 0; 03971 while ( (curve_coe = curve->next_coedge(curve_coe) ) != NULL ) 03972 { 03973 PartitionSurface* curve_surf = curve_coe->get_loop()->get_surface(); 03974 switch ( curve_surf->mark ) 03975 { 03976 case 0: boundary_count++; break; 03977 case 2: split_count++; break; 03978 } 03979 } 03980 03981 if ( split_count == 1 && !boundary_count ) 03982 { 03983 curve_coe = 0; 03984 while ( (curve_coe = curve->next_coedge(curve_coe) ) != NULL ) 03985 { 03986 PartitionSurface* curve_surf = curve_coe->get_loop()->get_surface(); 03987 if ( curve_surf->mark == 2 ) 03988 { 03989 curve_surf->mark = 3; 03990 surf_stack.append(curve_surf); 03991 } 03992 } 03993 } 03994 03995 coedge = loop->next_coedge( coedge ); 03996 } while( coedge != loop->first_coedge() ); 03997 } 03998 } 03999 04000 // Now build a new shell by traversing cofaces, marking 04001 // each with that will go in a new shell with a 1. 04002 04003 // Start with any cosurf that does not have a free 04004 // non-manifold surface (marked with a 3). We'll handle 04005 // free non-manifold surfaces later. 04006 DLIList<PartitionCoSurf*> cosurf_stack; 04007 cosurf = 0; 04008 while ( (cosurf = shell_to_split->next_co_surface(cosurf)) ) 04009 if ( cosurf->get_surface()->mark != 3 ) 04010 break; 04011 if ( cosurf ) 04012 { 04013 cosurf->mark = 1; 04014 cosurf_stack.append( cosurf ); 04015 } 04016 04017 // Traverse over adjacent cosurfaces, marking them with a 1 04018 while (cosurf_stack.size()) 04019 { 04020 cosurf = cosurf_stack.pop(); 04021 PartitionSurface* surf = cosurf->get_surface(); 04022 PartitionLoop* loop = 0; 04023 while ( (loop = surf->next_loop(loop)) ) 04024 { 04025 PartitionCoEdge* coedge = loop->first_coedge(); 04026 do 04027 { 04028 PartitionCurve* curve = coedge->get_curve(); 04029 PartitionCoEdge* curve_coe = 0; 04030 PartitionCoSurf *boundary_cosurf = 0, *split_cosurf = 0; 04031 int split_cosurf_count = 0; 04032 while ( (curve_coe = curve->next_coedge(curve_coe)) ) 04033 { 04034 if ( curve_coe == coedge ) 04035 continue; 04036 04037 bool same_coe_sense = curve_coe->sense() == coedge->sense(); 04038 PartitionSurface* curve_surf = curve_coe->get_loop()->get_surface(); 04039 PartitionCoSurf* curve_cosurf = 0; 04040 while ( (curve_cosurf = curve_surf->next_co_surface(curve_cosurf)) ) 04041 { 04042 if ( curve_cosurf->get_shell() != shell_to_split ) 04043 continue; 04044 04045 bool same_cos_sense = curve_cosurf->sense() == cosurf->sense(); 04046 if ( same_cos_sense == same_coe_sense ) 04047 continue; 04048 04049 // Always choose split surface first if we 04050 // found one 04051 if ( curve_cosurf->get_surface()->mark == 2 ) { 04052 split_cosurf_count++; 04053 split_cosurf = curve_cosurf; 04054 } 04055 04056 // Skip other non-manifold surfaces. We'll 04057 // handle those later. 04058 else if( curve_cosurf->get_surface()->mark != 3 ) 04059 boundary_cosurf = curve_cosurf; 04060 } 04061 } 04062 04063 PartitionCoSurf* next_cosurf = split_cosurf ? split_cosurf : boundary_cosurf; 04064 if ( !next_cosurf->mark && split_cosurf_count < 2 ) 04065 { 04066 next_cosurf->mark = 1; 04067 cosurf_stack.append(next_cosurf); 04068 } 04069 04070 coedge = loop->next_coedge(coedge); 04071 } while( coedge != loop->first_coedge() ); 04072 } // end while (loop) 04073 } // end while (cosurf_stack.size()) 04074 04075 04076 // build lists of cosurfaces, one for each shell and 04077 // one of other non-manifold surfaces 04078 DLIList<PartitionCoSurf*> marked_list, unmarked_list, other_list; 04079 while( (cosurf = shell_to_split->next_co_surface(0)) ) 04080 { 04081 shell_to_split->remove(cosurf); 04082 if ( cosurf->get_surface()->mark == 3 ) 04083 other_list.append( cosurf ); 04084 else if( cosurf->mark ) 04085 marked_list.append( cosurf ); 04086 else 04087 unmarked_list.append( cosurf ); 04088 } 04089 04090 // If one of marked_list or unmarked_list is empty, 04091 // we can't split the shell yet. Put cofaces back in 04092 // shell and exit. 04093 if ( !marked_list.size() || !unmarked_list.size() ) 04094 { 04095 marked_list += unmarked_list; 04096 marked_list += other_list; 04097 marked_list.reverse(); 04098 while ( marked_list.size() ) 04099 { 04100 cosurf = marked_list.pop(); 04101 cosurf->mark = 0; 04102 cosurf->get_surface()->mark = 0; 04103 shell_to_split->add( cosurf ); 04104 } 04105 return 0; 04106 } 04107 04108 // Put unmarked list back in old shell 04109 unmarked_list.reverse(); 04110 while ( unmarked_list.size() ) 04111 { 04112 cosurf = unmarked_list.pop(); 04113 cosurf->get_surface()->mark = 0; 04114 shell_to_split->add(cosurf); 04115 } 04116 04117 // Put marked list in new shell 04118 PartitionShell* new_shell = new PartitionShell; 04119 marked_list.reverse(); 04120 while ( marked_list.size() ) 04121 { 04122 cosurf = marked_list.pop(); 04123 cosurf->mark = 0; 04124 cosurf->get_surface()->mark = 0; 04125 new_shell->add(cosurf); 04126 } 04127 04128 // Now sort out other non-manifold surfaces 04129 04130 // Clear marks and get list of surface from cosurfaces 04131 surf_stack.clean_out(); 04132 while( other_list.size() ) 04133 { 04134 cosurf = other_list.pop(); 04135 PartitionSurface* surf = cosurf->get_surface(); 04136 if ( surf->mark ) 04137 { 04138 surf->mark = 0; 04139 surf_stack.append(surf); 04140 } 04141 } 04142 04143 insert_nonmanifold_surfaces( surf_stack, shell_to_split, new_shell ); 04144 return new_shell; 04145 } 04146 04147 04148 //------------------------------------------------------------------------- 04149 // Purpose : After a shell is split, determine which of the two 04150 // resulting shells each non-manifold surface belongs in. 04151 // 04152 // Special Notes : 04153 // 04154 // Creator : Jason Kraftcheck 04155 // 04156 // Creation Date : 02/23/03 04157 //------------------------------------------------------------------------- 04158 void PartitionEngine::insert_nonmanifold_surfaces( 04159 DLIList<PartitionSurface*>& surf_stack, 04160 PartitionShell* shell1, 04161 PartitionShell* shell2 ) 04162 { 04163 DLIList<PartitionSurface*> known_list(surf_stack.size()), 04164 unknown_list(surf_stack.size()); 04165 04166 PartitionCoSurf* cosurf; 04167 PartitionSurface* surf; 04168 PartitionLoop* loop; 04169 PartitionCoEdge *coedge, *curve_coe; 04170 PartitionCurve* curve; 04171 04172 // Loop until we've placed all the surfaces in one 04173 // shell or the other. 04174 while ( surf_stack.size() ) 04175 { 04176 bool did_some = false; 04177 04178 // Put any surfaces for which we immediately 04179 // know the shell into the appropriate shell. 04180 // Put others in known_list or unknown_list 04181 // depending on if we can determine which shell 04182 // they go in using a geometric comparison. 04183 known_list.clean_out(); 04184 unknown_list.clean_out(); 04185 04186 // Take all surfaces out of stack in this loop. 04187 // We might put some back in after the loop (thus 04188 // the outer loop.) 04189 while ( surf_stack.size() ) 04190 { 04191 surf = surf_stack.pop(); 04192 04193 PartitionShell* known_shell = 0; 04194 bool found_shell = false; 04195 loop = 0; 04196 while ( (loop = surf->next_loop(loop)) ) 04197 { 04198 coedge = loop->first_coedge(); 04199 do 04200 { 04201 curve = coedge->get_curve(); 04202 curve_coe = 0; 04203 while ( (curve_coe = curve->next_coedge(curve_coe)) ) 04204 { 04205 PartitionSurface* surf = curve_coe->get_loop()->get_surface(); 04206 cosurf = 0; 04207 while ( (cosurf = surf->next_co_surface( cosurf )) ) 04208 { 04209 if( cosurf->get_shell() == shell1 || 04210 cosurf->get_shell() == shell2 ) 04211 { 04212 found_shell = true; 04213 if ( known_shell && known_shell != cosurf->get_shell() ) 04214 known_shell = 0; 04215 else 04216 known_shell = cosurf->get_shell(); 04217 } 04218 } 04219 } 04220 04221 coedge = loop->next_coedge(coedge); 04222 } while( coedge != loop->first_coedge() ); 04223 } // end while(loop) 04224 04225 // This surface does not intersect the shell at 04226 // any curve. We can't do this one yet. 04227 if ( !found_shell ) 04228 { 04229 unknown_list.append( surf ); 04230 continue; 04231 } 04232 04233 // This surface intersected both shells at some 04234 // curves, but did not have a curve that intersected 04235 // only one shell. We can do this one geometricly 04236 // if we have to. 04237 if ( !known_shell ) 04238 { 04239 known_list.append( surf ); 04240 continue; 04241 } 04242 04243 // If we got this far, then the surface had at least 04244 // one curve that intersected only one of the shells. 04245 // We know it goes in that shell. 04246 did_some = true; 04247 PartitionCoSurf* cosurf1 = surf->find_first((PartitionShell*)0); 04248 PartitionCoSurf* cosurf2 = surf->find_next(cosurf1); 04249 known_shell->add(cosurf1); 04250 known_shell->add(cosurf2); 04251 04252 } // while(surf_stack) -- the inside one 04253 04254 // Unknown_list always goes back in surf_stack to 04255 // try again. 04256 surf_stack += unknown_list; 04257 04258 // If we did some surfaces, then put the rest back 04259 // in surf_stack and try again. If they intersect 04260 // one of the surfaces we did place in this iteration, 04261 // we can avoid needing to do geometric checks. 04262 if ( did_some ) 04263 { 04264 surf_stack += known_list; 04265 continue; 04266 } 04267 04268 // If known_list is empty, somethings wrong (we're 04269 // going to loop forever.) Abort the loop and try 04270 // to recover as best we can. 04271 if( !known_list.size() ) 04272 break; 04273 04274 // choose a single surface in do a geometric comparison 04275 // for, and put the rest back in surf_stack 04276 surf = known_list.pop(); 04277 surf_stack += known_list; 04278 04279 bool in_shell = false; 04280 if ( ! inside_shell( shell2, surf, in_shell ) ) 04281 { 04282 // if inside_shell failed, abort. 04283 surf_stack.append(surf); 04284 break; 04285 } 04286 04287 PartitionShell* shell = in_shell ? shell2 : shell1; 04288 shell->add(surf->find_first((PartitionShell*)0)); 04289 shell->add(surf->find_first((PartitionShell*)0)); 04290 } 04291 04292 // something went wrong 04293 if( surf_stack.size() ) 04294 { 04295 PRINT_ERROR("Internal error splitting volume at %s:%d\n" 04296 "Topology may be invalid. Please report this.\n", 04297 __FILE__, __LINE__); 04298 while( surf_stack.size() ) 04299 { 04300 PartitionSurface* surf = surf_stack.pop(); 04301 cosurf = 0; 04302 while( (cosurf = surf->next_co_surface(cosurf)) ) 04303 if( !cosurf->get_shell() ) 04304 shell1->add(cosurf); 04305 } 04306 } 04307 } 04308 04309 04310 CubitStatus PartitionEngine::inside_shell( PartitionShell* const shell, 04311 PartitionSurface* const surf, 04312 bool& result ) 04313 { 04314 // Find the curve and coedge at which the nonmanifold surface 04315 // intersects the shells 04316 PartitionLoop* loop = 0; 04317 PartitionCoEdge *nonman_coedge = 0; 04318 while ( !nonman_coedge && (loop = surf->next_loop(loop)) ) 04319 { 04320 PartitionCoEdge* loop_coedge = loop->first_coedge(); 04321 do 04322 { 04323 // Check if this curve is the curve of intersection 04324 // Iterate through curve coedges. 04325 PartitionCurve* curve = loop_coedge->get_curve(); 04326 PartitionCoEdge* curve_coedge = 0; 04327 while ( (curve_coedge = curve->next_coedge(curve_coedge)) ) 04328 { 04329 04330 PartitionSurface* coedge_surf = curve_coedge->get_loop()->get_surface(); 04331 if( coedge_surf->find_first(shell) ) 04332 { 04333 nonman_coedge = curve_coedge; 04334 break; 04335 } 04336 } 04337 04338 loop_coedge = loop->next_coedge(loop_coedge); 04339 } while( !nonman_coedge && loop_coedge != loop->first_coedge() ); 04340 } 04341 04342 if ( !nonman_coedge ) // bad input! 04343 return CUBIT_FAILURE; 04344 04345 // There must exist two surfaces in the shell that are manifold 04346 // in the shell and that are adjacent to the curve 04347 PartitionCurve* common_curve = nonman_coedge->get_curve(); 04348 PartitionCoSurf *cosurf1 = 0, *cosurf2 = 0, *cosurf; 04349 PartitionCoEdge *coedge1 = 0, *coedge2 = 0, *coedge = 0; 04350 while ( (coedge = common_curve->next_coedge(coedge)) ) 04351 { 04352 PartitionSurface* surf = coedge->get_loop()->get_surface(); 04353 if ( (cosurf = surf->find_first(shell)) && !surf->find_next(cosurf) ) 04354 { 04355 if( coedge1 ) { 04356 coedge2 = coedge; 04357 cosurf2 = cosurf; 04358 } else { 04359 coedge1 = coedge; 04360 cosurf1 = cosurf; 04361 } 04362 } 04363 } 04364 if ( !coedge1 || !coedge2 ) 04365 return CUBIT_FAILURE; 04366 04367 // Evaluate normals at midpoint of curve 04368 CubitVector base, tangent, point; 04369 double u = (common_curve->start_param()+common_curve->end_param())/2.0; 04370 common_curve->position_from_u( u, base ); 04371 common_curve->closest_point( base, point, &tangent ); 04372 tangent.normalize(); 04373 04374 CubitVector normal1, normal2, normal; 04375 surf->closest_point( base, 0, &normal ); 04376 cosurf1->get_surface()->closest_point( base, 0, &normal1 ); 04377 cosurf2->get_surface()->closest_point( base, 0, &normal2 ); 04378 04379 // Try to handle tangencies 04380 bool fix1 = (normal1 * normal).length_squared() < CUBIT_RESABS; 04381 bool fix2 = (normal2 * normal).length_squared() < CUBIT_RESABS; 04382 if ( fix1 || fix2 ) 04383 { 04384 CubitVector dir = tangent * normal; 04385 double len = dir.length(); 04386 assert(len > GEOMETRY_RESABS); 04387 dir /= len; 04388 if ( nonman_coedge->sense() == CUBIT_FORWARD ) 04389 dir = -dir; 04390 04391 CubitVector diag = surf->bounding_box().diagonal(); 04392 if ( fix1 ) 04393 { 04394 CubitVector d = cosurf1->get_surface()->bounding_box().diagonal(); 04395 if ( diag.x() < d.x() ) diag.x(d.x()); 04396 if ( diag.y() < d.y() ) diag.y(d.y()); 04397 if ( diag.z() < d.z() ) diag.z(d.z()); 04398 } 04399 if( fix2 ) 04400 { 04401 CubitVector d = cosurf2->get_surface()->bounding_box().diagonal(); 04402 if ( diag.x() < d.x() ) diag.x(d.x()); 04403 if ( diag.y() < d.y() ) diag.y(d.y()); 04404 if ( diag.z() < d.z() ) diag.z(d.z()); 04405 } 04406 04407 double step = 1e-3 * fabs( diag % dir ); 04408 if ( step < 2*GEOMETRY_RESABS ) 04409 step = 2*GEOMETRY_RESABS; 04410 04411 for ( int i = 0; i < 1000; i++ ) 04412 { 04413 point = base + i * step * dir; 04414 surf->closest_point( base, 0, &normal ); 04415 if( fix1 ) 04416 cosurf1->get_surface()->closest_point( base, 0, &normal1 ); 04417 if( fix2 ) 04418 cosurf2->get_surface()->closest_point( base, 0, &normal2 ); 04419 04420 bool done1 = !fix1 || (normal1 * normal).length_squared() > CUBIT_RESABS; 04421 bool done2 = !fix2 || (normal2 * normal).length_squared() > CUBIT_RESABS; 04422 if ( done1 && done2 ) 04423 { 04424 fix1 = fix2 = false; 04425 break; 04426 } 04427 } 04428 } 04429 04430 if ( fix1 || fix2 ) 04431 { 04432 PRINT_ERROR("Failed to adjust for surface tangencies.\n" 04433 "This is a BUG. %s:%d\n", __FILE__, __LINE__ ); 04434 return CUBIT_FAILURE; 04435 } 04436 04437 if ( nonman_coedge->sense() == CUBIT_FORWARD ) 04438 normal = -normal; 04439 if ( cosurf1->sense() == coedge1->sense() ) 04440 normal1 = -normal1; 04441 if ( cosurf2->sense() == coedge2->sense() ) 04442 normal2 = -normal2; 04443 04444 result = tangent.vector_angle(normal1, normal ) <= 04445 tangent.vector_angle(normal1, normal2); 04446 return CUBIT_SUCCESS; 04447 } 04448 04449 04450 04451 04452 04453 04454 //------------------------------------------------------------------------- 04455 // Purpose : Remove a partition surface previously inserted in a 04456 // lump via insert_surface(..). 04457 // 04458 // Special Notes : 04459 // 04460 // Creator : Jason Kraftcheck 04461 // 04462 // Creation Date : 01/13/03 04463 //------------------------------------------------------------------------- 04464 Lump* PartitionEngine::remove_surface( PartitionSurface* surface ) 04465 { 04466 // If surface belongs to non-partition volumes, we cannot proceed. 04467 DLIList<TopologyBridge*> shell_bridges; 04468 surface->get_parents_virt( shell_bridges ); 04469 while( shell_bridges.size() ) 04470 if( ! dynamic_cast<PartitionShell*>(shell_bridges.pop()) ) 04471 return 0; 04472 04473 PartitionCoSurf* cosurf1 = surface->next_co_surface(0); 04474 if( ! cosurf1 ) 04475 return 0; // doesn't belong to any PartitionLumps; 04476 04477 PartitionCoSurf* cosurf2 = surface->next_co_surface(cosurf1); 04478 if( !cosurf2 || surface->next_co_surface(cosurf2) ) 04479 return 0; // must have exactly two parent cosurfaces. 04480 04481 PartitionShell* shell1 = cosurf1->get_shell(); 04482 PartitionShell* shell2 = cosurf2->get_shell(); 04483 PartitionLump* lump1 = shell1->get_lump(); 04484 PartitionLump* lump2 = shell2->get_lump(); 04485 04486 if( surface->partitioned_entity() != lump1->partitioned_entity() ) 04487 return 0; // shouldn't have gotten this far, but just in case ... 04488 04489 // remove and destroy surface 04490 shell1->remove( cosurf1 ); 04491 shell2->remove( cosurf2 ); 04492 surface->remove(cosurf1); 04493 surface->remove(cosurf2); 04494 delete cosurf1; 04495 delete cosurf2; 04496 destroy_surface(surface); 04497 04498 04499 // combine volumes? 04500 if( shell1 != shell2 ) 04501 { 04502 assert(lump1 != lump2); 04503 while( PartitionCoSurf* cosurf = shell2->next_co_surface(0) ) 04504 { 04505 shell2->remove(cosurf); 04506 shell1->add(cosurf); 04507 } 04508 lump2->remove(shell2); 04509 delete shell2; 04510 04511 if( !shell1->next_co_surface(0) ) 04512 { 04513 lump1->remove(shell1); 04514 delete shell1; 04515 } 04516 04517 while( PartitionShell* shell = lump2->next_shell(0) ) 04518 { 04519 lump2->remove(shell); 04520 lump1->add(shell); 04521 } 04522 delete lump2; 04523 } 04524 // one-surface shell 04525 else if( !shell1->next_co_surface(0) ) 04526 { 04527 lump1->remove( shell1 ); 04528 delete shell1; 04529 } 04530 // possibly split shells 04531 else 04532 { 04533 PartitionShell* shell = split_shell( shell1 ); 04534 if( shell ) 04535 lump1->add(shell); 04536 } 04537 04538 if( !lump1->sub_entity_set().has_lower_order() ) 04539 return restore_lump( lump1 ); 04540 else 04541 return lump1; 04542 } 04543 04544 04545 //------------------------------------------------------------------------- 04546 // Purpose : tear down and free a surface 04547 // 04548 // Special Notes : 04549 // 04550 // Creator : Jason Kraftcheck 04551 // 04552 // Creation Date : 01/14/03 04553 //------------------------------------------------------------------------- 04554 CubitStatus PartitionEngine::destroy_surface( PartitionSurface* surface ) 04555 { 04556 while( PartitionLoop* dead_loop = surface->next_loop(0) ) 04557 { 04558 surface->remove(dead_loop); 04559 while( PartitionCoEdge* dead_coe = dead_loop->first_coedge() ) 04560 { 04561 PartitionCurve* dead_curve = dead_coe->get_curve(); 04562 dead_loop->remove(dead_coe); 04563 dead_curve->remove(dead_coe); 04564 delete dead_coe; 04565 04566 if( dead_curve->partitioned_entity() == surface->partitioned_entity() ) 04567 { 04568 if( dead_curve->next_coedge(0) == 0 ) 04569 { 04570 PartitionPoint* start_pt = dead_curve->start_point(); 04571 PartitionPoint* end_pt = dead_curve->end_point(); 04572 delete dead_curve; 04573 if( start_pt->partitioned_entity() == surface->partitioned_entity() && 04574 start_pt->next_curve() == 0 ) 04575 delete start_pt; 04576 if( end_pt->partitioned_entity() == surface->partitioned_entity() && 04577 end_pt->next_curve() == 0 ) 04578 delete end_pt; 04579 } 04580 } 04581 else if( SubCurve* subcurve = dynamic_cast<SubCurve*>(dead_curve) ) 04582 { 04583 restore_curve(subcurve); 04584 } 04585 } 04586 delete dead_loop; 04587 } 04588 delete surface; 04589 return CUBIT_SUCCESS; 04590 } 04591 04592 04593 //------------------------------------------------------------------------- 04594 // Purpose : Retreive entity from UID attrib data. 04595 // 04596 // Special Notes : Used when restoring saved geometry. 04597 // 04598 // Creator : Jason Kraftcheck 04599 // 04600 // Creation Date : 02/23/03 04601 //------------------------------------------------------------------------- 04602 PartitionEntity* PartitionEngine::entity_from_id( int set_id, 04603 int entity_id, 04604 SubEntitySet& default_set ) 04605 { 04606 if( set_id == 0 ) 04607 return default_set.entity_from_id( entity_id ); 04608 04609 SubEntitySet* set = get_from_id_map(set_id); 04610 if( set ) 04611 return set->entity_from_id( entity_id ); 04612 04613 return 0; 04614 } 04615 04616 //------------------------------------------------------------------------- 04617 // Purpose : Restore curve partitions 04618 // 04619 // Special Notes : 04620 // 04621 // Creator : Jason Kraftcheck 04622 // 04623 // Creation Date : 02/23/03 04624 //------------------------------------------------------------------------- 04625 CubitStatus PartitionEngine::restore_from_attrib( Curve* curve ) 04626 { 04627 int i, id, dim, max_id = 0; 04628 DLIList<CubitSimpleAttrib> attribs, point_attribs, curve_attribs; 04629 DLIList<CubitVector*> empty; 04630 DLIList<int> junk, point_conn; 04631 DLIList<PartitionPoint*> new_points; 04632 CubitStatus result = CUBIT_FAILURE; 04633 04634 { 04635 // Get list of partition attributes. 04636 curve->get_simple_attribute(PARTITION_GEOM_ATTRIB_NAME,attribs); 04637 if( attribs.size() == 0 ) 04638 return CUBIT_SUCCESS; 04639 04640 // Group attributes into those defining partition points and 04641 // those defining the subcurves. Also find max ID of all 04642 // partition geometry on this curve 04643 attribs.reset(); 04644 for( i = attribs.size(); i--; ) 04645 { 04646 const CubitSimpleAttrib& attrib = attribs.get_and_step(); 04647 dim = SubEntitySet::get_geom_dimension(attrib); 04648 if( dim == 0 ) 04649 point_attribs.append(attrib); 04650 else if( dim == 1 ) 04651 curve_attribs.append(attrib); 04652 else 04653 goto CLEANUP_CURVE_FROM_ATTRIB; 04654 04655 id = SubEntitySet::get_geom_id( attrib ); 04656 if( id > max_id ) 04657 max_id = id; 04658 } 04659 04660 // Create first curve (duplicate of input curve) 04661 PartitionCurve* first_curve = replace_curve( curve ); 04662 if( ! first_curve ) 04663 goto CLEANUP_CURVE_FROM_ATTRIB; 04664 04665 // Set up SubEntitySet such that new entities get IDs 04666 // larger than max_id as they are created. 04667 first_curve->sub_entity_set().renumerate( max_id + 1, false ); 04668 04669 // Create all the partition points 04670 point_attribs.reset(); 04671 for( i = point_attribs.size(); i--; ) 04672 { 04673 const CubitSimpleAttrib& attrib = point_attribs.get_and_step(); 04674 PartitionPoint* point = new PartitionPoint( attrib, first_curve ); 04675 if( !point ) 04676 goto CLEANUP_CURVE_FROM_ATTRIB; 04677 04678 curve->remove_simple_attribute_virt(attrib); 04679 } 04680 04681 // Now partition the curve and assign the ID from each 04682 // curve attribute the the appropriate curve partition. 04683 // 04684 // We're going to do this in order along the curve, such 04685 // that the first subcurve will begin at the start_point() of 04686 // the original curve. 04687 PartitionPoint* prev_point = first_curve->start_point(); 04688 PartitionCurve* next_curve = first_curve; 04689 while( curve_attribs.size() ) 04690 { 04691 // Search for attribute corresponding to curve 04692 // beginning at prev_point 04693 PartitionPoint *start = 0, *end = 0; 04694 CubitSimpleAttrib curve_attrib; 04695 curve_attribs.last(); 04696 for( i = curve_attribs.size(); i--; ) 04697 { 04698 // Get data from attribute 04699 const CubitSimpleAttrib& attrib = curve_attribs.step_and_get(); 04700 point_conn.clean_out(); 04701 if( !SubEntitySet::read_geometry(id,dim,empty,junk,point_conn,junk,attrib) 04702 || empty.size() || junk.size() || dim != 1 || point_conn.size() != 4) 04703 goto CLEANUP_CURVE_FROM_ATTRIB; 04704 04705 // Get start point from IDs 04706 point_conn.reset(); 04707 int sid = point_conn.get_and_step(); 04708 int eid = point_conn.get_and_step(); 04709 PartitionEntity* ent = entity_from_id(sid, eid, first_curve->sub_entity_set()); 04710 start = dynamic_cast<PartitionPoint*>(ent); 04711 04712 if( start == prev_point ) 04713 { 04714 // Found the attrib we want. 04715 // Get the end point and break the loop. 04716 sid = point_conn.get_and_step(); 04717 eid = point_conn.get_and_step(); 04718 ent = entity_from_id(sid, eid, first_curve->sub_entity_set()); 04719 end = dynamic_cast<PartitionPoint*>(ent); 04720 04721 curve_attrib = curve_attribs.extract(); 04722 break; 04723 } 04724 } 04725 04726 // Make sure we found an attrib to do 04727 if( curve_attrib.isEmpty() || !start || !end ) 04728 goto CLEANUP_CURVE_FROM_ATTRIB; 04729 04730 // Unless this is the last partition (no more splitting 04731 // required), split the curve at the end point. Make 04732 // next_curve point to the (unpartitioned) remainder of 04733 // the curve. 04734 PartitionCurve* new_curve = next_curve; 04735 if( next_curve->end_point() != end ) 04736 { 04737 next_curve = insert_point( new_curve, end ); 04738 if( !next_curve ) 04739 goto CLEANUP_CURVE_FROM_ATTRIB; 04740 } 04741 04742 // Set the new curve's ID to whatever it is stored 04743 // as in the attribute. 04744 new_curve->sub_entity_set().set_id( new_curve, 04745 SubEntitySet::get_geom_id( curve_attrib ) ); 04746 04747 // Remove processed attributes. 04748 curve->remove_simple_attribute_virt( curve_attrib ); 04749 04750 // Next iteration 04751 prev_point = end; 04752 } 04753 04754 // Compress SubEntitySet ID space 04755 next_curve->sub_entity_set().renumerate( max_id + 1, true ); 04756 result = CUBIT_SUCCESS; 04757 } 04758 04759 CLEANUP_CURVE_FROM_ATTRIB: 04760 04761 for( i = new_points.size(); i--; ) 04762 { 04763 PartitionPoint* pt = new_points.get_and_step(); 04764 if( !pt->next_curve(0) ) 04765 delete pt; 04766 } 04767 04768 if (!result) 04769 PRINT_ERROR("Error restoring curve partitions from attributes.\n"); 04770 04771 return result; 04772 } 04773 04774 04775 //------------------------------------------------------------------------- 04776 // Purpose : Restore surface partitions 04777 // 04778 // Special Notes : 04779 // 04780 // Creator : Jason Kraftcheck 04781 // 04782 // Creation Date : 02/23/03 04783 //------------------------------------------------------------------------- 04784 CubitStatus PartitionEngine::restore_from_attrib( Surface* surf ) 04785 { 04786 int i, j, k, id, dim, max_id = 0; 04787 DLIList<CubitSimpleAttrib> attribs; 04788 DLIList<CubitFacetEdgeData*> polyline_edges; 04789 DLIList<CubitPointData*> polyline_pts; 04790 DLIList<CubitFacetData*> surf_facets; 04791 DLIList<CubitVector*> positions; 04792 DLIList<PartitionEntity*> new_geom; 04793 DLIList<PartitionLoop*> loops; 04794 DLIList<int> facets(0), connectivity, pt_owners; 04795 CubitStatus result = CUBIT_FAILURE; 04796 SubSurface* first_surf = 0; 04797 04798 04799 { 04800 // Get partition attributes from entity. Return if there aren't any. 04801 surf->get_simple_attribute(PARTITION_GEOM_ATTRIB_NAME,attribs); 04802 if( attribs.size() == 0 ) 04803 return CUBIT_SUCCESS; 04804 04805 PRINT_DEBUG_86("Reading partition geometry on %s %p\n", 04806 fix_type_name( typeid(*surf).name() ), (void*)surf ); 04807 04808 // Find max ID 04809 attribs.reset(); 04810 for( i = attribs.size(); i--; ) 04811 { 04812 id = SubEntitySet::get_geom_id( attribs.get_and_step() ); 04813 if( id > max_id ) 04814 max_id = id; 04815 } 04816 04817 // Create first partition surface (initially a duplicate of 04818 // the input surface) 04819 first_surf = replace_surface( surf ); 04820 if( ! first_surf ) 04821 { 04822 PRINT_ERROR("Internal Error: PartitionEngine::replace_surface() failed.\n"); 04823 goto CLEANUP_SURF_FROM_ATTRIB; 04824 } 04825 04826 // Update SubEntitySet such that new entities get assigned 04827 // IDs greater than max_id when they are created. This 04828 // leaves the range 0->max_id free so that we can reassign 04829 // the saved IDs after the entities are created. 04830 first_surf->sub_entity_set().renumerate( max_id + 1, false ); 04831 04832 // create all interior vertices 04833 attribs.reset(); 04834 for( i = attribs.size(); i--; ) 04835 { 04836 // Only want point attributes (dimension of zero) 04837 CubitSimpleAttrib attrib = attribs.get(); 04838 if( SubEntitySet::get_geom_dimension(attrib) != 0 ) 04839 { 04840 attribs.step(); 04841 continue; 04842 } 04843 04844 // Create the point at the location specified in the attrib. 04845 attribs.extract(); 04846 surf->remove_simple_attribute_virt(attrib); 04847 PartitionPoint* new_pt = new PartitionPoint( attrib, first_surf ); 04848 CubitPointData* data = project_to_surface( first_surf, new_pt->coordinates() ); 04849 new_pt->facet_point(data); 04850 new_geom.append(new_pt); 04851 PRINT_DEBUG_86(" Created Point %p (%d in subset) at (%f,%f,%f)\n", 04852 (void*)new_pt, new_pt->sub_entity_set().get_id(new_pt), 04853 new_pt->coordinates().x(), new_pt->coordinates().y(), 04854 new_pt->coordinates().z() ); 04855 if (DEBUG_FLAG(86)) 04856 { 04857 GfxDebug::draw_point(new_pt->coordinates(), new_pt->sub_entity_set().get_id(new_pt)); 04858 GfxDebug::flush(); 04859 } 04860 } 04861 04862 // create all interior curves 04863 attribs.reset(); 04864 for( i = attribs.size(); i--; ) 04865 { 04866 // Only want curve attributes (dimension of one) 04867 CubitSimpleAttrib attrib = attribs.get(); 04868 if( SubEntitySet::get_geom_dimension(attrib) != 1 ) 04869 { 04870 attribs.step(); 04871 continue; 04872 } 04873 04874 // Remove this attrib from the real geom, as we are 04875 // handling it 04876 attribs.extract(); 04877 surf->remove_simple_attribute_virt(attrib); 04878 04879 if ( SubEntitySet::get_segment_count(attrib) == 0 ) 04880 { 04881 PartPTCurve* pt_curve = PartPTCurve::construct(attrib, first_surf); 04882 if (!pt_curve) 04883 { 04884 PRINT_ERROR("point-curve construction failed -- corrupt data?\n"); 04885 goto CLEANUP_SURF_FROM_ATTRIB; 04886 } 04887 new_geom.append( pt_curve ); 04888 PRINT_DEBUG_86(" Created point-curve %p (%d in subset) with\n" 04889 " point %p (%d in subset) at (%f,%f,%f)\n", 04890 (void*)pt_curve, 04891 pt_curve->sub_entity_set().get_id(pt_curve), 04892 (void*)pt_curve->start_point(), 04893 pt_curve->start_point()->sub_entity_set().get_id(pt_curve->start_point()), 04894 pt_curve->start_point()->coordinates().x(), 04895 pt_curve->start_point()->coordinates().y(), 04896 pt_curve->start_point()->coordinates().z() ); 04897 04898 CubitPointData* pt = project_to_surface( first_surf, pt_curve->start_point()->coordinates() ); 04899 if ( !pt ) 04900 { 04901 PRINT_ERROR("projection of position onto surface facets failed.\n"); 04902 goto CLEANUP_SURF_FROM_ATTRIB; 04903 } 04904 04905 pt_curve->start_point()->facet_point( pt ); 04906 continue; 04907 } 04908 04909 // Create the curve 04910 SegmentedCurve* new_curve = SegmentedCurve::construct( attrib, first_surf ); 04911 if( !new_curve ) 04912 { 04913 PRINT_ERROR("segmented curve construction failed -- corrupt data?\n"); 04914 goto CLEANUP_SURF_FROM_ATTRIB; 04915 } 04916 new_geom.append(new_curve); 04917 PRINT_DEBUG_86(" Created polyline curve %p (%d in subset) with %d segments.\n" 04918 " start point %p (%d in subset) at (%f,%f,%f)\n" 04919 " end point %p (%d in subset) at (%f,%f,%f)\n", 04920 (void*)new_curve, 04921 new_curve->sub_entity_set().get_id(new_curve), 04922 new_curve->point_count() - 1, 04923 (void*)new_curve->start_point(), 04924 new_curve->start_point()->sub_entity_set().get_id(new_curve->start_point()), 04925 new_curve->start_point()->coordinates().x(), 04926 new_curve->start_point()->coordinates().y(), 04927 new_curve->start_point()->coordinates().z(), 04928 (void*)new_curve->end_point(), 04929 new_curve->end_point()->sub_entity_set().get_id(new_curve->end_point()), 04930 new_curve->end_point()->coordinates().x(), 04931 new_curve->end_point()->coordinates().y(), 04932 new_curve->end_point()->coordinates().z() ); 04933 04934 // Get curve segments 04935 positions.clean_out(); 04936 polyline_edges.clean_out(); 04937 new_curve->get_segments( positions ); 04938 04939 if (DEBUG_FLAG(86)) 04940 { 04941 GPoint* array = new GPoint[positions.size()]; 04942 positions.reset(); 04943 for (int dd = 0; dd < positions.size(); dd++ ) 04944 { 04945 array[dd].x = (float)positions.next(dd)->x(); 04946 array[dd].y = (float)positions.next(dd)->y(); 04947 array[dd].z = (float)positions.next(dd)->z(); 04948 } 04949 04950 GfxDebug::draw_polyline(array, positions.size(), 04951 new_curve->sub_entity_set().get_id(new_curve)); 04952 GfxDebug::flush(); 04953 } 04954 04955 // Make sure segment end points are on curve end points 04956 positions.last(); 04957 *positions.get() = new_curve->end_point()->coordinates(); 04958 positions.reset(); 04959 *positions.get() = new_curve->start_point()->coordinates(); 04960 04961 // Project curve into surface facets 04962 surf_facets.clean_out(); 04963 first_surf->get_facet_data( surf_facets ); 04964 CubitStatus s = project_to_surface( surf_facets, positions, 04965 polyline_edges, polyline_pts ); 04966 while( positions.size() ) 04967 { 04968 CubitVector* position = positions.pop(); 04969 if(s) 04970 { 04971 // assert(polyline_pts.size()); 04972 CubitPointData* point = polyline_pts.pop(); 04973 if (point && point->check_inverted_facets(*position)) 04974 point->set(*position); 04975 } 04976 delete position; 04977 } 04978 if( !s || !polyline_edges.size() ) 04979 { 04980 PRINT_ERROR("Imprint of polyline onto surface facets failed.\n"); 04981 goto CLEANUP_SURF_FROM_ATTRIB; 04982 } 04983 04984 04985 // move facet points onto surface 04986 for ( j = 0; j < 2; j++ ) 04987 for ( k = polyline_edges.size(); k--; ) 04988 if ( CubitFacetEdgeData* edge = polyline_edges.get_and_step() ) 04989 edge->point(j)->marked(1); 04990 04991 for ( j = polyline_edges.size(); j--; ) 04992 { 04993 CubitFacetEdgeData* edge = polyline_edges.get_and_step(); 04994 if ( !edge ) continue; 04995 for ( k = 0; k < 2; k++ ) 04996 { 04997 CubitPoint* pt = edge->point(k); 04998 if ( pt->marked() ) 04999 { 05000 pt->marked(0); 05001 first_surf->relax_to_geometry(pt); 05002 } 05003 } 05004 } 05005 05006 05007 // Associate facet data with geometry 05008 05009 CubitPoint *last_pt, *first_pt; 05010 polyline_edges.last(); 05011 assert(!polyline_edges.get()); 05012 polyline_edges.pop(); 05013 05014 if( polyline_edges.size() == 1 ) 05015 { 05016 last_pt = polyline_edges.get()->point(1); 05017 first_pt = polyline_edges.get()->point(0); 05018 } 05019 else 05020 { 05021 CubitFacetEdgeData *edge, *neighbor; 05022 05023 polyline_edges.last(); 05024 edge = polyline_edges.get(); 05025 neighbor = polyline_edges.prev(); 05026 if( !edge || !neighbor ) 05027 { 05028 PRINT_ERROR("Bad surface facets.\n"); 05029 goto CLEANUP_SURF_FROM_ATTRIB; 05030 } 05031 last_pt = edge->shared_point(neighbor); 05032 last_pt = edge->other_point(last_pt); 05033 05034 polyline_edges.reset(); 05035 edge = polyline_edges.get(); 05036 neighbor = polyline_edges.next(); 05037 if( !edge || !neighbor ) 05038 { 05039 PRINT_ERROR("Bad surface facets.\n"); 05040 goto CLEANUP_SURF_FROM_ATTRIB; 05041 } 05042 first_pt = edge->shared_point(neighbor); 05043 first_pt = edge->other_point(first_pt); 05044 } 05045 05046 PartitionEntity* owner1 = TDVGFacetOwner::get( first_pt ); 05047 PartitionEntity* owner2 = TDVGFacetOwner::get( last_pt ); 05048 05049 if ( new_curve->start_point() == new_curve->end_point() ) 05050 { 05051 if ( owner1 == owner2 && owner1 == new_curve->start_point() ) 05052 { 05053 first_pt = polyline_edges.get()->other_point( first_pt ); 05054 polyline_edges.last(); 05055 last_pt = polyline_edges.get()->other_point( last_pt ); 05056 double u1 = new_curve->u_from_position( first_pt->coordinates() ); 05057 double u2 = new_curve->u_from_position( last_pt->coordinates() ); 05058 if ( u2 < u1 ) 05059 polyline_edges.reverse(); 05060 polyline_edges.reset(); 05061 } 05062 else 05063 { 05064 s = CUBIT_FAILURE; 05065 } 05066 } 05067 else if ( owner1 == new_curve->end_point() && 05068 owner2 == new_curve->start_point() ) 05069 { 05070 polyline_edges.reverse(); 05071 polyline_edges.reset(); 05072 } 05073 else if( owner1 != new_curve->start_point() || 05074 owner2 != new_curve->end_point() ) 05075 { 05076 s = CUBIT_FAILURE; 05077 } 05078 05079 if (!s) 05080 { 05081 PRINT_ERROR("Tolerance problems when restoring surface partitions.\n"); 05082 goto CLEANUP_SURF_FROM_ATTRIB; 05083 } 05084 05085 new_curve->set_facet_data( polyline_edges ); 05086 } 05087 05088 // while there are more surface partitions to create 05089 PartitionEntity* ent = 0; 05090 while( attribs.size() ) 05091 { 05092 // read attribute 05093 CubitSimpleAttrib surf_attr = attribs.pop(); 05094 connectivity.clean_out(); 05095 CubitStatus s = SubEntitySet:: 05096 read_geometry( id, dim, positions, facets, connectivity, pt_owners, surf_attr ); 05097 05098 if( !s || dim != 2 || positions.size() || facets.size() ) 05099 { 05100 PRINT_ERROR("Corrupt/inconsistent subsurface data.\n"); 05101 goto CLEANUP_SURF_FROM_ATTRIB; 05102 } 05103 05104 PRINT_DEBUG_86(" Constructing SubSurface (%d in subset)\n", id); 05105 05106 // construct surface loops 05107 int j = connectivity.size(); 05108 PartitionCoEdge* curve_coedge = 0; // save one non-point-curve coedge 05109 while ( j > 0 ) 05110 { 05111 int loop = connectivity.get_and_step(); 05112 j--; 05113 05114 PartitionLoop* new_loop = new PartitionLoop(); 05115 loops.append( new_loop ); 05116 PartitionCoEdge* prev_coedge = 0; 05117 PRINT_DEBUG_86(" Loop: "); 05118 05119 while( loop-- ) 05120 { 05121 int set_id = connectivity.get_and_step(); 05122 int ent_id = connectivity.get_and_step(); 05123 int sense = ent_id < 0 ? -1 : 1; 05124 ent_id *= sense; 05125 j -= 2; 05126 05127 ent = entity_from_id( set_id, ent_id, first_surf->sub_entity_set() ); 05128 PartitionCurve* curve = dynamic_cast<PartitionCurve*>(ent); 05129 PRINT_DEBUG_86(" %p,%d,%d%c", (void*)curve, set_id, ent_id*sense, loop?',':'\n'); 05130 if(!curve) 05131 { 05132 PRINT_ERROR("Nonexistant curve specified in saved connectivity.\n"); 05133 goto CLEANUP_SURF_FROM_ATTRIB; 05134 } 05135 05136 CubitSense cubit_sense = sense == -1 ? CUBIT_REVERSED : CUBIT_FORWARD; 05137 PartitionCoEdge* coedge = 0; 05138 while ( (coedge = curve->next_coedge(coedge)) ) 05139 { 05140 if ( coedge->sense() == cubit_sense && 05141 coedge->get_loop() && 05142 coedge->get_loop()->get_surface() == first_surf ) 05143 { 05144 coedge->get_loop()->remove( coedge ); 05145 break; 05146 } 05147 } 05148 if ( !coedge ) 05149 { 05150 coedge = new PartitionCoEdge( first_surf, cubit_sense ); 05151 curve->add(coedge); 05152 } 05153 05154 if (!curve_coedge && curve->geometry_type() != POINT_CURVE_TYPE) 05155 curve_coedge = coedge; 05156 05157 new_loop->insert_after( coedge, prev_coedge ); 05158 prev_coedge = coedge; 05159 } 05160 } 05161 05162 if (!curve_coedge) 05163 { 05164 PRINT_ERROR("Nonexistant co-edge specified in saved connectivity.\n"); 05165 goto CLEANUP_SURF_FROM_ATTRIB; 05166 } 05167 05168 PartitionSurface* new_surf = split_surface( first_surf, curve_coedge ); 05169 if (new_surf == first_surf && attribs.size() > 0) 05170 { 05171 PRINT_ERROR("Surface splitting failed -- bad topology?.\n"); 05172 goto CLEANUP_SURF_FROM_ATTRIB; 05173 } 05174 05175 new_surf->sub_entity_set().set_id( new_surf, id ); 05176 while ( loops.size() ) 05177 new_surf->add( loops.pop() ); 05178 } 05179 05180 result = CUBIT_SUCCESS; 05181 } 05182 05183 CLEANUP_SURF_FROM_ATTRIB: 05184 05185 // clean up any unused loops from failed surface creation 05186 while ( loops.size() ) 05187 { 05188 PartitionLoop* loop = loops.pop(); 05189 while ( loop->first_coedge() ) 05190 { 05191 PartitionCoEdge* coedge = loop->first_coedge(); 05192 loop->remove(coedge); 05193 if (coedge->get_curve()) 05194 coedge->get_curve()->remove(coedge); 05195 delete coedge; 05196 } 05197 delete loop; 05198 } 05199 05200 // first_surf will contain dead loops - clean them up 05201 PartitionLoop* surf_loop = 0; 05202 while ( (surf_loop = first_surf->next_loop( surf_loop ) ) != NULL ) 05203 if ( !surf_loop->first_coedge() ) 05204 loops.append( surf_loop ); 05205 while ( loops.size() ) 05206 { 05207 surf_loop = loops.pop(); 05208 first_surf->remove( surf_loop ); 05209 delete surf_loop; 05210 } 05211 05212 new_geom.reset(); 05213 while( new_geom.size() ) 05214 { 05215 PartitionEntity* ent = new_geom.pop(); 05216 if( PartitionPoint* pt = dynamic_cast<PartitionPoint*>(ent) ) 05217 { 05218 if( !pt->next_curve(0) ) 05219 delete pt; 05220 } 05221 else if( PartitionCurve* curve = dynamic_cast<PartitionCurve*>(ent) ) 05222 { 05223 if( !curve->next_coedge(0) ) 05224 delete curve; 05225 } 05226 } 05227 05228 first_surf->sub_entity_set().renumerate( max_id + 1, true ); 05229 05230 if (!result) 05231 PRINT_ERROR("Error restoring surface partitions from attributes.\n"); 05232 05233 return result; 05234 } 05235 05236 //------------------------------------------------------------------------- 05237 // Purpose : Restore volume partitions from an attribute 05238 // 05239 // Special Notes : 05240 // 05241 // Creator : Jason Kraftcheck 05242 // 05243 // Creation Date : 01/22/03 05244 //------------------------------------------------------------------------- 05245 CubitStatus PartitionEngine::restore_from_attrib( Lump* lump ) 05246 { 05247 int i, id, dim, max_id = 0; 05248 DLIList<CubitSimpleAttrib> attribs; 05249 DLIList<CubitVector*> positions; 05250 DLIList<int> facets, connectivity, pt_owners; 05251 DLIList<PartitionEntity*> new_geom; 05252 CubitStatus result = CUBIT_FAILURE; 05253 PartitionLump* first_lump = 0; 05254 PartitionLump* new_lump = 0; 05255 05256 { // pseudo-'try'-block 05257 05258 // get partition attributes from entity. Return if none. 05259 lump->get_simple_attribute(PARTITION_GEOM_ATTRIB_NAME,attribs); 05260 if( attribs.size() == 0 ) 05261 return CUBIT_SUCCESS; 05262 05263 // find max ID 05264 attribs.reset(); 05265 for( i = attribs.size(); i--; ) 05266 { 05267 id = SubEntitySet::get_geom_id( attribs.get_and_step() ); 05268 if( id > max_id ) 05269 max_id = id; 05270 } 05271 05272 // Create first parition lump (initially a duplicate of 05273 // the input lump) 05274 first_lump = replace_lump( lump ); 05275 if( ! first_lump ) 05276 goto CLEANUP_LUMP_FROM_ATTRIB; 05277 05278 // Update SubEntitySet such that new entities get assigned 05279 // IDs greater than max_id when they are created. This 05280 // leaves the range 0->max_id free so that we can reassign 05281 // the saved IDs after the entities are created. 05282 first_lump->sub_entity_set().renumerate( max_id + 1, false ); 05283 05284 // create all interior vertices 05285 attribs.reset(); 05286 for( i = attribs.size(); i--; ) 05287 { 05288 // skip any non-point geometry 05289 CubitSimpleAttrib attrib = attribs.get(); 05290 if( SubEntitySet::get_geom_dimension(attrib) != 0 ) 05291 { 05292 attribs.step(); 05293 continue; 05294 } 05295 05296 // create the point as specified in the attrib 05297 attribs.extract(); 05298 lump->remove_simple_attribute_virt(attrib); 05299 PartitionPoint* new_pt = new PartitionPoint( attrib, first_lump ); 05300 new_geom.append(new_pt); 05301 } 05302 05303 // create all interior curves 05304 attribs.reset(); 05305 for( i = attribs.size(); i--; ) 05306 { 05307 // skip attribs for anything but curves 05308 CubitSimpleAttrib attrib = attribs.get(); 05309 if( SubEntitySet::get_geom_dimension(attrib) != 1 ) 05310 { 05311 attribs.step(); 05312 continue; 05313 } 05314 05315 // create curve from attrib 05316 attribs.extract(); 05317 lump->remove_simple_attribute_virt(attrib); 05318 SegmentedCurve* new_curve = SegmentedCurve::construct( attrib, first_lump ); 05319 if( !new_curve ) 05320 goto CLEANUP_LUMP_FROM_ATTRIB; 05321 05322 new_geom.append(new_curve); 05323 } 05324 05325 // create all interior surfaces 05326 attribs.reset(); 05327 for( i = attribs.size(); i--; ) 05328 { 05329 // skip non-surface attributes 05330 CubitSimpleAttrib attrib = attribs.get(); 05331 if( SubEntitySet::get_geom_dimension(attrib) != 2 ) 05332 { 05333 attribs.step(); 05334 continue; 05335 } 05336 05337 // create surface from attribute 05338 attribs.extract(); 05339 lump->remove_simple_attribute_virt(attrib); 05340 PartitionSurface* new_surf = PartitionSurface::construct( attrib, first_lump ); 05341 if( !new_surf ) 05342 goto CLEANUP_LUMP_FROM_ATTRIB; 05343 05344 new_geom.append(new_surf); 05345 } 05346 05347 05348 // while there are more volume partitions to create 05349 PartitionEntity* ent = 0; 05350 while( attribs.size() ) 05351 { 05352 // Read data from attribute 05353 const CubitSimpleAttrib& attr = attribs.pop(); 05354 connectivity.clean_out(); 05355 CubitStatus s = SubEntitySet:: 05356 read_geometry( id, dim, positions, facets, connectivity, pt_owners, attr ); 05357 if( !s || dim != 3 || positions.size() || facets.size() ) 05358 { 05359 new_lump = 0; 05360 goto CLEANUP_LUMP_FROM_ATTRIB; 05361 } 05362 05363 new_lump = new PartitionLump( first_lump ); 05364 05365 // Get list of bounding co-surfaces from attrib data 05366 int j = connectivity.size(); 05367 while( j > 0 ) 05368 { 05369 int shell = connectivity.get_and_step(); 05370 j--; 05371 PartitionShell* new_shell = new PartitionShell(); 05372 new_lump->add(new_shell); 05373 while( shell-- ) 05374 { 05375 int set_id = connectivity.get_and_step(); 05376 int ent_id = connectivity.get_and_step(); 05377 j -= 2; 05378 05379 CubitSense sense = CUBIT_FORWARD; 05380 if ( ent_id < 0 ) 05381 { 05382 ent_id = -ent_id; 05383 sense = CUBIT_REVERSED; 05384 } 05385 05386 ent = entity_from_id( set_id, ent_id, first_lump->sub_entity_set() ); 05387 PartitionSurface* surf = dynamic_cast<PartitionSurface*>(ent); 05388 if(!surf) 05389 goto CLEANUP_LUMP_FROM_ATTRIB; 05390 05391 PartitionCoSurf* new_cosurf = new PartitionCoSurf(sense); 05392 surf->add(new_cosurf); 05393 new_shell->add(new_cosurf); 05394 } 05395 } 05396 05397 new_lump->sub_entity_set().set_id( new_lump, id ); 05398 new_lump = 0; // we succeeded with this one, so don't try to 05399 // destroy it if we fail before creating the next. 05400 } 05401 05402 result = CUBIT_SUCCESS; 05403 } 05404 05405 CLEANUP_LUMP_FROM_ATTRIB: 05406 05407 if( new_lump ) // created a lump but didn't successfully complete it 05408 { 05409 PartitionShell* shell = 0; 05410 while ( shell ) 05411 { 05412 new_lump->remove(shell); 05413 shell->remove_all_surfaces(); 05414 PartitionShell* old_shell = shell; 05415 shell = new_lump->next_shell(shell); 05416 delete old_shell; 05417 } 05418 } 05419 05420 DLIList<PartitionEntity*> lump_list; 05421 if( first_lump ) 05422 { 05423 // Get list of other lumps created 05424 first_lump->sub_entity_set().get_sub_entities( lump_list ); 05425 lump_list.move_to(first_lump); 05426 assert( lump_list.get() == first_lump ); 05427 lump_list.extract(); 05428 05429 // Destroy first_lump (it is the union of all the partitions) 05430 DLIList<PartitionSurface*> surfaces; 05431 PartitionShell* shell = 0; 05432 while ( shell ) 05433 { 05434 first_lump->remove(shell); 05435 shell->remove_all_surfaces( &surfaces ); 05436 PartitionShell* old_shell = shell; 05437 shell = first_lump->next_shell(shell); 05438 delete old_shell; 05439 while( surfaces.size() ) 05440 { 05441 SubSurface* surf = dynamic_cast<SubSurface*>(surfaces.pop()); 05442 if ( surf && !surf->next_co_surface(0) && 05443 !surf->sub_entity_set().has_lower_order() ) 05444 restore_surface( surf ); 05445 } 05446 } 05447 delete first_lump; 05448 } 05449 05450 // destroy any unused split geometry 05451 new_geom.reset(); 05452 while( new_geom.size() ) 05453 { 05454 PartitionEntity* ent = new_geom.pop(); 05455 if( PartitionPoint* pt = dynamic_cast<PartitionPoint*>(ent) ) 05456 { 05457 if( !pt->next_curve(0) ) 05458 delete pt; 05459 } 05460 else if( PartitionCurve* curve = dynamic_cast<PartitionCurve*>(ent) ) 05461 { 05462 if( !curve->next_coedge(0) ) 05463 delete curve; 05464 } 05465 else if( PartitionSurface* surf = dynamic_cast<PartitionSurface*>(ent) ) 05466 { 05467 if( !surf->next_co_surface(0) ) 05468 destroy_surface( surf ); 05469 } 05470 } 05471 05472 // if there are any remaining partitions of the volume, 05473 // compress the ID space 05474 if ( lump_list.size() ) 05475 { 05476 lump_list.get()->sub_entity_set().renumerate( max_id + 1, true ); 05477 } 05478 05479 if (!result) 05480 PRINT_ERROR("Error restoring volume partitions from attributes.\n"); 05481 05482 return result; 05483 } 05484 05485 05486 05487 //------------------------------------------------------------------------- 05488 // Purpose : Save partition geometry 05489 // 05490 // Special Notes : 05491 // 05492 // Creator : Jason Kraftcheck 05493 // 05494 // Creation Date : 02/23/03 05495 //------------------------------------------------------------------------- 05496 CubitStatus PartitionEngine::export_geometry( DLIList<TopologyBridge*>& list ) 05497 { 05498 int i; 05499 CubitStatus result = CUBIT_SUCCESS; 05500 05501 if ( CGMApp::instance()->attrib_manager()->auto_update_flag(CA_PARTITION_VG) && 05502 CGMApp::instance()->attrib_manager()->auto_write_flag(CA_PARTITION_VG) ) 05503 { 05504 05505 // Get all child topology to export 05506 05507 DLIList<Curve*> curve_list; 05508 DLIList<Surface*> surface_list; 05509 DLIList<Lump*> lump_list; 05510 DLIList<BodySM*> body_list; 05511 DLIList<TopologyBridge*> bridge_list, temp_list, coe_curves(1), surf_curves; 05512 05513 CAST_LIST( list, curve_list, Curve ); 05514 CAST_LIST( list, surface_list, Surface ); 05515 CAST_LIST( list, lump_list, Lump ); 05516 CAST_LIST( list, body_list, BodySM ); 05517 05518 for( i = body_list.size(); i--; ) 05519 { 05520 BodySM* body = body_list.get_and_step(); 05521 body->get_children( bridge_list, true, layer() ); 05522 while( bridge_list.size() ) 05523 lump_list.append( dynamic_cast<Lump*>(bridge_list.pop()) ); 05524 } 05525 05526 for( i = lump_list.size(); i--; ) 05527 { 05528 Lump* lump = lump_list.get_and_step(); 05529 lump->get_children( bridge_list, true, layer() ); 05530 while( bridge_list.size() ) 05531 { 05532 bridge_list.pop()->get_children( temp_list, true, layer() ); 05533 while( temp_list.size() ) 05534 surface_list.append( dynamic_cast<Surface*>(temp_list.pop()) ); 05535 } 05536 } 05537 05538 for( i = surface_list.size(); i--; ) 05539 { 05540 Surface* surf = surface_list.get_and_step(); 05541 surf->get_children( bridge_list, true, layer() ); 05542 while( bridge_list.size() ) 05543 { 05544 bridge_list.pop()->get_children( temp_list, true, layer() ); 05545 while( temp_list.size() ) 05546 { 05547 temp_list.pop()->get_children_virt( coe_curves ); 05548 assert(coe_curves.size() == 1); 05549 surf_curves.append(coe_curves.pop()); 05550 } 05551 } 05552 surf_curves.uniquify_ordered(); 05553 while( surf_curves.size() ) 05554 curve_list.append( dynamic_cast<Curve*>(surf_curves.pop()) ); 05555 } 05556 05557 05558 // save curve partitions 05559 05560 DLIList<SubEntitySet*> set_list; 05561 for( i = curve_list.size(); i--; ) 05562 { 05563 SubCurve* curve = dynamic_cast<SubCurve*>(curve_list.get_and_step()); 05564 if( curve ) 05565 set_list.append( &(curve->sub_entity_set()) ); 05566 } 05567 set_list.uniquify_ordered(); 05568 for( i = set_list.size(); i--; ) 05569 if( ! set_list.get_and_step()->save_geometry() ) 05570 result = CUBIT_FAILURE; 05571 05572 05573 // save surface partitions 05574 05575 set_list.clean_out(); 05576 for( i = surface_list.size(); i--; ) 05577 { 05578 SubSurface* surf = dynamic_cast<SubSurface*>(surface_list.get_and_step()); 05579 if( surf ) 05580 set_list.append( &(surf->sub_entity_set()) ); 05581 } 05582 set_list.uniquify_ordered(); 05583 for( i = set_list.size(); i--; ) 05584 if( ! set_list.get_and_step()->save_geometry() ) 05585 result = CUBIT_FAILURE; 05586 05587 05588 // save volume partitions 05589 05590 set_list.clean_out(); 05591 for( i = lump_list.size(); i--; ) 05592 { 05593 PartitionLump* lump = dynamic_cast<PartitionLump*>(lump_list.get_and_step()); 05594 if( lump ) 05595 set_list.append( &(lump->sub_entity_set()) ); 05596 } 05597 set_list.uniquify_ordered(); 05598 for( i = set_list.size(); i--; ) 05599 if( ! set_list.get_and_step()->save_geometry() ) 05600 result = CUBIT_FAILURE; 05601 } 05602 05603 // replace partitions in passed list with the real 05604 // entities they partition 05605 05606 PartitionEntity* p_ent = 0; 05607 list.last() ; 05608 for ( i = list.size(); i--; ) 05609 { 05610 if( (p_ent = dynamic_cast<PartitionEntity*>(list.step_and_get())) ) 05611 { 05612 if( list.is_in_list(p_ent->partitioned_entity()) ) 05613 list.change_to(0); 05614 else 05615 list.change_to(p_ent->partitioned_entity()); 05616 } 05617 } 05618 list.remove_all_with_value(0); 05619 05620 return result; 05621 } 05622 05623 05624 //------------------------------------------------------------------------- 05625 // Purpose : Restore form attributes 05626 // 05627 // Special Notes : 05628 // 05629 // Creator : Jason Kraftcheck 05630 // 05631 // Creation Date : 01/23/03 05632 //------------------------------------------------------------------------- 05633 CubitStatus PartitionEngine::import_geometry( DLIList<TopologyBridge*>& list ) 05634 { 05635 int i; 05636 CubitStatus result = CUBIT_SUCCESS; 05637 05638 DLIList<Curve*> curve_list, temp_curves; 05639 DLIList<Surface*> surface_list, temp_surfaces; 05640 DLIList<Lump*> lump_list, temp_lumps; 05641 DLIList<BodySM*> body_list; 05642 05643 CAST_LIST( list, curve_list, Curve ); 05644 CAST_LIST( list, surface_list, Surface ); 05645 CAST_LIST( list, lump_list, Lump ); 05646 CAST_LIST( list, body_list, BodySM ); 05647 05648 for( i = body_list.size(); i--; ) 05649 { 05650 temp_lumps.clean_out(); 05651 body_list.get_and_step()->lumps( temp_lumps ); 05652 lump_list += temp_lumps; 05653 } 05654 05655 for( i = lump_list.size(); i--; ) 05656 { 05657 temp_surfaces.clean_out(); 05658 lump_list.get_and_step()->surfaces( temp_surfaces ); 05659 surface_list += temp_surfaces; 05660 } 05661 05662 for( i = surface_list.size(); i--; ) 05663 { 05664 temp_curves.clean_out(); 05665 surface_list.get_and_step()->curves( temp_curves ); 05666 curve_list += temp_curves; 05667 } 05668 05669 05670 if ( CGMApp::instance()->attrib_manager()->auto_actuate_flag(CA_PARTITION_VG) && 05671 CGMApp::instance()->attrib_manager()->auto_read_flag(CA_PARTITION_VG) ) 05672 { 05673 05674 curve_list.uniquify_ordered(); 05675 for( i = curve_list.size(); i--; ) 05676 if( ! restore_from_attrib( curve_list.get_and_step() ) ) 05677 result = CUBIT_FAILURE; 05678 05679 surface_list.uniquify_ordered(); 05680 for( i = surface_list.size(); i--; ) 05681 if( ! restore_from_attrib( surface_list.get_and_step() ) ) 05682 result = CUBIT_FAILURE; 05683 05684 lump_list.uniquify_ordered(); 05685 for( i = lump_list.size(); i--; ) 05686 if( ! restore_from_attrib( lump_list.get_and_step() ) ) 05687 result = CUBIT_FAILURE; 05688 05689 // update imported list 05690 list.last(); 05691 DLIList<PartitionEntity*> entity_list; 05692 DLIList<TopologyBridge*> temp_list; 05693 for( i = list.size(); i--; ) 05694 { 05695 TopologyBridge* bridge = list.step_and_get(); 05696 SubEntitySet* set = dynamic_cast<SubEntitySet*>(bridge->owner()); 05697 if( !set ) continue; 05698 05699 entity_list.clean_out(); 05700 temp_list.clean_out(); 05701 set->get_sub_entities( entity_list ); 05702 CAST_LIST( entity_list, temp_list, TopologyBridge ); 05703 05704 temp_list.reset(); 05705 list.change_to( temp_list.get_and_step() ); 05706 for( int j = temp_list.size(); j > 1; j-- ) 05707 list.append( temp_list.get_and_step() ); 05708 } 05709 } 05710 else 05711 { 05712 curve_list.uniquify_ordered(); 05713 surface_list.uniquify_ordered(); 05714 lump_list.uniquify_ordered(); 05715 05716 DLIList<TopologyBridge*> point_list(curve_list.size()*2), tmp_points(2); 05717 for ( i = curve_list.size(); i--; ) 05718 { 05719 tmp_points.clean_out(); 05720 curve_list.get()->get_children(tmp_points); 05721 point_list += tmp_points; 05722 SubEntitySet::strip_attributes( curve_list.get_and_step() ); 05723 } 05724 point_list.uniquify_ordered(); 05725 for ( i = point_list.size(); i--; ) 05726 SubEntitySet::strip_attributes( point_list.get_and_step() ); 05727 for ( i = surface_list.size(); i--; ) 05728 SubEntitySet::strip_attributes( surface_list.get_and_step() ); 05729 for ( i = lump_list.size(); i--; ) 05730 SubEntitySet::strip_attributes( lump_list.get_and_step() ); 05731 } 05732 05733 return result; 05734 } 05735 /* 05736 void PartitionEngine::destroy_facet( CubitFacetData* facet ) 05737 { 05738 int i; 05739 05740 for( i = 0; i < 3; i++ ) 05741 { 05742 CubitFacetEdgeData* edge = dynamic_cast<CubitFacetEdgeData*>(facet->edge(i)); 05743 if( edge ) 05744 { 05745 facet->edge(0, i); 05746 if( edge->number_tris() == 0 ) 05747 delete edge; 05748 } 05749 } 05750 05751 for( i = 0; i < 3; i++ ) 05752 { 05753 CubitPointData* point = dynamic_cast<CubitPointData*>(facet->point(0)); 05754 assert(point); 05755 point->remove_facet( facet ); 05756 if( point->num_adj_facets() == 0 ) 05757 delete point; 05758 } 05759 05760 delete facet; 05761 } 05762 */ 05763 //------------------------------------------------------------------------- 05764 // Purpose : Core functionality of make_body( X* ) methods. 05765 // 05766 // Special Notes : 05767 // 05768 // Creator : Jason Kraftcheck 05769 // 05770 // Creation Date : 02/23/03 05771 //------------------------------------------------------------------------- 05772 PartitionBody* PartitionEngine::make_body_internal( TopologyBridge* bridge ) 05773 { 05774 // query topology for BodySM 05775 DLIList<TopologyBridge*> list; 05776 BodySM* body; 05777 while( !(body = dynamic_cast<BodySM*>(bridge)) ) 05778 { 05779 list.clean_out(); 05780 bridge->get_parents_virt(list); 05781 if( !list.size() ) 05782 return 0; 05783 bridge = list.get(); 05784 } 05785 05786 SubEntitySet* set = dynamic_cast<SubEntitySet*>(body->owner()); 05787 if( set ) 05788 return set->body(); 05789 05790 PartitionBody* result = new PartitionBody(body); 05791 if( body->owner() ) 05792 body->owner()->swap_bridge( body, result, false ); 05793 body->owner( &(result->sub_entity_set()) ); 05794 return result; 05795 } 05796 05797 //------------------------------------------------------------------------- 05798 // Purpose : Find or make an owning bodySM 05799 // 05800 // Special Notes : 05801 // 05802 // Creator : Jason Kraftcheck 05803 // 05804 // Creation Date : 02/23/03 05805 //------------------------------------------------------------------------- 05806 PartitionBody* PartitionEngine::make_body( PartitionLump* lump ) 05807 { 05808 if( lump->get_body() ) 05809 return lump->get_body(); 05810 05811 return make_body_internal( lump ); 05812 } 05813 05814 //------------------------------------------------------------------------- 05815 // Purpose : Find or make an owning bodySM 05816 // 05817 // Special Notes : 05818 // 05819 // Creator : Jason Kraftcheck 05820 // 05821 // Creation Date : 02/23/03 05822 //------------------------------------------------------------------------- 05823 PartitionBody* PartitionEngine::make_body( PartitionSurface* surf ) 05824 { 05825 if( surf->sub_entity_set().body() ) 05826 return surf->sub_entity_set().body(); 05827 05828 if( surf->next_co_surface(0) ) 05829 return make_body(surf->next_co_surface(0)->get_shell()->get_lump()); 05830 05831 return make_body_internal(surf); 05832 } 05833 05834 //------------------------------------------------------------------------- 05835 // Purpose : Find or make an owning bodySM 05836 // 05837 // Special Notes : 05838 // 05839 // Creator : Jason Kraftcheck 05840 // 05841 // Creation Date : 02/23/03 05842 //------------------------------------------------------------------------- 05843 PartitionBody* PartitionEngine::make_body( PartitionCurve* curve ) 05844 { 05845 if( curve->sub_entity_set().body() ) 05846 return curve->sub_entity_set().body(); 05847 05848 PartitionCoEdge* coedge = 0; 05849 while( (coedge = curve->next_coedge(coedge)) ) 05850 if( coedge->get_loop() ) 05851 return make_body(coedge->get_loop()->get_surface()); 05852 05853 return make_body_internal(curve); 05854 } 05855 05856 //------------------------------------------------------------------------- 05857 // Purpose : Find or make an owning bodySM 05858 // 05859 // Special Notes : 05860 // 05861 // Creator : Jason Kraftcheck 05862 // 05863 // Creation Date : 02/23/03 05864 //------------------------------------------------------------------------- 05865 PartitionBody* PartitionEngine::make_body( PartitionPoint* pt ) 05866 { 05867 if( pt->sub_entity_set().body() ) 05868 return pt->sub_entity_set().body(); 05869 05870 if( pt->next_curve(0) ) 05871 return make_body(pt->next_curve(0)); 05872 05873 return make_body_internal(pt); 05874 } 05875 static CubitStatus get_edge_replacements( 05876 std::vector<CubitFacetData*> &facet_list, 05877 std::vector<CubitFacetEdgeData*> replace_edge_lists[3]) 05878 { 05879 // first facet is the facet to replace 05880 // make sure more than one facet to replace the first 05881 assert(facet_list.size() > 2); 05882 05883 // make sure the lists of replacement edges are empty 05884 assert(replace_edge_lists[0].size() == 0); 05885 assert(replace_edge_lists[1].size() == 0); 05886 assert(replace_edge_lists[2].size() == 0); 05887 05888 05889 CubitFacetData* p_dead = facet_list[0]; // facet to be replaced 05890 05891 // look for edges on the facet that are owned by curves 05892 int i; 05893 //int replace_edge = 0; 05894 05895 // get the edges 05896 CubitFacetEdgeData *edges[3]; 05897 for (i=0; i<3; i++) 05898 { 05899 edges[i] = CAST_TO(p_dead->edge(i), CubitFacetEdgeData); 05900 assert(edges[i] != NULL); 05901 } 05902 05903 PartitionEntity *p_owner; 05904 PartitionCurve *p_curve; 05905 05906 // see if any are owned by a curve 05907 CubitBoolean b_boundary = CUBIT_FALSE; 05908 for (i=0; i<3 && !b_boundary; i++) 05909 { 05910 p_owner = TDVGFacetOwner::get(edges[i]); 05911 p_curve = CAST_TO(p_owner, PartitionCurve); 05912 if (p_curve) 05913 b_boundary = CUBIT_TRUE; 05914 } 05915 05916 // if the facet has an edge on a curve, replace the edge with the edges of the 05917 // replacement facets and split the facet on the adjacent surface. 05918 if (b_boundary) 05919 { 05920 // make a list with just the new facets -- skip the first facet 05921 DLIList<CubitFacet*> new_facets(facet_list.size() - 1); 05922 for (unsigned u = 1; u < facet_list.size(); u++) 05923 new_facets.append(facet_list[u]); 05924 05925 // get a point edge chain around the boundary of the replacement facets 05926 DLIList<FacetEntity*> point_edge_chain; 05927 FacetDataUtil::ordered_point_edge_bdry(new_facets, point_edge_chain); 05928 05929 // for each edge on a curve get corresponding points and edges from the 05930 // replacement facets 05931 //std::vector<CubitFacetEdgeData*>::iterator eitor; 05932 for (i=0; i<3; i++) 05933 { 05934 p_owner = TDVGFacetOwner::get(edges[i]); 05935 p_curve = CAST_TO(p_owner, PartitionCurve); 05936 if (p_curve) 05937 { 05938 // fill the replacement list for this edge 05939 // add the edge to be replaced first 05940 //eitor = replace_edge_lists[i].begin(); 05941 05942 // get the points from the edge of the dead facet - in the correct order 05943 CubitPoint* pt1; 05944 CubitPoint* pt2; 05945 05946 p_dead->get_edge_pts(i, pt1, pt2); 05947 05948 // get the corresponding chain of points and edges from the replacement facets 05949 DLIList<FacetEntity*> replacement_chain; 05950 CubitStatus res = FacetDataUtil::partial_chain(point_edge_chain, 05951 pt1, pt2, replacement_chain); 05952 if (CUBIT_FAILURE == res) 05953 return CUBIT_FAILURE; 05954 05955 // there should be an odd number of list entries, since it includes points 05956 // and edges, beginning and ending with a point 05957 assert( (replacement_chain.size() % 2) == 1 ); 05958 05959 // if only one replacement edge, it should be the same edge 05960 replacement_chain.reset(); 05961 if (replacement_chain.size() == 3) 05962 { 05963 assert(replacement_chain.next(1) == edges[i]); 05964 } 05965 else 05966 { 05967 // add the replacement edges to the list - edge to replace first 05968 //*eitor++ = edges[i]; 05969 replace_edge_lists[i].push_back(edges[i]); 05970 int j; 05971 CubitFacetEdgeData* p_edge; 05972 for (j=1; j<replacement_chain.size(); j+=2) 05973 { 05974 //replacement_chain.step(); 05975 p_edge = CAST_TO(replacement_chain.next(j), CubitFacetEdgeData); 05976 assert(p_edge != NULL); 05977 //*eitor++ = p_edge; 05978 replace_edge_lists[i].push_back(p_edge); 05979 } 05980 } 05981 } 05982 } 05983 } 05984 05985 return CUBIT_SUCCESS; 05986 } 05987 05988 //------------------------------------------------------------------------- 05989 // Purpose : clean up for deleted geometry 05990 // 05991 // Special Notes : 05992 // 05993 // Creator : Jason Kraftcheck 05994 // 05995 // Creation Date : 04/03/03 05996 //------------------------------------------------------------------------- 05997 CubitStatus PartitionEngine::delete_solid_model_entities( 05998 PartitionBody* body, BodySM*& real_body ) 05999 { 06000 real_body = body->real_body(); 06001 body->destroy_all_children(); 06002 return CUBIT_SUCCESS; 06003 } 06004 06005 CubitStatus PartitionEngine::delete_solid_model_entities( 06006 PartitionSurface* surf, 06007 Surface*& real_surf ) 06008 { 06009 DLIList<TopologyBridge*> parents(0); 06010 surf->get_parents_virt(parents); 06011 if ( parents.size() ) 06012 return CUBIT_FAILURE; 06013 06014 real_surf = 0; 06015 if ( !surf->sub_entity_set().has_multiple_sub_entities() ) 06016 real_surf = dynamic_cast<Surface*>(surf->partitioned_entity()); 06017 destroy_surface(surf); 06018 return CUBIT_SUCCESS; 06019 } 06020 06021 CubitStatus PartitionEngine::delete_solid_model_entities( 06022 PartitionCurve* curve, 06023 Curve*& real_curve ) 06024 { 06025 if( curve->next_coedge(0) ) 06026 return CUBIT_FAILURE; 06027 06028 real_curve = 0; 06029 if ( !curve->sub_entity_set().has_multiple_sub_entities() ) 06030 real_curve = dynamic_cast<Curve*>(curve->partitioned_entity()); 06031 PartitionPoint* start = curve->start_point(); 06032 PartitionPoint* end = curve->end_point(); 06033 delete curve; 06034 if ( start->num_curves() == 0 ) 06035 delete start; 06036 if ( end->num_curves() == 0 ) 06037 delete end; 06038 return CUBIT_SUCCESS; 06039 } 06040 06041 CubitStatus PartitionEngine::translate( PartitionEntity* ent, 06042 const CubitVector& delta ) 06043 { 06044 GeometryEntity* geom = dynamic_cast<GeometryEntity*>(ent->partitioned_entity()); 06045 if (!geom->get_geometry_query_engine()->translate( geom, delta )) 06046 return CUBIT_FAILURE; 06047 06048 CubitTransformMatrix xform; 06049 xform.translate( delta ); 06050 notify_transform_internal( geom, xform ); 06051 return CUBIT_SUCCESS; 06052 } 06053 06054 CubitStatus PartitionEngine::rotate( PartitionEntity* ent, 06055 const CubitVector& axis, 06056 double degrees ) 06057 { 06058 GeometryEntity* geom = dynamic_cast<GeometryEntity*>(ent->partitioned_entity()); 06059 if (!geom->get_geometry_query_engine()->rotate( geom, axis, degrees )) 06060 return CUBIT_FAILURE; 06061 06062 CubitTransformMatrix xform; 06063 xform.rotate( degrees, axis ); 06064 notify_transform_internal( geom, xform ); 06065 return CUBIT_SUCCESS; 06066 } 06067 06068 CubitStatus PartitionEngine::scale( PartitionEntity* ent, 06069 const CubitVector& factors ) 06070 { 06071 GeometryEntity* geom = dynamic_cast<GeometryEntity*>(ent->partitioned_entity()); 06072 if (!geom->get_geometry_query_engine()->scale( geom, factors )) 06073 return CUBIT_FAILURE; 06074 06075 CubitTransformMatrix xform; 06076 xform.scale_about_origin( factors ); 06077 notify_transform_internal( geom, xform ); 06078 return CUBIT_SUCCESS; 06079 } 06080 06081 CubitStatus PartitionEngine::reflect( PartitionEntity* ent, 06082 const CubitVector& axis ) 06083 { 06084 GeometryEntity* geom = dynamic_cast<GeometryEntity*>(ent->partitioned_entity()); 06085 if (!geom->get_geometry_query_engine()->reflect( geom, axis )) 06086 return CUBIT_FAILURE; 06087 06088 CubitTransformMatrix xform; 06089 xform.reflect( axis ); 06090 notify_transform_internal( geom, xform ); 06091 return CUBIT_SUCCESS; 06092 } 06093 06094 CubitStatus PartitionEngine::translate( PartitionBody* ent, 06095 const CubitVector& delta ) 06096 { 06097 BodySM* body = ent->real_body(); 06098 if (!body->get_geometry_query_engine()->translate( body, delta )) 06099 return CUBIT_FAILURE; 06100 06101 CubitTransformMatrix xform; 06102 xform.translate( delta ); 06103 notify_transform_internal( ent, xform ); 06104 return CUBIT_SUCCESS; 06105 } 06106 06107 CubitStatus PartitionEngine::rotate( PartitionBody* ent, 06108 const CubitVector& axis, 06109 double degrees ) 06110 { 06111 BodySM* body = ent->real_body(); 06112 if (!body->get_geometry_query_engine()->rotate( body, axis, degrees )) 06113 return CUBIT_FAILURE; 06114 06115 CubitTransformMatrix xform; 06116 xform.rotate( degrees, axis ); 06117 notify_transform_internal( ent, xform ); 06118 return CUBIT_SUCCESS; 06119 } 06120 06121 CubitStatus PartitionEngine::scale( PartitionBody* ent, 06122 const CubitVector& factors ) 06123 { 06124 BodySM* body = ent->real_body(); 06125 06126 if( factors.x() != factors.y() || 06127 factors.y() != factors.z() || 06128 factors.x() != factors.z() ) 06129 { 06130 GeometryModifyEngine *tmp_engine = GeometryModifyTool::instance()->get_engine( body ); 06131 tmp_engine->scale( body, factors ); 06132 } 06133 else if(!body->get_geometry_query_engine()->scale( body, factors )) 06134 return CUBIT_FAILURE; 06135 06136 CubitTransformMatrix xform; 06137 xform.scale_about_origin( factors ); 06138 notify_transform_internal( ent, xform ); 06139 return CUBIT_SUCCESS; 06140 } 06141 06142 CubitStatus PartitionEngine::reflect( PartitionBody* ent, 06143 const CubitVector& axis ) 06144 { 06145 BodySM* body = ent->real_body(); 06146 if (!body->get_geometry_query_engine()->reflect( body, axis )) 06147 return CUBIT_FAILURE; 06148 06149 CubitTransformMatrix xform; 06150 xform.reflect( axis ); 06151 notify_transform_internal( ent, xform ); 06152 return CUBIT_SUCCESS; 06153 } 06154 06155 CubitStatus PartitionEngine::restore_transform( PartitionBody* ent ) 06156 { 06157 BodySM* body = ent->real_body(); 06158 CubitTransformMatrix xform; 06159 body->get_transforms( xform ); 06160 if (!body->get_geometry_query_engine()->restore_transform( body )) 06161 return CUBIT_FAILURE; 06162 06163 notify_transform_internal( ent, xform ); 06164 return CUBIT_SUCCESS; 06165 } 06166 06167 CubitStatus PartitionEngine::notify_transform( TopologyBridge* , 06168 const CubitTransformMatrix& ) 06169 { 06170 return CUBIT_SUCCESS; 06171 } 06172 06173 CubitStatus PartitionEngine::notify_transform_internal( TopologyBridge* ent, 06174 const CubitTransformMatrix& xform ) 06175 { 06176 int i; 06177 DLIList<Surface*> surfaces; 06178 DLIList<Curve*> curves; 06179 DLIList<TBPoint*> points; 06180 06181 if (PartitionBody* body = dynamic_cast<PartitionBody*>(ent)) 06182 { 06183 DLIList<PartitionEntity*> ent_list; 06184 body->get_all_children( ent_list ); 06185 CAST_LIST( ent_list, surfaces, PartitionSurface ); 06186 CAST_LIST( ent_list, curves, PartitionCurve ); 06187 CAST_LIST( ent_list, points, PartitionPoint ); 06188 } 06189 else 06190 { 06191 if(BodySM* bodysm = dynamic_cast<BodySM*>(ent)) 06192 { 06193 DLIList<TopologyBridge*> lumps, shells, tmp_surfs; 06194 bodysm->get_children( lumps, true, layer() ); 06195 while (lumps.size()) 06196 { 06197 lumps.pop()->get_children( shells, true, layer() ); 06198 while (shells.size()) 06199 { 06200 tmp_surfs.clean_out(); 06201 shells.pop()->get_children( tmp_surfs, true, layer() ); 06202 while (tmp_surfs.size()) 06203 surfaces.append( dynamic_cast<Surface*>(tmp_surfs.pop()) ); 06204 } 06205 } 06206 surfaces.uniquify_ordered(); 06207 } 06208 else if(Surface* surf = dynamic_cast<Surface*>(ent)) 06209 surfaces.append( surf ); 06210 else if(Curve* curv = dynamic_cast<Curve*>(ent)) 06211 curves.append( curv ); 06212 else if(TBPoint* point = dynamic_cast<TBPoint*>(ent)) 06213 points.append( point ); 06214 06215 if (surfaces.size()) 06216 { 06217 DLIList<TopologyBridge*> loops, coedges, tmp_curves; 06218 for (i = surfaces.size(); i--; ) 06219 { 06220 surfaces.get_and_step()->get_children( loops, true, layer() ); 06221 while( loops.size() ) 06222 { 06223 loops.pop()->get_children( coedges, true, layer() ); 06224 while (coedges.size()) 06225 { 06226 coedges.pop()->get_children( tmp_curves, true, layer() ); 06227 while (tmp_curves.size()) 06228 curves.append( dynamic_cast<Curve*>(tmp_curves.pop()) ); 06229 } 06230 } 06231 } 06232 curves.uniquify_ordered(); 06233 } 06234 06235 if (curves.size()) 06236 { 06237 DLIList<TopologyBridge*> tmp_points; 06238 for (i = curves.size(); i--; ) 06239 { 06240 curves.get_and_step()->get_children( tmp_points, true, layer() ); 06241 while (tmp_points.size()) 06242 points.append( dynamic_cast<TBPoint*>(tmp_points.pop()) ); 06243 } 06244 points.uniquify_ordered(); 06245 } 06246 } 06247 06248 // see if the transformation is a reflection 06249 double det = xform.sub_matrix( 3, 3 ).determinant(); 06250 bool reflection = det < 0.0; 06251 06252 while (surfaces.size()) 06253 { 06254 PartitionSurface* surf = dynamic_cast<PartitionSurface*>(surfaces.pop()); 06255 if (surf) 06256 { 06257 surf->transform( xform ); 06258 } 06259 } 06260 06261 while (curves.size()) 06262 { 06263 PartitionCurve* curv = dynamic_cast<PartitionCurve*>(curves.pop()); 06264 if (curv) 06265 { 06266 curv->transform( xform ); 06267 06268 if (reflection) 06269 { 06270 // PartitionSurface transform above reverses loops and coedges on Partition 06271 // surfaces. Need to reverse sense of PartitionCoEdges in loops on non 06272 // partition surfaces 06273 // reverse the coedges of this curve 06274 PartitionCoEdge* p_coedge = 0; 06275 while ((p_coedge = curv->next_coedge(p_coedge)) != NULL) 06276 { 06277 TopologyBridge* loop_bridge = p_coedge->find_parent_loop(); 06278 if (loop_bridge) 06279 { 06280 if (0 == dynamic_cast<PartitionLoop*>(loop_bridge)) 06281 { 06282 p_coedge->reverse_sense(); 06283 } 06284 } 06285 } 06286 } 06287 } 06288 } 06289 06290 while (points.size()) 06291 { 06292 PartitionPoint* pnt = dynamic_cast<PartitionPoint*>(points.pop()); 06293 if (pnt) 06294 pnt->transform( xform ); 06295 } 06296 06297 return CUBIT_SUCCESS; 06298 } 06299 06300 void PartitionEngine::remove_attributes( DLIList<TopologyBridge*> &list ) 06301 { 06302 //for each SubEntitySet in map, change it's unique id to zero 06303 std::map<int,SubEntitySet*>::iterator itor = uniqueIdMap.begin(); 06304 while( itor != uniqueIdMap.end() ) 06305 { 06306 if(itor->second->get_entity()) 06307 { 06308 SubEntitySet::strip_attributes( itor->second->get_entity() ); 06309 itor->second->reset_unique_id(); 06310 } 06311 itor++; 06312 } 06313 06314 //clean out the map 06315 uniqueIdMap.clear(); 06316 } 06317 06318 void PartitionEngine::notify_deactivated (PartitionBody* body) 06319 { 06320 } 06321 void PartitionEngine::notify_deactivated(PartitionLump* vol) 06322 { 06323 } 06324 void PartitionEngine::add_to_deactivated_list(PartitionLump* vol) 06325 { 06326 } 06327 void PartitionEngine::add_to_deactivated_list(PartitionBody* body) 06328 { 06329 } 06330 void PartitionEngine::notify_deactivated (PartitionSurface* surface) 06331 { 06332 } 06333 void PartitionEngine::add_to_deactivated_list (PartitionSurface* surface) 06334 { 06335 } 06336 void PartitionEngine::notify_deactivated (PartitionCurve* curve) 06337 { 06338 } 06339 void PartitionEngine::add_to_deactivated_list (PartitionCurve* curve) 06340 { 06341 } 06342 void PartitionEngine::notify_deactivated (PartitionPoint* point) 06343 { 06344 } 06345 void PartitionEngine::add_to_deactivated_list (PartitionPoint* point) 06346 { 06347 } 06348 void PartitionEngine::clean_out_deactivated_geometry() 06349 { 06350 } 06351 void PartitionEngine::remove_modified(DLIList<Surface*> &all_surfs, 06352 DLIList<Curve*> &all_curves, DLIList<TBPoint*> &all_pts) 06353 { 06354 } 06355 06356 void PartitionEngine::get_tbs_with_bridge_manager_as_owner( TopologyBridge *source_bridge, 06357 DLIList<TopologyBridge*> &tbs ) 06358 { 06359 BridgeManager* bm = dynamic_cast<BridgeManager*>(source_bridge->owner()); 06360 if( bm ) 06361 { 06362 tbs.append( source_bridge ); 06363 return; 06364 } 06365 06366 SubEntitySet* set = dynamic_cast<SubEntitySet*>(source_bridge->owner()); 06367 if( !set ) 06368 return; 06369 06370 DLIList<PartitionEntity*> entity_list; 06371 set->get_sub_entities( entity_list ); 06372 DLIList<TopologyBridge*> tb_list; 06373 CAST_LIST( entity_list, tb_list, TopologyBridge ); 06374 06375 while( tb_list.size() ) 06376 { 06377 TopologyBridge *tb = tb_list.pop(); 06378 if( tb->bridge_manager() ) 06379 tbs.append( tb ); 06380 else 06381 { 06382 TBOwner *owner = tb->owner(); 06383 TopologyBridge *tmp_tb = CAST_TO( owner, TopologyBridge ); 06384 if( tmp_tb ) 06385 tb_list.append( tmp_tb ); 06386 else 06387 { 06388 CompositePoint *comp_pt = CAST_TO( tb, CompositePoint ); 06389 if( comp_pt ) 06390 CompositeEngine::instance().get_tbs_with_bridge_manager_as_owner( tb, tb_list ); 06391 else 06392 { 06393 CompositeCurve *comp_curve = CAST_TO( tb, CompositeCurve ); 06394 if( comp_curve ) 06395 CompositeEngine::instance().get_tbs_with_bridge_manager_as_owner( tb, tb_list ); 06396 } 06397 } 06398 } 06399 } 06400 06401 tbs.uniquify_ordered(); 06402 06403 return; 06404 } 06405