cgma
|
00001 #include "PartitionLump.hpp" 00002 #include "PartitionSurface.hpp" 00003 #include "PartitionLoop.hpp" 00004 #include "PartitionShell.hpp" 00005 #include "PartitionCurve.hpp" 00006 #include "VirtualQueryEngine.hpp" 00007 #include "PartitionEngine.hpp" 00008 #include "PartSurfFacetTool.hpp" 00009 #include "PartitionTool.hpp" 00010 00011 #include "CubitFacetData.hpp" 00012 #include "TDVGFacetOwner.hpp" 00013 #include "GMem.hpp" 00014 #include "CubitPoint.hpp" 00015 #include "CubitPointData.hpp" 00016 #include "CubitFacetEdgeData.hpp" 00017 #include "CubitTransformMatrix.hpp" 00018 #include "GfxDebug.hpp" 00019 00020 #include "RefVertex.hpp" 00021 00022 void PartitionSurface::draw_facets( int color ) const 00023 { 00024 DLIList<CubitFacetData*> facets; 00025 get_facet_data(facets); 00026 int i; 00027 for ( i = facets.size(); i--; ) { 00028 CubitFacet* facet = facets.step_and_get(); 00029 for ( int j = 0; j < 3; j++ ) 00030 if ( facet->edge(j) ) 00031 facet->edge(j)->marked(0); 00032 } 00033 for ( i = facets.size(); i--; ) { 00034 CubitFacet* facet = facets.step_and_get(); 00035 for ( int j = 0; j < 3; j++ ) 00036 if ( facet->edge(j) ) 00037 facet->edge(j)->marked(facet->edge(j)->marked()+1); 00038 } 00039 00040 00041 for ( i = facets.size(); i--; ) { 00042 CubitFacetData* facet = facets.step_and_get(); 00043 CubitVector pts[3] = {facet->point(0)->coordinates(), 00044 facet->point(1)->coordinates(), 00045 facet->point(2)->coordinates()}; 00046 for ( int j = 0; j < 3; j++ ) 00047 { 00048 CubitVector p1 = pts[j]; 00049 CubitVector p2 = pts[(j+1)%3]; 00050 int c = color == CUBIT_RED_INDEX ? color - 1 : CUBIT_RED_INDEX; 00051 CubitFacetEdge* edge = facet->edge((j+2)%3); 00052 if (!edge) continue; 00053 00054 switch( edge->marked() ) { 00055 case 1: c = color + 1; break; 00056 case 2: c = color; break; 00057 default : c = color == CUBIT_RED_INDEX ? color - 1 : CUBIT_RED_INDEX; 00058 00059 if (edge->marked()==1 && !TDVGFacetOwner::get(edge)) 00060 PRINT_WARNING("Boundary edge in surface facetting not owned by a curve.\n"); 00061 } 00062 00063 GfxDebug::draw_line( (float)p1.x(), (float)p1.y(), (float)p1.z(), 00064 (float)p2.x(), (float)p2.y(), (float)p2.z(), c ); 00065 } 00066 00067 00068 CubitVector center = ( pts[0] + pts[1] + pts[2] ) / 3.0; 00069 CubitVector normal = (pts[1] - pts[0]) * (pts[2] - pts[0]); 00070 double len = normal.length(); 00071 if ( len > GEOMETRY_RESABS ) { 00072 normal /= sqrt(len); 00073 // if ( len > 1e-2 ) 00074 // normal /= len; 00075 // else 00076 // normal.length(1.0); 00077 00078 GfxDebug::draw_vector( center, center + normal, color ); 00079 } else { 00080 GfxDebug::draw_point( center, color + 1 ); 00081 } 00082 } 00083 GfxDebug::flush(); 00084 00085 for ( i = facets.size(); i--; ) { 00086 CubitFacet* facet = facets.step_and_get(); 00087 for ( int j = 0; j < 3; j++ ) 00088 if ( facet->edge(j) ) 00089 facet->edge(j)->marked(0); 00090 } 00091 } 00092 00093 void PartitionSurface::print_debug_info( const char* prefix , 00094 bool print_sub_entity_set ) const 00095 { 00096 if( !prefix ) prefix = ""; 00097 PRINT_INFO("%sPartitionSurface %p\n", prefix, (void*)this ); 00098 PartitionLoop* loop = 0; 00099 while( (loop = next_loop(loop)) ) 00100 { 00101 PRINT_INFO("%s Loop %p:\n", prefix, (void*)loop ); 00102 PartitionCoEdge* coedge = loop->first_coedge(); 00103 do 00104 { 00105 PRINT_INFO("%s CoEdge %p %s -> Curve %p\n", 00106 prefix, (void*)coedge, coedge->sense() == CUBIT_FORWARD ? "FORWARD" : 00107 coedge->sense() == CUBIT_REVERSED ? "REVERSE" : 00108 "UNKNOWN", (void*)coedge->get_curve() ); 00109 coedge = loop->next_coedge(coedge); 00110 } while( coedge != loop->first_coedge() ); 00111 } 00112 00113 char buffer[128]; 00114 sprintf(buffer,"%s ",prefix); 00115 if( print_sub_entity_set ) 00116 sub_entity_set().print_debug_info(buffer); 00117 } 00118 00119 PartitionSurface::PartitionSurface() 00120 : geometry_sense(CUBIT_FORWARD), firstLoop(0), firstCoSurf(0) 00121 {} 00122 00123 PartitionSurface::PartitionSurface( PartitionLump* lump ) 00124 : geometry_sense(CUBIT_FORWARD), firstLoop(0), firstCoSurf(0) 00125 { 00126 lump->sub_entity_set().add_lower_order( this ); 00127 } 00128 00129 PartitionSurface::~PartitionSurface() 00130 { 00131 while( firstLoop ) 00132 remove( firstLoop ); 00133 00134 while( firstCoSurf ) 00135 { 00136 PartitionCoSurf* cos = firstCoSurf; 00137 if( cos->get_shell() ) 00138 cos->get_shell()->remove( cos ); 00139 remove( cos ); 00140 delete cos; 00141 assert( firstCoSurf != cos ); 00142 } 00143 00144 // delete facets 00145 DLIList<CubitPoint*> facet_points(3); 00146 DLIList<CubitFacetEdge*> facet_edges(3); 00147 while( facetList.size() ) 00148 { 00149 CubitFacet* facet = facetList.pop(); 00150 facet_edges.clean_out(); 00151 facet->edges(facet_edges); 00152 facet_points.clean_out(); 00153 facet->points(facet_points); 00154 TDVGFacetOwner::remove(facet); 00155 delete facet; 00156 00157 PartitionCurve* curve; 00158 while( facet_edges.size() ) 00159 { 00160 CubitFacetEdge* edge = facet_edges.pop(); 00161 if( edge && !edge->num_adj_facets() ) { 00162 if ( TDVGFacetOwner::get(edge) ) { 00163 curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(edge)); 00164 curve->remove_facet_data(); 00165 } 00166 delete edge; 00167 } 00168 } 00169 00170 PartitionPoint* ppoint; 00171 while( facet_points.size() ) 00172 { 00173 CubitPoint* point = facet_points.pop(); 00174 if( point && !point->num_adj_facets() ) { 00175 if ( TDVGFacetOwner::get(point) ) { 00176 ppoint = dynamic_cast<PartitionPoint*>(TDVGFacetOwner::get(point)); 00177 if( ppoint ) 00178 ppoint->facet_point(0); 00179 } 00180 delete point; 00181 } 00182 } 00183 } 00184 } 00185 00186 CubitStatus PartitionSurface::add( PartitionLoop* loop ) 00187 { 00188 if( loop->mySurface ) 00189 return CUBIT_FAILURE; 00190 00191 loop->mySurface = this; 00192 loop->nextInSurface = firstLoop; 00193 firstLoop = loop; 00194 return CUBIT_SUCCESS; 00195 } 00196 00197 00198 CubitStatus PartitionSurface::remove( PartitionLoop* loop ) 00199 { 00200 if( loop->mySurface != this ) 00201 return CUBIT_FAILURE; 00202 00203 if( firstLoop == loop ) 00204 { 00205 firstLoop = loop->nextInSurface; 00206 } 00207 else 00208 { 00209 PartitionLoop* prev = firstLoop; 00210 while( prev && prev->nextInSurface != loop ) 00211 prev = prev->nextInSurface; 00212 00213 if( !prev ) 00214 { 00215 assert(0); 00216 return CUBIT_FAILURE; 00217 } 00218 00219 prev->nextInSurface = loop->nextInSurface; 00220 } 00221 00222 loop->mySurface = 0; 00223 loop->nextInSurface = 0; 00224 return CUBIT_SUCCESS; 00225 } 00226 00227 int PartitionSurface::num_loops() const 00228 { 00229 int count = 0; 00230 for( PartitionLoop* loop = firstLoop; loop; loop = loop->nextInSurface ) 00231 count++; 00232 return count; 00233 } 00234 00235 CubitStatus PartitionSurface::add( PartitionCoSurf* cosurf ) 00236 { 00237 if( cosurf->mySurface ) 00238 return CUBIT_FAILURE; 00239 00240 cosurf->mySurface = this; 00241 cosurf->surfaceNext = firstCoSurf; 00242 firstCoSurf = cosurf; 00243 return CUBIT_SUCCESS; 00244 } 00245 00246 CubitStatus PartitionSurface::remove( PartitionCoSurf* cosurf ) 00247 { 00248 if( cosurf->mySurface != this ) 00249 return CUBIT_FAILURE; 00250 00251 if( cosurf == firstCoSurf ) 00252 { 00253 firstCoSurf = cosurf->surfaceNext; 00254 } 00255 else 00256 { 00257 PartitionCoSurf* prev = firstCoSurf; 00258 while( prev && prev->surfaceNext != cosurf ) 00259 prev = prev->surfaceNext; 00260 00261 if( !prev ) { assert(prev != NULL); return CUBIT_FAILURE; } 00262 00263 prev->surfaceNext = cosurf->surfaceNext; 00264 } 00265 00266 cosurf->mySurface = 0; 00267 cosurf->surfaceNext = 0; 00268 return CUBIT_SUCCESS; 00269 } 00270 00271 PartitionCoSurf* PartitionSurface::find_first( const PartitionShell* shell ) const 00272 { 00273 PartitionCoSurf* cos = firstCoSurf; 00274 while( cos && cos->get_shell() != shell ) 00275 cos = cos->surfaceNext; 00276 return cos; 00277 } 00278 00279 00280 PartitionCoSurf* PartitionSurface::find_first( const PartitionLump* lump ) const 00281 { 00282 PartitionCoSurf* cos = firstCoSurf; 00283 while( cos && (!cos->get_shell() || cos->get_shell()->get_lump() != lump ) ) 00284 cos = cos->surfaceNext; 00285 return cos; 00286 } 00287 00288 PartitionCoSurf* PartitionSurface::find_next( const PartitionCoSurf* prev ) const 00289 { 00290 if( prev->mySurface != this ) 00291 return 0; 00292 PartitionCoSurf* cos = prev->surfaceNext; 00293 while( cos && cos->get_shell() != prev->get_shell() ) 00294 cos = cos->surfaceNext; 00295 return cos; 00296 } 00297 00298 PartitionCoSurf* PartitionSurface::find_first( const PartitionShell* shell, 00299 CubitSense sense ) const 00300 { 00301 PartitionCoSurf* cos = firstCoSurf; 00302 while( cos && (cos->get_shell() != shell || cos->sense() != sense) ) 00303 cos = cos->surfaceNext; 00304 return cos; 00305 } 00306 00307 //------------------------------------------------------------------------- 00308 // Purpose : Get child point bridges 00309 // 00310 // Special Notes : 00311 // 00312 // Creator : Jason Kraftcheck 00313 // 00314 // Creation Date : 00315 //------------------------------------------------------------------------- 00316 void PartitionSurface::get_points( DLIList<PartitionPoint*>& list ) const 00317 { 00318 PartitionLoop* loop = 0; 00319 while ( (loop = next_loop(loop)) ) 00320 { 00321 PartitionCoEdge* coedge = loop->first_coedge(); 00322 do 00323 { 00324 PartitionCurve* curve = coedge->get_curve(); 00325 00326 list.append( curve->start_point() ); 00327 list.append( curve->end_point() ); 00328 00329 coedge = loop->next_coedge(coedge); 00330 } while( coedge != loop->first_coedge() ); 00331 } 00332 00333 list.reset(); 00334 int i; 00335 for ( i = list.size(); i--; ) 00336 list.get_and_step()->mark = 1; 00337 00338 for ( i = list.size(); i--; ) 00339 { 00340 list.back(); 00341 if( list.get()->mark ) 00342 list.get()->mark = 0; 00343 else 00344 list.change_to(0); 00345 } 00346 list.remove_all_with_value(0); 00347 } 00348 00349 00350 00351 00352 GeometryQueryEngine* PartitionSurface::get_geometry_query_engine() const 00353 { 00354 return VirtualQueryEngine::instance(); 00355 } 00356 00357 void PartitionSurface::get_children_virt( DLIList<TopologyBridge*>& list ) 00358 { 00359 for( PartitionLoop* loop = firstLoop; loop; loop = loop->nextInSurface ) 00360 list.append( loop ); 00361 } 00362 00363 void PartitionSurface::get_parents_virt( DLIList<TopologyBridge*>& result_list ) 00364 { 00365 Surface* real_surf = dynamic_cast<Surface*>(partitioned_entity()); 00366 if( ! real_surf ) 00367 { 00368 for( PartitionCoSurf* cos = firstCoSurf; cos; cos = cos->surfaceNext ) 00369 if( cos->get_shell() ) 00370 result_list.append_unique( cos->get_shell() ); 00371 } 00372 else 00373 { 00374 int i; 00375 DLIList<TopologyBridge*> real_surf_shells, tmp_list; 00376 real_surf->get_parents_virt( real_surf_shells ); 00377 00378 // get real volumes from real shells 00379 DLIList<TopologyBridge*> real_surf_vols(real_surf_shells.size()); 00380 real_surf_shells.reset(); 00381 for( i = real_surf_shells.size(); i--; ) 00382 { 00383 tmp_list.clean_out(); 00384 real_surf_shells.get_and_step()->get_parents_virt( tmp_list ); 00385 assert(tmp_list.size() == 1); 00386 real_surf_vols.append(tmp_list.get()); 00387 } 00388 00389 // replace real volumes with owning partition volumes (if any) 00390 DLIList<TopologyBridge*> vol_list(real_surf_vols.size()); 00391 real_surf_vols.reset(); 00392 for( i = real_surf_vols.size(); i--; ) 00393 { 00394 TopologyBridge* vol_bridge = real_surf_vols.get_and_step(); 00395 SubEntitySet* set = dynamic_cast<SubEntitySet*>(vol_bridge->owner()); 00396 if( set ) 00397 { 00398 tmp_list.clean_out(); 00399 set->get_owners(tmp_list); 00400 vol_list += tmp_list; 00401 } 00402 else 00403 vol_list.append(vol_bridge); 00404 } 00405 00406 // for each volume, get all child shells that are parents of this 00407 vol_list.reset(); 00408 DLIList<TopologyBridge*> vol_shells; 00409 for( i = vol_list.size(); i--; ) 00410 { 00411 vol_shells.clean_out(); 00412 vol_list.get_and_step()->get_children( vol_shells, false, layer() ); 00413 vol_shells.reset(); 00414 for( int j = vol_shells.size(); j--; ) 00415 { 00416 TopologyBridge* shell = vol_shells.get_and_step(); 00417 tmp_list.clean_out(); 00418 shell->get_children( tmp_list, false, layer() ); 00419 if( tmp_list.is_in_list(this) ) 00420 result_list.append(shell); 00421 } 00422 } 00423 } 00424 } 00425 00426 CubitSense PartitionSurface::get_shell_sense( ShellSM* shell_ptr ) const 00427 { 00428 if( PartitionShell* pshell = dynamic_cast<PartitionShell*>(shell_ptr) ) 00429 return pshell->find_sense( this ); 00430 00431 Surface* real_surf = dynamic_cast<Surface*>(partitioned_entity()); 00432 if( real_surf ) 00433 { 00434 DLIList<TopologyBridge*> list(2); 00435 real_surf->get_parents_virt( list ); 00436 if( list.is_in_list( shell_ptr ) ) 00437 return real_surf->get_shell_sense( shell_ptr ); 00438 } 00439 00440 return CUBIT_UNKNOWN; 00441 } 00442 00443 00444 void PartitionSurface::append_simple_attribute_virt(const CubitSimpleAttrib& csa) 00445 { sub_entity_set().add_attribute( this, csa ); } 00446 void PartitionSurface::remove_simple_attribute_virt(const CubitSimpleAttrib& csa) 00447 { sub_entity_set().rem_attribute( this, csa ); } 00448 void PartitionSurface::remove_all_simple_attribute_virt() 00449 { sub_entity_set().rem_all_attrib( this ); } 00450 CubitStatus PartitionSurface::get_simple_attribute(DLIList<CubitSimpleAttrib>& list) 00451 { 00452 sub_entity_set().get_attributes( this, list ); 00453 return CUBIT_SUCCESS; 00454 } 00455 CubitStatus PartitionSurface::get_simple_attribute(const CubitString& name, 00456 DLIList<CubitSimpleAttrib>& list) 00457 { 00458 sub_entity_set().get_attributes( this, name.c_str(), list ); 00459 return CUBIT_SUCCESS; 00460 } 00461 00462 void PartitionSurface::reverse_loops() 00463 { 00464 PartitionLoop* loop = 0; 00465 while( (loop = next_loop(loop)) ) 00466 loop->reverse(); 00467 } 00468 00469 CubitBox PartitionSurface::bounding_box() const 00470 { 00471 int i, j; 00472 CubitFacet* facet; 00473 for ( i = 0; i< facetList.size(); i++ ) { 00474 facet = facetList.next(i); 00475 facet->point(0)->marked(1); 00476 facet->point(1)->marked(1); 00477 facet->point(2)->marked(1); 00478 } 00479 00480 facet = facetList.get(); 00481 CubitBox result(facet->point(0)->coordinates()); 00482 facet->point(0)->marked(0); 00483 00484 for ( i = 0; i< facetList.size(); i++ ) { 00485 facet = facetList.next(i); 00486 for ( j = 0; j < 3; j++ ) { 00487 if ( facet->point(j)->marked() ) { 00488 facet->point(j)->marked(0); 00489 result |= facet->point(j)->coordinates(); 00490 } 00491 } 00492 } 00493 00494 return result; 00495 } 00496 00497 00498 00499 00500 double PartitionSurface::measure() 00501 { 00502 double result = 0.; 00503 for ( int i = facetList.size(); i--; ) 00504 result += facetList.step_and_get()->area(); 00505 return result; 00506 } 00507 00508 GeometryType PartitionSurface::geometry_type() 00509 { 00510 return FACET_SURFACE_TYPE; 00511 } 00512 00513 void PartitionSurface::closest_point_trimmed( CubitVector f, CubitVector& r ) 00514 { 00515 closest_facet( f, r ); 00516 } 00517 00518 CubitStatus PartitionSurface::closest_point_along_vector(CubitVector& from_point, 00519 CubitVector& along_vector, 00520 CubitVector& point_on_surface) 00521 { 00522 return CUBIT_FAILURE; 00523 } 00524 00525 CubitStatus PartitionSurface::get_point_normal( CubitVector &, CubitVector & ) 00526 { 00527 return CUBIT_FAILURE; 00528 } 00529 00530 CubitStatus PartitionSurface::move_to_geometry( CubitVector& pos ) 00531 { 00532 const CubitVector copy(pos); 00533 return closest_point( copy, &pos ); 00534 } 00535 00536 CubitStatus PartitionSurface::closest_point_uv_guess( 00537 CubitVector const& location, 00538 double&, double&, 00539 CubitVector* closest_location, 00540 CubitVector* unit_normal ) 00541 { 00542 return closest_point(location, closest_location, unit_normal); 00543 } 00544 00545 00546 CubitStatus PartitionSurface::closest_point( const CubitVector& position, 00547 CubitVector* closest, 00548 CubitVector* normal, 00549 CubitVector* curvature1, 00550 CubitVector* curvature2 ) 00551 { 00552 if ( closest || normal ) 00553 { 00554 CubitVector tmp_closest; 00555 CubitFacet* facet = closest_facet( position, tmp_closest ); 00556 if ( closest ) 00557 *closest = tmp_closest; 00558 if ( normal ) 00559 *normal = facet->normal(); 00560 } 00561 00562 if( curvature1 ) 00563 curvature1->set( 0.0, 0.0, 0.0 ); 00564 if( curvature2 ) 00565 curvature2->set( 0.0, 0.0, 0.0 ); 00566 00567 return CUBIT_SUCCESS; 00568 } 00569 00570 CubitStatus PartitionSurface::principal_curvatures( 00571 const CubitVector& , 00572 double&, double& , 00573 CubitVector* ) 00574 { 00575 return CUBIT_FAILURE; 00576 } 00577 00578 CubitVector PartitionSurface::position_from_u_v( double , double ) 00579 { 00580 return CubitVector(0.0,0.0,0.0); 00581 } 00582 00583 CubitStatus PartitionSurface::u_v_from_position( const CubitVector& , 00584 double&, double &, 00585 CubitVector* ) 00586 { 00587 return CUBIT_FAILURE; 00588 } 00589 00590 CubitBoolean PartitionSurface::is_periodic() 00591 { 00592 return CUBIT_FALSE; 00593 } 00594 00595 CubitBoolean PartitionSurface::is_periodic_in_U( double& ) 00596 { 00597 return CUBIT_FALSE; 00598 } 00599 00600 CubitBoolean PartitionSurface::is_periodic_in_V( double& ) 00601 { 00602 return CUBIT_FALSE; 00603 } 00604 00605 CubitBoolean PartitionSurface::is_singular_in_U( double ) 00606 { 00607 return CUBIT_FALSE; 00608 } 00609 00610 CubitBoolean PartitionSurface::is_singular_in_V( double ) 00611 { 00612 return CUBIT_FALSE; 00613 } 00614 00615 CubitBoolean PartitionSurface::is_closed_in_U() 00616 { 00617 return CUBIT_FALSE; 00618 } 00619 00620 CubitBoolean PartitionSurface::is_closed_in_V() 00621 { 00622 return CUBIT_FALSE; 00623 } 00624 00625 CubitStatus PartitionSurface::uv_derivitives( double , double , 00626 CubitVector& , 00627 CubitVector& ) 00628 { 00629 return CUBIT_FAILURE; 00630 } 00631 00632 CubitBoolean PartitionSurface::is_parametric() 00633 { 00634 return CUBIT_FALSE; 00635 } 00636 00637 CubitBoolean PartitionSurface::get_param_range_U( double& , double& ) 00638 { 00639 return CUBIT_FALSE; 00640 } 00641 00642 CubitBoolean PartitionSurface::get_param_range_V( double&, double& ) 00643 { 00644 return CUBIT_FALSE; 00645 } 00646 00647 CubitBoolean PartitionSurface::is_position_on( CubitVector& position ) 00648 { 00649 const double tolsqr = GEOMETRY_RESABS * GEOMETRY_RESABS; 00650 CubitVector closest; 00651 closest_facet( position, closest ); 00652 double distsqr = (position - closest).length_squared(); 00653 return (CubitBoolean)(distsqr < tolsqr); 00654 } 00655 00656 CubitPointContainment PartitionSurface::point_containment( const CubitVector& point ) 00657 { 00658 PartitionCurve* curve = 0; 00659 CubitPointContainment result = point_containment( point, curve ); 00660 if ( curve ) { 00661 CubitVector curve_closest; 00662 curve->closest_point( point, curve_closest ); 00663 if ( (point - curve_closest).length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS ) 00664 result = CUBIT_PNT_BOUNDARY; 00665 } 00666 return result; 00667 } 00668 00669 CubitPointContainment PartitionSurface::point_containment( const CubitVector& point, 00670 PartitionCurve*& curve ) 00671 { 00672 CubitVector facet_pos; 00673 CubitFacet* facet = closest_facet(point, facet_pos); 00674 00675 int i; 00676 double tol = 10*GEOMETRY_RESABS; 00677 int closest_edge = -1; 00678 CubitPoint* closest_point = 0; 00679 double closest_dist_sqr = CUBIT_DBL_MAX; 00680 CubitVector closest_pos; 00681 CubitFacetEdge* edge; 00682 00683 // Find closest edge/point on facet 00684 for ( i = 0; i < 3; i++ ) 00685 { 00686 edge = facet->edge(i); 00687 00688 CubitVector start = edge->point(0)->coordinates(); 00689 CubitVector end = edge->point(1)->coordinates(); 00690 CubitVector dir = end - start; 00691 double len_sqr = dir.length_squared(); 00692 double t = (dir % (point - start)) / len_sqr; 00693 double len = sqrt(len_sqr); 00694 double dist_from_start = t * len; 00695 double dist_from_end = (1.0 - t) * len; 00696 CubitPoint* facet_point = 0; 00697 CubitVector pos; 00698 if ( dist_from_start < tol ) 00699 { 00700 pos = start; 00701 facet_point = edge->point(0); 00702 } 00703 else if( dist_from_end < tol ) 00704 { 00705 pos = end; 00706 facet_point = edge->point(1); 00707 } 00708 else 00709 pos = t * dir + start; 00710 00711 double dist_sqr = (pos - point).length_squared(); 00712 if ( dist_sqr < closest_dist_sqr ) 00713 { 00714 closest_edge = i; 00715 closest_point = facet_point; 00716 closest_dist_sqr = dist_sqr; 00717 closest_pos = pos; 00718 } 00719 } 00720 00721 edge = facet->edge(closest_edge); 00722 00723 // If closest to an edge (not a point) ... 00724 if ( !closest_point ) 00725 { 00726 // If the edge is not on the boundary of the surface facets... 00727 curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(edge)); 00728 if ( !curve || curve->is_nonmanifold(this) ) 00729 return CUBIT_PNT_INSIDE; // not a boundary edge 00730 00731 // If within tolerance of boundary 00732 if ( (point - closest_pos).length_squared() < tol*tol ) 00733 return CUBIT_PNT_BOUNDARY; 00734 00735 // Check which side of the edge the point is on 00736 CubitVector dir = edge->point(1)->coordinates() - edge->point(0)->coordinates(); 00737 if ( facet->edge_use(closest_edge) == -1 ) 00738 dir = -dir; 00739 double dot = facet->normal() % ((closest_pos - point) * dir); 00740 if ( dot < 0.0 ) 00741 return CUBIT_PNT_OUTSIDE; 00742 else 00743 return CUBIT_PNT_INSIDE; 00744 } 00745 00746 00747 // Get two boundary edges adjacent to point 00748 DLIList<CubitFacetEdge*> edge_list; 00749 closest_point->edges( edge_list ); 00750 for ( i = edge_list.size(); i--; ) 00751 { 00752 edge = edge_list.step_and_get(); 00753 curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(edge)); 00754 if ( !curve || !curve->is_in_surface(this,true) ) 00755 edge_list.change_to(0); 00756 } 00757 edge_list.remove_all_with_value(0); 00758 00759 if (!edge_list.size()) 00760 return CUBIT_PNT_INSIDE; 00761 00762 if (edge_list.size() > 2) 00763 { 00764 // This is a special case. The point was closest to an 00765 // intersection of more than two curves on the surface boundary 00766 // (for example the point where a circular hole is tangent to 00767 // the boundary of the surface.). If the input position is closest 00768 // to such a point it must be outside the surface (or on the boundary). 00769 // However, a little work is required to decide which curve to pass back. 00770 DLIList<PartitionCurve*> curve_list; 00771 while (edge_list.size()) 00772 { 00773 PartitionEntity* owner = TDVGFacetOwner::get(edge_list.pop()); 00774 curve_list.append_unique( dynamic_cast<PartitionCurve*>(owner) ); 00775 } 00776 assert( !! TDVGFacetOwner::get(closest_point) ); 00777 closest_dist_sqr = CUBIT_DBL_MAX; 00778 curve = 0; 00779 while (curve_list.size()) 00780 { 00781 PartitionCurve* temp_curve = curve_list.pop(); 00782 temp_curve->closest_point( point, closest_pos ); 00783 if ( (point - closest_pos).length_squared() < closest_dist_sqr ) 00784 { 00785 curve = temp_curve; 00786 closest_dist_sqr = (point - closest_pos).length_squared(); 00787 } 00788 } 00789 00790 if ( (point - closest_point->coordinates()).length_squared() < tol*tol ) 00791 return CUBIT_PNT_BOUNDARY; 00792 else 00793 return CUBIT_PNT_OUTSIDE; 00794 } 00795 00796 00797 00798 assert(edge_list.size() == 2); 00799 CubitFacetEdge *bdy_edges[2] = {edge_list.get(), edge_list.next()}; 00800 00801 00802 // need to pass back a curve 00803 curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(bdy_edges[0])); 00804 00805 // If within tolerance of boundary 00806 if ( (point - closest_pos).length_squared() < tol*tol ) 00807 return CUBIT_PNT_BOUNDARY; 00808 00809 // Fill arrays for each of two boundary edges 00810 CubitFacet* bdy_facets[2] = {0,0}; // adjacent facet 00811 bool inside_facets[2] = {false,false}; // inside/outside of facet 00812 CubitPoint* start_pts[2], *end_pts[2]; // edge points 00813 for ( int j = 0; j < 2; j++ ) 00814 { 00815 for ( i = 0; i < bdy_edges[j]->num_adj_facets(); i++ ) 00816 { 00817 CubitFacet* facet = bdy_edges[j]->adj_facet(i); 00818 if ( TDVGFacetOwner::get(facet) == this ) 00819 { 00820 bdy_facets[j] = facet; 00821 break; 00822 } 00823 } 00824 assert(!!bdy_facets[j]); 00825 00826 int index = bdy_facets[j]->edge_index(bdy_edges[j]); 00827 if ( bdy_facets[j]->edge_use(index) < 0 ) { 00828 start_pts[j] = bdy_edges[j]->point(1); 00829 end_pts[j] = bdy_edges[j]->point(0); 00830 } else { 00831 start_pts[j] = bdy_edges[j]->point(0); 00832 end_pts[j] = bdy_edges[j]->point(1); 00833 } 00834 CubitVector dir = end_pts[j]->coordinates() - start_pts[j]->coordinates(); 00835 double dot = facet->normal() % ((closest_pos - point) * dir); 00836 inside_facets[j] = dot > 0.0; 00837 } 00838 00839 // mean normal for facets 00840 CubitVector normal = bdy_facets[0]->normal(); 00841 normal += bdy_facets[1]->normal(); 00842 00843 // cross product of edge vectors 00844 // if we had edges in wrong order, need to reverse 00845 // crossproduct 00846 CubitVector cross; 00847 CubitVector dir1 = end_pts[0]->coordinates() - start_pts[0]->coordinates(); 00848 CubitVector dir2 = end_pts[1]->coordinates() - start_pts[1]->coordinates(); 00849 if ( end_pts[0] == closest_point && start_pts[1] == closest_point ) 00850 { 00851 cross = dir1 * dir2; 00852 } 00853 else 00854 { 00855 assert( start_pts[0] == closest_point && end_pts[1] == closest_point ); 00856 cross = dir2 * dir1; 00857 } 00858 00859 bool convex = (cross % normal) > 0.0; 00860 if ( convex ) 00861 return inside_facets[0] && inside_facets[1] ? CUBIT_PNT_INSIDE : CUBIT_PNT_OUTSIDE; 00862 else 00863 return inside_facets[0] || inside_facets[1] ? CUBIT_PNT_INSIDE : CUBIT_PNT_OUTSIDE; 00864 } 00865 00866 00867 00868 00869 CubitPointContainment PartitionSurface::point_containment( double , double ) 00870 { 00871 return CUBIT_PNT_UNKNOWN; 00872 } 00873 /* 00874 CubitPointContainment PartitionSurface::point_containment( 00875 CubitVector& point, double u, double v ) 00876 { 00877 return point_containment( point ); 00878 } 00879 */ 00880 CubitSense PartitionSurface::get_geometry_sense() 00881 { 00882 return geometry_sense; 00883 } 00884 00885 void PartitionSurface::reverse_sense() 00886 { 00887 reverse_loops(); 00888 if( owner() ) 00889 owner()->notify_reversed(this); 00890 00891 if(geometry_sense == CUBIT_FORWARD) 00892 geometry_sense = CUBIT_REVERSED; 00893 else 00894 geometry_sense = CUBIT_FORWARD; 00895 00896 int j; 00897 DLIList<CubitFacetData*> surf_facets; 00898 this->get_facet_data( surf_facets ); 00899 for(j=surf_facets.size(); j--;) 00900 surf_facets.get_and_step()->flip(); 00901 } 00902 00903 PartitionSurface::PartitionSurface( PartitionSurface* split_from ) 00904 : geometry_sense(CUBIT_FORWARD), firstLoop(0), firstCoSurf(0) 00905 { 00906 split_from->sub_entity_set().add_lower_order( this ); 00907 } 00908 00909 PartitionSurface* PartitionSurface::copy() 00910 { 00911 return new PartitionSurface(this); 00912 } 00913 00914 PartitionSurface* PartitionSurface::split( DLIList<CubitFacetData*>& facets ) 00915 { 00916 int i; 00917 bool okay = true; 00918 00919 // mark facets 00920 for( i = facets.size(); i--; ) 00921 facets.get_and_step()->marked(0); 00922 for( i = facetList.size(); i--; ) 00923 facetList.get_and_step()->marked(1); 00924 00925 // make sure all facets in passed list are in my list, 00926 // and clear the marks 00927 for( i = facets.size(); i--; ) { 00928 CubitFacetData* facet = facets.get_and_step(); 00929 if( facet->marked() ) 00930 facet->marked(0); 00931 else 00932 okay = false; 00933 } 00934 00935 if (!okay) { 00936 for( i = facetList.size(); i--; ) 00937 facetList.get_and_step()->marked(0); 00938 assert(okay); 00939 return 0; 00940 } 00941 00942 for( i = facetList.size(); i--; ) { 00943 if( facetList.step_and_get()->marked() ) 00944 facetList.get()->marked(0); 00945 else 00946 facetList.change_to(0); 00947 } 00948 facetList.remove_all_with_value(0); 00949 00950 PartitionSurface* result = copy(); 00951 result->set_facet_data(facets); 00952 return result; 00953 } 00954 00955 CubitStatus PartitionSurface::combine( PartitionSurface* other_surf ) 00956 { 00957 for ( int i = other_surf->facetList.size(); i--; ) 00958 TDVGFacetOwner::set(other_surf->facetList.step_and_get(),this); 00959 facetList += other_surf->facetList; 00960 other_surf->facetList.clean_out(); 00961 return CUBIT_SUCCESS; 00962 } 00963 00964 void PartitionSurface::get_facet_data( DLIList<CubitFacetData*>& result_list ) const 00965 { 00966 result_list = facetList; 00967 } 00968 00969 void PartitionSurface::set_facet_data( const DLIList<CubitFacetData*>& new_list ) 00970 { 00971 int i; 00972 00973 for ( i = facetList.size(); i--; ) 00974 TDVGFacetOwner::remove(facetList.step_and_get()); 00975 facetList = new_list; 00976 for ( i = facetList.size(); i--; ) 00977 TDVGFacetOwner::set(facetList.step_and_get(),this); 00978 } 00979 00980 void PartitionSurface::notify_split( FacetEntity* old_tri, FacetEntity* new_tri ) 00981 { 00982 if ( dynamic_cast<CubitFacetEdge*>(old_tri) ) 00983 return; 00984 00985 CubitFacetData* new_ptr = dynamic_cast<CubitFacetData*>(new_tri); 00986 #ifndef NDEBUG 00987 CubitFacetData* old_ptr = dynamic_cast<CubitFacetData*>(old_tri); 00988 assert(old_ptr && new_ptr && facetList.is_in_list(old_ptr)); 00989 #endif 00990 TDVGFacetOwner::set(new_ptr,this); 00991 facetList.append(new_ptr); 00992 } 00993 00994 CubitStatus PartitionSurface::init_facet_data() 00995 { 00996 Surface* real_surf = dynamic_cast<Surface*>(partitioned_entity()); 00997 //assert(are_marks_cleared()); 00998 00999 CubitStatus res = CUBIT_SUCCESS; 01000 GMem gMem; 01001 01002 // TODO - tolerance arguments are defaulted. Do we need to specify? 01003 res = real_surf->get_geometry_query_engine()-> 01004 get_graphics(real_surf, &gMem, PartitionTool::instance()->get_faceting_tolerance() ); 01005 if( !res ) 01006 return CUBIT_FAILURE; 01007 01008 // Work around bug w/ coincident facet points 01009 // for blend surfaces. Consolidate coincident points. 01010 int old_count = gMem.pointListCount; 01011 gMem.consolidate_points(GEOMETRY_RESABS); 01012 if( old_count != gMem.pointListCount ) { 01013 PRINT_WARNING("Possible invalid facetting for surface. " 01014 "Coincident points found.\n"); 01015 } 01016 01017 DLIList<CubitFacetData*> surf_facets; 01018 CubitPointData** point_array = new CubitPointData*[gMem.pointListCount]; 01019 01020 // create CubitFacetData from GMem 01021 int i; 01022 01023 CubitVector ipos, opos; 01024 for ( i = 0; i < gMem.pointListCount; i++ ) { 01025 ipos.set( gMem.point_list()[i].x, gMem.point_list()[i].y, gMem.point_list()[i].z ); 01026 if( real_surf->closest_point( ipos, &opos ) ) 01027 ipos = opos; 01028 point_array[i] = new CubitPointData( ipos ); 01029 } 01030 01031 int junk = 0; 01032 bool fail_out = false; 01033 CubitPoint *p1, *p2, *p3; 01034 for ( i = 0; i < gMem.fListCount; i += 4 ) 01035 { 01036 if(gMem.facet_list()[i] != 3) 01037 fail_out = true; 01038 else 01039 { 01040 p1 = point_array[ gMem.facet_list()[i+1] ]; 01041 p2 = point_array[ gMem.facet_list()[i+2] ]; 01042 p3 = point_array[ gMem.facet_list()[i+3] ]; 01043 01044 if(p1 == p2 || p1 == p3 || p2 == p3) 01045 fail_out = true; 01046 } 01047 if(fail_out == true) 01048 { 01049 PRINT_ERROR("Non-triangular facet encountered. Aborting.\n"); 01050 while (surf_facets.size()) 01051 delete surf_facets.pop(); 01052 for (i = 0; i < gMem.pointListCount; i++) 01053 delete point_array[i]; 01054 delete [] point_array; 01055 return CUBIT_FAILURE; 01056 } 01057 else 01058 { 01059 CubitFacetData* facet = new CubitFacetData(p1, p2, p3, &junk ); 01060 surf_facets.append(facet); 01061 } 01062 } 01063 01064 delete [] point_array; 01065 01066 if(geometry_sense == CUBIT_REVERSED) 01067 { 01068 for(i=surf_facets.size(); i--;) 01069 surf_facets.get_and_step()->flip(); 01070 } 01071 01072 /* 01073 // Make sure facet orientation is consistant 01074 DLIList<CubitFacet*> facets(surf_facets.size()); 01075 for ( i = surf_facets.size(); i--; ) 01076 { 01077 CubitFacet* facet = surf_facets.step_and_get(); 01078 facet->marked(1); 01079 facets.append(facet); 01080 } 01081 bool reversed_some = false; 01082 while ( facets.size() ) 01083 { 01084 CubitFacet* facet = facets.pop(); 01085 facet->marked(0); 01086 bool reversed[3] = {false,false,false}; 01087 CubitFacet* neighbors[3] = {0,0,0}; 01088 for ( i = 0; i < 3; i++ ) 01089 { 01090 CubitFacetEdge* edge = facet->edge(i); 01091 CubitFacet* other = edge->other_facet(facet); 01092 if( other && other != facet ) 01093 { 01094 neighbors[i] = other; 01095 int index = other->edge_index(edge); 01096 if ( facet->edge_use(i) == other->edge_use(index) ) 01097 reversed[i] = true; 01098 } 01099 } 01100 01101 if ( !(reversed[0] || reversed[1] || reversed[2]) ) 01102 continue; 01103 01104 facet->flip(); 01105 reversed_some = true; 01106 reversed[0] = !reversed[0]; 01107 reversed[1] = !reversed[1]; 01108 reversed[2] = !reversed[2]; 01109 01110 for ( i = 0; i < 3; i++ ) 01111 { 01112 if( neighbors[i] && reversed[i] && !neighbors[i]->marked() ) 01113 { 01114 neighbors[i]->marked(1); 01115 facets.append( neighbors[i] ); 01116 } 01117 } 01118 } 01119 01120 if( reversed_some ) 01121 { 01122 PRINT_WARNING("Possible invalid facetting for surface. " 01123 "Inconsistent facet orientation.\n"); 01124 } 01125 01126 // pick a facet and compare to surface normal to see 01127 // if we have them all backwards 01128 surf_facets.reset(); 01129 CubitFacet* facet = surf_facets.get(); 01130 CubitVector pts[3] = { facet->point(0)->coordinates(), 01131 facet->point(1)->coordinates(), 01132 facet->point(2)->coordinates()}; 01133 CubitVector facet_norm = (pts[1] - pts[0]) * (pts[2] - pts[0]); 01134 CubitVector facet_cent = (pts[0] + pts[1] + pts[2]) / 3.0; 01135 CubitVector surf_norm; 01136 real_surf->closest_point( facet_cent, 0, &surf_norm ); 01137 if ( facet_norm % surf_norm < 0 ) 01138 { 01139 PRINT_WARNING("Possible invalid facetting for surface. " 01140 "Backwards facets.\n"); 01141 for ( i = surf_facets.size(); i--; ) 01142 surf_facets.step_and_get()->flip(); 01143 } 01144 */ 01145 01146 PartSurfFacetTool tool(this); 01147 return tool.init_facet_data(surf_facets); 01148 } 01149 01150 01151 void PartitionSurface::replace_facets( DLIList<CubitFacetData*> &dead_facets, 01152 DLIList<CubitFacetData*> &new_facets) 01153 { 01154 int i; 01155 facetList -= dead_facets; 01156 facetList += new_facets; 01157 01158 for( i = dead_facets.size(); i--; ) 01159 TDVGFacetOwner::remove( dead_facets.step_and_get() ); 01160 01161 for( i = new_facets.size(); i--; ) 01162 TDVGFacetOwner::set( new_facets.step_and_get(), this ); 01163 01164 // TODO - memory management - where should the facets get deleted 01165 } 01166 01167 //------------------------------------------------------------------------- 01168 // Purpose : Find closest facet and point on facet 01169 // 01170 // Special Notes : 01171 // 01172 // Creator : Jason Kraftcheck 01173 // 01174 // Creation Date : 03/28/03 01175 //------------------------------------------------------------------------- 01176 CubitFacet* PartitionSurface::closest_facet( const CubitVector& input_position, 01177 CubitVector& result_position) 01178 { 01179 return PartSurfFacetTool::closest_facet( input_position, facetList, result_position ); 01180 } 01181 01182 01183 //------------------------------------------------------------------------- 01184 // Purpose : Save geometry in an attribute 01185 // 01186 // Special Notes : 01187 // 01188 // Creator : Jason Kraftcheck 01189 // 01190 // Creation Date : 01/21/03 01191 //------------------------------------------------------------------------- 01192 CubitStatus PartitionSurface::save( CubitSimpleAttrib& attrib ) 01193 { 01194 assert(dynamic_cast<Lump*>(partitioned_entity()) != 0); 01195 01196 int i; 01197 int id = sub_entity_set().get_id(this); 01198 if( id <= 0 ) return CUBIT_FAILURE; 01199 01200 // get facets 01201 DLIList<CubitFacetData*> facets; 01202 get_facet_data( facets ); 01203 01204 // get list of points from facets 01205 DLIList<CubitPoint*> points(facets.size()*3), facet_points(3); 01206 facets.reset(); 01207 for( i = facets.size(); i--; ) 01208 { 01209 facet_points.clean_out(); 01210 facets.get_and_step()->points(facet_points); 01211 points += facet_points; 01212 } 01213 01214 for( i = points.size(); i--; ) 01215 points.step_and_get()->marked(0); 01216 for( i = points.size(); i--; ) 01217 { 01218 CubitPoint* pt = points.step_and_get(); 01219 pt->marked(pt->marked()+1); 01220 } 01221 points.last(); 01222 for( i = points.size(); i--; ) 01223 { 01224 if( points.get()->marked() > 1 ) 01225 { 01226 points.get()->marked( points.get()->marked() - 1 ); 01227 points.change_to(0); 01228 } 01229 points.back(); 01230 } 01231 points.remove_all_with_value(0); 01232 01233 // construct position list 01234 DLIList<CubitVector*> pt_list(points.size()); 01235 points.reset(); 01236 for( i = 0; i < points.size(); i++ ) 01237 { 01238 CubitPoint* pt = points.get_and_step(); 01239 pt_list.append( new CubitVector(pt->coordinates()) ); 01240 pt->marked(i); 01241 } 01242 01243 // connect facet connectivity list 01244 DLIList<int> facetlist( facets.size() * 3 ); 01245 facets.reset(); 01246 for( i = facets.size(); i--; ) 01247 { 01248 facet_points.clean_out(); 01249 facets.get_and_step()->points(facet_points); 01250 facet_points.reset(); 01251 for( int j = facet_points.size(); j--; ) 01252 facetlist.append( facet_points.get_and_step()->marked() ); 01253 } 01254 01255 DLIList<int> facet_point_owners; 01256 DLIList<CubitFacetEdge*> pt_edges; 01257 points.reset(); 01258 for ( i = points.size(); i--; ) 01259 { 01260 CubitPoint* pt = points.get_and_step(); 01261 PartitionEntity* owner = TDVGFacetOwner::get(pt); 01262 if (!owner) 01263 { 01264 pt->edges(pt_edges); 01265 while ( pt_edges.size() ) 01266 { 01267 CubitFacetEdge* edge = pt_edges.pop(); 01268 PartitionEntity* tmp = TDVGFacetOwner::get(edge); 01269 if ( tmp ) 01270 { 01271 assert(!owner || owner == tmp); 01272 owner = tmp; 01273 } 01274 } 01275 } 01276 if ( !owner ) 01277 owner = this; 01278 01279 int set_id, ent_id; 01280 if( &(owner->sub_entity_set()) == &(sub_entity_set()) ) 01281 { 01282 set_id = 0; 01283 ent_id = sub_entity_set().get_id( owner ); 01284 } 01285 else 01286 { 01287 set_id = owner->sub_entity_set().get_unique_id(); 01288 ent_id = owner->sub_entity_set().get_id(owner); 01289 } 01290 facet_point_owners.append( set_id ); 01291 facet_point_owners.append( ent_id ); 01292 } 01293 01294 // clean up point marks 01295 for( i = points.size(); i--; ) 01296 points.step_and_get()->marked(0); 01297 01298 DLIList<int> topo_list; 01299 get_save_topology( topo_list ); 01300 01301 return sub_entity_set().save_geometry( id, 2, &pt_list, &facetlist, &topo_list, 01302 &facet_point_owners, attrib ); 01303 } 01304 01305 //------------------------------------------------------------------------- 01306 // Purpose : Get topology connectivity list for use in saving 01307 // 01308 // Special Notes : 01309 // 01310 // Creator : Jason Kraftcheck 01311 // 01312 // Creation Date : 01/21/03 01313 //------------------------------------------------------------------------- 01314 CubitStatus PartitionSurface::get_save_topology( DLIList<int>& topo_list ) 01315 { 01316 PartitionLoop* loop = 0; 01317 while( (loop = next_loop(loop)) ) 01318 { 01319 topo_list.append(loop->num_coedges()); 01320 PartitionCoEdge* coedge = loop->first_coedge(); 01321 do 01322 { 01323 int set_id, crv_id; 01324 PartitionCurve* curve = coedge->get_curve(); 01325 if( &(curve->sub_entity_set()) == &(sub_entity_set()) ) 01326 { 01327 set_id = 0; 01328 crv_id = sub_entity_set().get_id( curve ); 01329 } 01330 else 01331 { 01332 set_id = curve->sub_entity_set().get_unique_id(); 01333 crv_id = curve->sub_entity_set().get_id(curve); 01334 } 01335 01336 if( coedge->sense() == CUBIT_REVERSED ) 01337 crv_id *= -1; 01338 topo_list.append(set_id); 01339 topo_list.append(crv_id); 01340 } while( (coedge = loop->next_coedge(coedge)) != loop->first_coedge() ); 01341 } 01342 01343 return CUBIT_SUCCESS; 01344 } 01345 01346 01347 void PartitionSurface::interior_facet_points( DLIList<CubitPoint*>& list ) const 01348 { 01349 01350 DLIList<CubitPoint*> point_list(facetList.size() * 3); 01351 DLIList<CubitFacetEdge*> edge_list; 01352 int i; 01353 for( i = 0; i < facetList.size(); i++ ) 01354 { 01355 CubitFacetData* facet = facetList.next(i); 01356 for( int j = 0; j < 3; j++ ) 01357 { 01358 CubitPoint* pt = facet->point(j); 01359 if( TDVGFacetOwner::get(pt) ) 01360 continue; // not interior - on a vertex 01361 01362 edge_list.clean_out(); 01363 pt->edges( edge_list ); 01364 bool skip = false; 01365 for( int k = edge_list.size(); k--; ) 01366 if( TDVGFacetOwner::get(edge_list.step_and_get()) ) 01367 skip = true; // not interior - on a curve 01368 01369 if( !skip ) 01370 point_list.append(pt); 01371 } 01372 } 01373 01374 // uniquify list 01375 for( i = point_list.size(); i--; ) 01376 point_list.step_and_get()->marked(1); 01377 for( i = point_list.size(); i--; ) 01378 if( point_list.step_and_get()->marked() ) 01379 point_list.get()->marked(0); 01380 else 01381 point_list.change_to(0); 01382 point_list.remove_all_with_value(0); 01383 list = point_list; 01384 } 01385 01386 01387 void PartitionSurface::transform( const CubitTransformMatrix& xform ) 01388 { 01389 int i; 01390 01391 DLIList<CubitPoint*> points; 01392 interior_facet_points(points); 01393 for(i = points.size(); i--; ) 01394 { 01395 CubitPoint* pt = points.step_and_get(); 01396 pt->set( xform * pt->coordinates() ); 01397 } 01398 01399 double det = xform.sub_matrix( 3, 3 ).determinant(); 01400 if (det < 0.0) 01401 { 01402 for (i = 0; i < facetList.size(); i++) 01403 facetList.next(i)->flip(); 01404 01405 PartitionLoop* loop = 0; 01406 while ((loop = next_loop(loop))) 01407 loop->reverse(); 01408 } 01409 01410 for (i = 0; i < facetList.size(); i++ ) 01411 { 01412 facetList.next(i)->update_plane(); 01413 } 01414 01415 } 01416 01417 01418 01419 PartitionSurface* PartitionSurface::construct( const CubitSimpleAttrib& attrib, 01420 PartitionLump* vol ) 01421 { 01422 // construct surface and read attrib data 01423 PartitionSurface* new_surf = new PartitionSurface; 01424 DLIList<CubitVector*> facet_points; 01425 DLIList<int> facets, curve_conn, point_owners; 01426 vol->sub_entity_set(). 01427 add_lower_order( new_surf, attrib, 2, facet_points, facets, curve_conn, point_owners ); 01428 01429 if( facets.size() % 3 != 0 ) 01430 { 01431 assert( !(facets.size() % 3 ) ); 01432 delete new_surf; 01433 return 0; 01434 } 01435 01436 // create loops and coedges 01437 DLIList<PartitionCurve*> curve_list; 01438 int i = curve_conn.size(); 01439 curve_conn.reset(); 01440 bool okay = true; 01441 while( okay && i > 0 ) 01442 { 01443 int k = curve_conn.get_and_step(); 01444 i--; 01445 01446 if( k <= 0 || i < 2*k ) 01447 { okay = false; break; } 01448 01449 PartitionLoop* new_loop = new PartitionLoop(); 01450 PartitionCoEdge* prev_coedge = 0; 01451 new_surf->add( new_loop ); 01452 01453 for( int j = 0; okay && j < k; j++ ) 01454 { 01455 int set_id = curve_conn.get_and_step(); 01456 int ent_id = curve_conn.get_and_step(); 01457 i -= 2; 01458 01459 CubitSense sense = CUBIT_FORWARD; 01460 if( ent_id < 0 ) 01461 { 01462 sense = CUBIT_REVERSED; 01463 ent_id = -ent_id; 01464 } 01465 01466 PartitionEntity* ent = PartitionEngine::instance() 01467 .entity_from_id( set_id, ent_id, vol->sub_entity_set() ); 01468 PartitionCurve* curve = dynamic_cast<PartitionCurve*>(ent); 01469 01470 if( !curve ) 01471 { okay = false; break; } 01472 01473 curve_list.append( curve ); 01474 PartitionCoEdge* coedge = new PartitionCoEdge( new_surf, sense ); 01475 new_loop->insert_after( coedge, prev_coedge ); 01476 prev_coedge = coedge; 01477 curve->add( coedge ); 01478 } 01479 } 01480 01481 if( !okay ) 01482 { 01483 PartitionEngine::instance().destroy_surface( new_surf ); 01484 return 0; 01485 } 01486 01487 // construct facet points 01488 CubitPointData** points = new CubitPointData*[facet_points.size()]; 01489 facet_points.reset(); 01490 point_owners.reset(); 01491 for( i = 0; i < facet_points.size(); i++ ) 01492 { 01493 CubitVector* pt = facet_points.get_and_step(); 01494 points[i] = new CubitPointData(*pt); 01495 delete pt; 01496 01497 int set_id = point_owners.get_and_step(); 01498 int ent_id = point_owners.get_and_step(); 01499 PartitionEntity* owner = PartitionEngine::instance() 01500 .entity_from_id( set_id, ent_id, vol->sub_entity_set() ); 01501 01502 if ( !owner ) 01503 { 01504 okay = false; 01505 break; 01506 } 01507 01508 if ( owner != new_surf ) 01509 { 01510 if ( !dynamic_cast<PartitionPoint*>(owner) && 01511 !dynamic_cast<PartitionCurve*>(owner) ) 01512 { 01513 okay = false; 01514 break; 01515 } 01516 TDVGFacetOwner::set(points[i], owner); 01517 } 01518 } 01519 01520 if ( !okay ) 01521 { 01522 for ( i = 0; i < facet_points.size(); i++ ) 01523 delete points[i]; 01524 delete [] points; 01525 PartitionEngine::instance().destroy_surface( new_surf ); 01526 return 0; 01527 } 01528 01529 // construct facets 01530 facets.reset(); 01531 DLIList<CubitFacetData*> facet_list; 01532 int junk = 0; 01533 for( i = 0; i < facets.size(); i += 3 ) 01534 { 01535 CubitFacetData* facet = new CubitFacetData( 01536 points[facets.next(0)], 01537 points[facets.next(1)], 01538 points[facets.next(2)], &junk ); 01539 facet_list.append(facet); 01540 facets.step(3); 01541 01542 // set edge owners to this surface as a kind of mark 01543 // (will use this a little later) 01544 for ( int j = 0; j < 3; j++ ) 01545 TDVGFacetOwner::set( facet->edge(j), new_surf ); 01546 } 01547 01548 // Seam facet points on vertices 01549 for ( i = 0; i < facet_points.size(); i++ ) 01550 { 01551 PartitionEntity* ent = TDVGFacetOwner::get(points[i]); 01552 PartitionPoint* vertex = dynamic_cast<PartitionPoint*>(ent); 01553 if (!vertex) continue; 01554 01555 if ( !vertex->facet_point() ) 01556 vertex->facet_point(points[i]); 01557 else if ( vertex->facet_point() != points[i] ) 01558 { 01559 vertex->facet_point()->merge_points(points[i]); 01560 points[i] = vertex->facet_point(); 01561 } 01562 } 01563 01564 // done with point list -- delete it 01565 delete [] points; 01566 01567 // seam facet edges with curves 01568 DLIList<CubitFacetEdge*> pt_edges; 01569 DLIList<CubitFacetEdgeData*> curve_edges; 01570 while ( curve_list.size() ) 01571 { 01572 curve_edges.clean_out(); 01573 PartitionCurve* curve = curve_list.pop(); 01574 CubitPoint* pt = curve->start_point()->facet_point(); 01575 if (!pt) {okay = false; break;} 01576 01577 //For periodic curves, you can easily set up 'curve_edges' 01578 //in the opposite order. When finding the first edge, I added 01579 //the logic in the if(find_correct_direction_on_periodics) block. It 01580 //looks at the first facet edge in the curve and finds the appropriate 01581 //facet edge sharing the same point that has the smallest angle between. 01582 //This approach assure that we are appending the facet edges to the list 01583 //'curve_edges' in the same orientation as the facet edges on the curve. 01584 bool find_correct_direction_on_periodics = false; 01585 PartitionPoint* start_vtx = curve->start_point(); 01586 PartitionPoint* end_vtx = curve->end_point(); 01587 CubitPointData* start_point = start_vtx->facet_point(); 01588 CubitPointData* end_point = end_vtx->facet_point(); 01589 if( start_vtx == end_vtx && start_point == end_point ) 01590 find_correct_direction_on_periodics = true; 01591 01592 double smallest_angle = CUBIT_DBL_MAX; 01593 bool debug = false; 01594 01595 do { 01596 01597 if( smallest_angle != CUBIT_DBL_MAX ) 01598 find_correct_direction_on_periodics = false; 01599 01600 CubitFacetEdge *edge = 0, *pt_edge = 0; 01601 pt_edges.clean_out(); 01602 pt->edges(pt_edges); 01603 while ( pt_edges.size() ) 01604 { 01605 CubitFacetEdge* tmp_edge = pt_edges.pop(); 01606 if ( TDVGFacetOwner::get(tmp_edge) != new_surf ) 01607 continue; 01608 01609 PartitionEntity* owner = TDVGFacetOwner::get(tmp_edge->other_point(pt)); 01610 if ( owner == curve ) 01611 { 01612 if( find_correct_direction_on_periodics ) 01613 { 01614 CubitPoint* start_point = pt; 01615 01616 DLIList<CubitFacetEdgeData*> curve_edges; 01617 curve->get_facet_data(curve_edges); 01618 curve_edges.reset(); 01619 CubitFacetEdge *first_facet_edge = curve_edges.get(); 01620 CubitPoint *real_next_point = first_facet_edge->other_point(start_point); 01621 CubitPoint *possible_next_point = tmp_edge->other_point(start_point); 01622 01623 CubitVector v1 = real_next_point->coordinates() - start_point->coordinates(); 01624 CubitVector v2 = possible_next_point->coordinates() - start_point->coordinates(); 01625 01626 double angle = v1.interior_angle(v2); 01627 01628 if( angle < smallest_angle ) 01629 { 01630 smallest_angle = angle; 01631 edge = tmp_edge; 01632 } 01633 } 01634 else 01635 { 01636 edge = tmp_edge; 01637 } 01638 } 01639 else if ( owner == curve->end_point() ) 01640 { 01641 pt_edge = tmp_edge; 01642 } 01643 } 01644 01645 if ( !edge ) 01646 edge = pt_edge; 01647 else 01648 { 01649 //so we don't traverse backwards 01650 TDVGFacetOwner::set(edge->other_point(pt), 0); 01651 } 01652 01653 CubitFacetEdgeData* edge_d = dynamic_cast<CubitFacetEdgeData*>(edge); 01654 if (!edge_d) 01655 { 01656 okay = false; 01657 break; 01658 } 01659 01660 if( debug ) 01661 { 01662 pt->debug_draw(4); 01663 GfxDebug::mouse_xforms(); 01664 edge_d->debug_draw(5); 01665 GfxDebug::mouse_xforms(); 01666 edge_d->other_point(pt)->debug_draw(6); 01667 GfxDebug::mouse_xforms(); 01668 } 01669 01670 curve_edges.append(edge_d); 01671 pt = edge_d->other_point(pt); 01672 } while (pt != curve->end_point()->facet_point()); 01673 01674 if( !okay || !PartSurfFacetTool::seam_curve( curve_edges, curve, facet_list ) ) 01675 { 01676 okay = false; 01677 break; 01678 } 01679 } 01680 01681 // clean up any owner pointers on edges that were being 01682 // used as a kind of mark 01683 for ( i = facet_list.size(); i--; ) 01684 { 01685 CubitFacet* facet = facet_list.get_and_step(); 01686 for ( int j = 0; j < 3; j++ ) 01687 if ( TDVGFacetOwner::get(facet->edge(j)) == new_surf ) 01688 TDVGFacetOwner::set(facet->edge(j), 0); 01689 } 01690 01691 // set surface facets 01692 new_surf->set_facet_data( facet_list ); 01693 01694 if (!okay) 01695 { 01696 PartitionEngine::instance().destroy_surface( new_surf ); 01697 return 0; 01698 } 01699 01700 return new_surf; 01701 } 01702 01703 01704 CubitStatus PartitionSurface::notify_moving_point( CubitPoint* point, 01705 const CubitVector& new_pos ) 01706 { 01707 DLIList<CubitFacetData*> old_facets, new_facets; 01708 if (!PartSurfFacetTool::fix_move_point(point, new_pos, facetList, old_facets, new_facets, this)) 01709 return CUBIT_FAILURE; 01710 01711 assert( !old_facets.size() == !new_facets.size() ); 01712 if (old_facets.size()) 01713 replace_facets( old_facets, new_facets ); 01714 return CUBIT_SUCCESS; 01715 } 01716 01717 void PartitionSurface::notify_destroyed( CubitFacetData* facet ) 01718 { 01719 facetList.move_to(facet); 01720 assert(facetList.size() && facetList.get() == facet); 01721 facetList.extract(); 01722 } 01723 01724 01725 CubitStatus PartitionSurface::evaluate( double u, double v, 01726 CubitVector *position, 01727 CubitVector *normal, 01728 CubitVector *curvature1, 01729 CubitVector *curvature2 ) 01730 { 01731 return CUBIT_FAILURE; 01732 } 01733 01734 CubitStatus PartitionSurface::get_projected_distance_on_surface( CubitVector *pos1, 01735 CubitVector *pos2, 01736 double &distance ) 01737 { 01738 return CUBIT_FAILURE; 01739 } 01740 01741 CubitStatus PartitionSurface::get_sphere_params 01742 ( 01743 CubitVector ¢er, 01744 double &radius 01745 ) const 01746 { 01747 PRINT_ERROR("Currently, Cubit is unable to determine sphere parameters for PartitionSurfaces.\n"); 01748 return CUBIT_FAILURE; 01749 } 01750 01751 CubitStatus PartitionSurface::get_cone_params 01752 ( 01753 CubitVector ¢er, 01754 CubitVector &normal, 01755 CubitVector &major_axis, 01756 double &radius_ratio, 01757 double &sine_angle, 01758 double &cos_angle 01759 ) const 01760 { 01761 PRINT_ERROR("Currently, Cubit is unable to determine cone parameters for PartitionSurfaces.\n"); 01762 return CUBIT_FAILURE; 01763 } 01764 01765 CubitStatus PartitionSurface::get_torus_params 01766 ( 01767 CubitVector ¢er, 01768 CubitVector &normal, 01769 double &major_radius, 01770 double &minor_radius 01771 ) const 01772 { 01773 PRINT_ERROR("Currently, Cubit is unable to determine torus parameters for PartitionSurface.\n"); 01774 return CUBIT_FAILURE; 01775 } 01776 01777 CubitStatus PartitionSurface::get_nurb_params 01778 ( 01779 bool &rational, 01780 int °ree_u, 01781 int °ree_v, 01782 int &num_cntrl_pts_u, 01783 int &num_cntrl_pts_v, 01784 DLIList<CubitVector> &cntrl_pts, 01785 DLIList<double> &cntrl_pt_weights, 01786 DLIList<double> &u_knots, 01787 DLIList<double> &v_knots 01788 ) const 01789 { 01790 PRINT_ERROR("Currently, Cubit is unable to determine nurbs parameters for PartitionSurface.\n"); 01791 return CUBIT_FAILURE; 01792 }