cgma
|
00001 //-Class: TDSplitSurface.cpp 00002 00003 #include "TDSplitSurface.hpp" 00004 #include "RefFace.hpp" 00005 #include "RefEdge.hpp" 00006 #include "RefVertex.hpp" 00007 #include "CoEdge.hpp" 00008 #include "Loop.hpp" 00009 #include "GMem.hpp" 00010 #include "CubitMessage.hpp" 00011 00012 TDSplitSurface::TDSplitSurface( int vertex_type ) 00013 { 00014 vertexType = vertex_type; 00015 sideA = NULL; 00016 sideB = NULL; 00017 sideC = NULL; 00018 sideD = NULL; 00019 } 00020 00021 TDSplitSurface::TDSplitSurface( RefFace *ref_face_ptr ) 00022 { 00023 refFacePtr = ref_face_ptr; 00024 00025 sideA = NULL; 00026 sideB = NULL; 00027 sideC = NULL; 00028 sideD = NULL; 00029 } 00030 00031 TDSplitSurface::~TDSplitSurface() 00032 { 00033 if( sideA ) 00034 delete sideA; 00035 if( sideB ) 00036 delete sideB; 00037 if( sideC ) 00038 delete sideC; 00039 if( sideD ) 00040 delete sideD; 00041 } 00042 00043 CubitStatus 00044 TDSplitSurface::add_coedges( DLIList<CoEdge*> &co_edge_list, 00045 int side_interval[] ) 00046 { 00047 int i; 00048 co_edge_list.reset(); 00049 CoEdge *co_edge_ptr; 00050 DLIList<CoEdge*> chain; 00051 RefVertex *start_vertex_ptr; 00052 00053 // SIDE A 00054 if( side_interval[0] == 0 ) 00055 { 00056 co_edge_ptr = co_edge_list.get(); 00057 start_vertex_ptr = start_vertex( co_edge_ptr ); 00058 CubitVector tmp(start_vertex_ptr->coordinates()); 00059 sideA = new SSSide( refFacePtr, chain, &tmp ); 00060 } 00061 else 00062 { 00063 for( i=side_interval[0]; i--; ) 00064 { 00065 co_edge_ptr = co_edge_list.get_and_step(); 00066 chain.append( co_edge_ptr ); 00067 } 00068 sideA = new SSSide( refFacePtr, chain ); 00069 } 00070 chain.clean_out(); 00071 00072 // SIDE B 00073 if( side_interval[1] == 0 ) 00074 { 00075 co_edge_ptr = co_edge_list.get(); 00076 start_vertex_ptr = start_vertex( co_edge_ptr ); 00077 CubitVector tmp(start_vertex_ptr->coordinates()); 00078 sideB = new SSSide( refFacePtr, chain, &tmp ); 00079 } 00080 else 00081 { 00082 for( i=side_interval[1]; i--; ) 00083 { 00084 co_edge_ptr = co_edge_list.get_and_step(); 00085 chain.append( co_edge_ptr ); 00086 } 00087 sideB = new SSSide( refFacePtr, chain ); 00088 } 00089 chain.clean_out(); 00090 00091 // SIDE C 00092 if( side_interval[2] == 0 ) 00093 { 00094 co_edge_ptr = co_edge_list.get(); 00095 start_vertex_ptr = start_vertex( co_edge_ptr ); 00096 CubitVector tmp(start_vertex_ptr->coordinates()); 00097 sideC = new SSSide( refFacePtr, chain, &tmp ); 00098 } 00099 else 00100 { 00101 for( i=side_interval[2]; i--; ) 00102 { 00103 co_edge_ptr = co_edge_list.get_and_step(); 00104 chain.append( co_edge_ptr ); 00105 } 00106 sideC = new SSSide( refFacePtr, chain ); 00107 } 00108 chain.clean_out(); 00109 00110 // SIDE D 00111 if( side_interval[3] == 0 ) 00112 { 00113 co_edge_ptr = co_edge_list.get(); 00114 start_vertex_ptr = start_vertex( co_edge_ptr ); 00115 CubitVector tmp(start_vertex_ptr->coordinates()); 00116 sideD = new SSSide( refFacePtr, chain, &tmp ); 00117 } 00118 else 00119 { 00120 for( i=side_interval[3]; i--; ) 00121 { 00122 co_edge_ptr = co_edge_list.get_and_step(); 00123 chain.append( co_edge_ptr ); 00124 } 00125 sideD = new SSSide( refFacePtr, chain ); 00126 } 00127 00128 return CUBIT_SUCCESS; 00129 } 00130 00131 CubitStatus 00132 TDSplitSurface::add_a_coedges( DLIList<CoEdge*> &a_coedges, 00133 RefVertex *start_vertex_ptr ) 00134 { 00135 if( start_vertex_ptr == NULL ) 00136 sideA = new SSSide( refFacePtr, a_coedges ); 00137 else 00138 { 00139 // Collapsed side (for triangle) 00140 CubitVector tmp(start_vertex_ptr->coordinates()); 00141 sideA = new SSSide( refFacePtr, a_coedges, &tmp ); 00142 } 00143 return CUBIT_SUCCESS; 00144 } 00145 00146 CubitStatus 00147 TDSplitSurface::add_b_coedges( DLIList<CoEdge*> &b_coedges, 00148 RefVertex *start_vertex_ptr ) 00149 { 00150 if( start_vertex_ptr == NULL ) 00151 sideB = new SSSide( refFacePtr, b_coedges ); 00152 else 00153 { 00154 // Collapsed side (for triangle) 00155 CubitVector tmp(start_vertex_ptr->coordinates()); 00156 sideB = new SSSide( refFacePtr, b_coedges, &tmp ); 00157 } 00158 return CUBIT_SUCCESS; 00159 } 00160 00161 CubitStatus 00162 TDSplitSurface::add_c_coedges( DLIList<CoEdge*> &c_coedges, 00163 RefVertex *start_vertex_ptr ) 00164 { 00165 if( start_vertex_ptr == NULL ) 00166 sideC = new SSSide( refFacePtr, c_coedges ); 00167 else 00168 { 00169 // Collapsed side (for triangle) 00170 CubitVector tmp(start_vertex_ptr->coordinates()); 00171 sideC = new SSSide( refFacePtr, c_coedges, &tmp ); 00172 } 00173 return CUBIT_SUCCESS; 00174 } 00175 00176 CubitStatus 00177 TDSplitSurface::add_d_coedges( DLIList<CoEdge*> &d_coedges, 00178 RefVertex *start_vertex_ptr ) 00179 { 00180 if( start_vertex_ptr == NULL ) 00181 sideD = new SSSide( refFacePtr, d_coedges ); 00182 else 00183 { 00184 // Collapsed side (for triangle) 00185 CubitVector tmp(start_vertex_ptr->coordinates()); 00186 sideD = new SSSide( refFacePtr, d_coedges, &tmp ); 00187 } 00188 return CUBIT_SUCCESS; 00189 } 00190 00191 DLIList<CoEdge*> * 00192 TDSplitSurface::get_a_coedges() 00193 { 00194 return sideA->co_edges(); 00195 } 00196 00197 DLIList<CoEdge*> * 00198 TDSplitSurface::get_b_coedges() 00199 { 00200 return sideB->co_edges(); 00201 } 00202 00203 DLIList<CoEdge*> * 00204 TDSplitSurface::get_c_coedges() 00205 { 00206 return sideC->co_edges(); 00207 } 00208 00209 DLIList<CoEdge*> * 00210 TDSplitSurface::get_d_coedges() 00211 { 00212 return sideD->co_edges(); 00213 } 00214 00215 CubitStatus 00216 TDSplitSurface::tessellate_sides( double tol, double fraction, double distance, 00217 int num_segs, 00218 DLIList<RefVertex*> &through_vertex_list ) 00219 { 00220 // Sides B and D will use the graphics tessellation to build the 00221 // param lists. 00222 if( sideB->build_param_list_from_facets( tol ) == CUBIT_FAILURE ) 00223 return CUBIT_FAILURE; 00224 if( sideD->build_param_list_from_facets( tol ) == CUBIT_FAILURE ) 00225 return CUBIT_FAILURE; 00226 00227 // Syncronize the lists so that we have the same number and evenly 00228 // spaced tessellations on B and D sides 00229 if( sideB->syncronize_lists( sideD, tol ) == CUBIT_FAILURE ) 00230 { 00231 PRINT_ERROR( "Unable to interpolate split location.\n" ); 00232 return CUBIT_FAILURE; 00233 } 00234 00235 // Sides A and C typically only need to retrieve the 50% location, 00236 // but may have a location different than 50% or multiple locations. 00237 // Note if num_segs>2 the fraction is ignored. 00238 00239 // Populate lists for side A 00240 if( sideA->build_param_list( fraction, distance, num_segs, through_vertex_list ) 00241 == CUBIT_FAILURE ) 00242 return CUBIT_FAILURE; 00243 00244 // Populate lists for side C 00245 if( distance != -1.0 ) 00246 distance = sideC->length()-distance; 00247 00248 if( sideC->build_param_list( 1.0-fraction, distance, num_segs, 00249 through_vertex_list ) == CUBIT_FAILURE ) 00250 return CUBIT_FAILURE; 00251 00252 return CUBIT_SUCCESS; 00253 } 00254 00255 RefVertex * 00256 TDSplitSurface::start_vertex( CoEdge *co_edge_ptr ) 00257 { 00258 RefEdge *ref_edge_ptr = co_edge_ptr->get_ref_edge_ptr(); 00259 00260 if ( co_edge_ptr->get_sense() == CUBIT_REVERSED ) 00261 return ref_edge_ptr->end_vertex(); 00262 else 00263 return ref_edge_ptr->start_vertex(); 00264 } 00265 00266 //================================================================================ 00267 // Description: A trivial class to hold two parameter values so that they 00268 // can be stored in a DLIList. They are the min and max parameter 00269 // space along the composite curve. (Split Surface Param) 00270 // Author : Steve Storm 00271 // Date : 2/3/2004 00272 //================================================================================ 00273 SSParam::SSParam( double min, double max ) 00274 { 00275 uMin = min; 00276 uMax = max; 00277 } 00278 00279 SSParam::~SSParam() 00280 { 00281 } 00282 00283 //================================================================================ 00284 // Description: This class (Split Surface Side) holds a chain of curves on one 00285 // side of the surface. It is needed to handle queries using a 00286 // composite curve concept. 00287 // Author : Steve Storm 00288 // Date : 2/3/2004 00289 //================================================================================ 00290 SSSide::SSSide( RefFace *ref_face_ptr, DLIList<CoEdge*> &co_edges, 00291 const CubitVector *collapsed_loc_ptr ) 00292 { 00293 refFacePtr = ref_face_ptr; 00294 isCollapsed = CUBIT_FALSE; 00295 00296 coEdgeChain = co_edges; 00297 double param_low = 0.0; 00298 paramHigh = 0.0; 00299 int i; 00300 CoEdge *co_edge_ptr; 00301 for( i=coEdgeChain.size(); i--; ) 00302 { 00303 co_edge_ptr = coEdgeChain.get_and_step(); 00304 paramHigh += co_edge_ptr->get_ref_edge_ptr()->measure(); 00305 coEdgeParamList.append( new SSParam( param_low, paramHigh) ); 00306 param_low = paramHigh; 00307 } 00308 00309 if( !coEdgeChain.size() ) 00310 { 00311 // Need to add a single point to hold the location of this side 00312 // ie., the side is collapsed (point of a triangle) 00313 isCollapsed = CUBIT_TRUE; 00314 00315 assert( collapsed_loc_ptr != NULL ); 00316 00317 paramHigh = 0.0; 00318 coordList.append( new CubitVector( *collapsed_loc_ptr ) ); 00319 paramList.append( 0.0 ); 00320 } 00321 } 00322 00323 SSSide::~SSSide() 00324 { 00325 // Free memory 00326 while( coEdgeParamList.size() ) 00327 delete coEdgeParamList.pop(); 00328 while( coordList.size() ) 00329 delete coordList.pop(); 00330 } 00331 00332 CubitStatus 00333 SSSide::position_from_u( double u_value, CubitVector &output_position) 00334 { 00335 if( isCollapsed ) 00336 { 00337 output_position = *coordList.get(); 00338 return CUBIT_SUCCESS; 00339 } 00340 00341 // Determine which CoEdge the given u is on 00342 int i; 00343 coEdgeChain.reset(); 00344 coEdgeParamList.reset(); 00345 CoEdge *co_edge_ptr = NULL; 00346 SSParam *param_ptr = NULL; 00347 double coedge_param_max; 00348 for( i=coEdgeChain.size(); i--; ) 00349 { 00350 co_edge_ptr = coEdgeChain.get_and_step(); 00351 param_ptr = coEdgeParamList.get_and_step(); 00352 coedge_param_max = param_ptr->umax(); 00353 if( u_value <= coedge_param_max ) 00354 break; 00355 } 00356 00357 // We have found the correct coedge. Get it's RefEdge. 00358 // Subtract it's start parameter. 00359 // We now have the distance along the curve to traverse. 00360 RefEdge *ref_edge_ptr = co_edge_ptr->get_ref_edge_ptr(); 00361 double i_dist; // individual distance 00362 i_dist = u_value - param_ptr->umin(); 00363 00364 double ui_min, ui_max; 00365 ref_edge_ptr->get_param_range( ui_min, ui_max ); 00366 00367 if( co_edge_ptr->get_sense() == CUBIT_REVERSED ) 00368 i_dist = ref_edge_ptr->measure() - i_dist; 00369 00370 double ui = ref_edge_ptr->u_from_arc_length( ui_min, i_dist ); 00371 00372 return ref_edge_ptr->position_from_u( ui, output_position ); 00373 } 00374 00375 CubitStatus 00376 SSSide::u_from_position( const CubitVector &input_position, double &u ) 00377 { 00378 if( isCollapsed ) 00379 { 00380 u = 0.0; 00381 return CUBIT_SUCCESS; 00382 } 00383 00384 // First check each curve to determine which one the input position is on 00385 int i; 00386 coEdgeChain.reset(); 00387 coEdgeParamList.reset(); 00388 CoEdge *co_edge_ptr = NULL; 00389 SSParam *param_ptr = NULL; 00390 int found = 0; 00391 CubitPointContainment pnt_containment; 00392 for( i=coEdgeChain.size(); i--; ) 00393 { 00394 co_edge_ptr = coEdgeChain.get_and_step(); 00395 param_ptr = coEdgeParamList.get_and_step(); 00396 pnt_containment = co_edge_ptr->get_ref_edge_ptr()->point_containment( input_position ); 00397 if( pnt_containment == CUBIT_PNT_ON ) 00398 { 00399 found = 1; 00400 break; 00401 } 00402 } 00403 00404 if( !found ) 00405 { 00406 PRINT_ERROR( "Position %f, %f, %f not found on any curve.\n", 00407 input_position.x(), input_position.y(), input_position.z() ); 00408 return CUBIT_FAILURE; 00409 } 00410 00411 // Now we know which CoEdge it is on. Get the curve. Get the parameter of 00412 // the individual curve. 00413 RefEdge *ref_edge_ptr = co_edge_ptr->get_ref_edge_ptr(); 00414 double ui = ref_edge_ptr->u_from_position( input_position ); 00415 00416 // Get the parameter of the composite curve 00417 00418 // Add the distance along the curve to its start param (umin) 00419 double sum = param_ptr->umin(); 00420 00421 double ui_min, ui_max; 00422 ref_edge_ptr->get_param_range( ui_min, ui_max ); 00423 00424 CubitSense sense = co_edge_ptr->get_sense(); 00425 double root_param = (sense == CUBIT_FORWARD) ? ui_min : ui_max; 00426 double lfu = ( root_param < ui ) ? 00427 ref_edge_ptr->length_from_u( root_param, ui ) : 00428 ref_edge_ptr->length_from_u( ui, root_param ); 00429 00430 u = sum + fabs( lfu ); 00431 00432 return CUBIT_SUCCESS; 00433 } 00434 00435 // Same as above function but curve is known 00436 CubitStatus 00437 SSSide::u_from_position( const CubitVector &input_position, 00438 CoEdge *co_edge_ptr, SSParam *param, 00439 double &u ) 00440 { 00441 if( isCollapsed ) 00442 { 00443 u = 0.0; 00444 return CUBIT_SUCCESS; 00445 } 00446 00447 RefEdge *ref_edge_ptr = co_edge_ptr->get_ref_edge_ptr(); 00448 double ui = ref_edge_ptr->u_from_position( input_position ); 00449 00450 // Get the parameter of the composite curve 00451 double sum = param->umin(); 00452 00453 double ui_min, ui_max; 00454 ref_edge_ptr->get_param_range( ui_min, ui_max ); 00455 00456 CubitSense sense = co_edge_ptr->get_sense(); 00457 double root_param = (sense == CUBIT_FORWARD) ? ui_min : ui_max; 00458 double lfu = ( root_param < ui ) ? 00459 ref_edge_ptr->length_from_u( root_param, ui ) : 00460 ref_edge_ptr->length_from_u( ui, root_param ); 00461 00462 u = sum + fabs( lfu ); 00463 00464 return CUBIT_SUCCESS; 00465 } 00466 00467 CubitBoolean 00468 SSSide::is_vertex_on( RefVertex *ref_vertex_ptr ) 00469 { 00470 if( isCollapsed ) 00471 { 00472 // Compare coordinates 00473 CubitVector *side_coord = coordList.get(); 00474 00475 if( side_coord->about_equal( ref_vertex_ptr->coordinates() ) ) 00476 return CUBIT_TRUE; 00477 else 00478 return CUBIT_FALSE; 00479 } 00480 00481 // Check if it is on each coedge 00482 CubitVector ref_coords = ref_vertex_ptr->coordinates(); 00483 CubitPointContainment pnt_containment; 00484 int i; 00485 CoEdge *co_edge_ptr; 00486 coEdgeChain.reset(); 00487 for( i=coEdgeChain.size(); i--; ) 00488 { 00489 co_edge_ptr = coEdgeChain.get_and_step(); 00490 pnt_containment = co_edge_ptr->get_ref_edge_ptr()-> 00491 point_containment( ref_coords ); 00492 if( pnt_containment == CUBIT_PNT_ON ) 00493 return CUBIT_TRUE; 00494 } 00495 00496 return CUBIT_FALSE; 00497 } 00498 00499 CubitStatus 00500 SSSide::build_param_list_from_facets( double tolerance ) 00501 { 00502 if( isCollapsed ) 00503 return CUBIT_SUCCESS; 00504 00505 int i, j, num_pnts; 00506 CoEdge *co_edge_ptr; 00507 SSParam *param_ptr; 00508 double param; 00509 CubitVector vec, *vec_ptr; 00510 00511 coEdgeChain.reset(); 00512 coEdgeParamList.reset(); 00513 co_edge_ptr = coEdgeChain.get(); 00514 param_ptr = coEdgeParamList.get(); 00515 00516 // Get the first coordinate 00517 if( co_edge_ptr->get_sense() == CUBIT_FORWARD ) 00518 vec = co_edge_ptr->get_ref_edge_ptr()->start_coordinates(); 00519 else 00520 vec = co_edge_ptr->get_ref_edge_ptr()->end_coordinates(); 00521 00522 // Add to list 00523 if( u_from_position( vec, co_edge_ptr, param_ptr, param ) == CUBIT_FAILURE ) 00524 return CUBIT_FAILURE; 00525 paramList.append( param ); 00526 00527 for( i=coEdgeChain.size(); i--; ) 00528 { 00529 DLIList<CubitVector*> temp_vec_list; 00530 co_edge_ptr = coEdgeChain.get_and_step(); 00531 param_ptr = coEdgeParamList.get_and_step(); 00532 GMem *g_mem = new GMem; 00533 00534 co_edge_ptr->get_ref_edge_ptr()->get_graphics( *g_mem, tolerance ); 00535 num_pnts = g_mem->pointListCount; 00536 00537 GPoint* point_list = g_mem->point_list(); 00538 00539 for( j=0; j<num_pnts; j++ ) 00540 { 00541 vec_ptr = new CubitVector( 00542 point_list[j].x, point_list[j].y, point_list[j].z ); 00543 temp_vec_list.append( vec_ptr ); 00544 } 00545 00546 delete g_mem; 00547 00548 if( co_edge_ptr->get_sense() == CUBIT_REVERSED ) 00549 temp_vec_list.reverse(); 00550 00551 // Calculate corresponding parameter values 00552 temp_vec_list.reset(); 00553 // Skip the first point since already in the list 00554 vec_ptr = temp_vec_list.get_and_step(); 00555 for( j=1; j<num_pnts; j++ ) 00556 { 00557 vec_ptr = temp_vec_list.get_and_step(); 00558 if( u_from_position( *vec_ptr, co_edge_ptr, param_ptr, param ) 00559 == CUBIT_FAILURE ) 00560 return CUBIT_FAILURE; 00561 paramList.append( param ); 00562 } 00563 00564 while( temp_vec_list.size() ) 00565 delete temp_vec_list.pop(); 00566 } 00567 00568 // Extremes of paramList should be 0.0 and paramHigh - force them to 00569 // these values exactly. This avoids some slight roundoff errors that 00570 // can cause an extra split point close to the start or end of a surface 00571 // that won't even be cleaned up in syncronize_lists. This causes 00572 // unexpected results at the start or end of the split. 00573 paramList.reset(); 00574 double first_param = paramList.get_and_back(); 00575 double last_param = paramList.get(); 00576 paramList.reset(); 00577 if( first_param > last_param ) 00578 { 00579 paramList.change_to( paramHigh ); 00580 paramList.back(); 00581 paramList.change_to( 0.0 ); 00582 } 00583 else 00584 { 00585 paramList.change_to( 0.0 ); 00586 paramList.back(); 00587 paramList.change_to( paramHigh ); 00588 } 00589 00590 return CUBIT_SUCCESS; 00591 } 00592 00593 CubitStatus 00594 SSSide::build_param_list( double fraction, double distance, int num_segs, 00595 DLIList<RefVertex*> &through_vertex_list ) 00596 { 00597 int i; 00598 double frac, param; 00599 // Add paramList.size to account for potential collapsed edge that already 00600 // has an item in the list 00601 for( i=1+paramList.size(); i<num_segs; i++ ) 00602 { 00603 // Example locations (we need to fill middle only): 0 1 2 3 4 00604 if( num_segs > 2 ) 00605 frac = (double)i/num_segs; 00606 else if( through_vertex_list.size() ) 00607 { 00608 int j; 00609 int found = 0; 00610 through_vertex_list.reset(); 00611 for( j=through_vertex_list.size(); j--; ) 00612 { 00613 RefVertex *ref_vertex_ptr = through_vertex_list.get_and_step(); 00614 if( is_vertex_on( ref_vertex_ptr ) ) 00615 { 00616 coordList.append( new CubitVector( ref_vertex_ptr->coordinates() ) ); 00617 if( u_from_position( ref_vertex_ptr->coordinates(), param ) == CUBIT_FAILURE ) 00618 return CUBIT_FAILURE; 00619 paramList.append( param ); 00620 found = 1; 00621 00622 // Keep track of vertices that were used - we can give a warning when 00623 // done if some weren't used. 00624 TDSplitSurface *tdss = (TDSplitSurface *)ref_vertex_ptr-> 00625 get_TD(&TDSplitSurface::is_split_surface); 00626 if( !tdss ) 00627 ref_vertex_ptr->add_TD( new TDSplitSurface( 0 ) ); 00628 break; 00629 } 00630 } 00631 if( found ) 00632 continue; 00633 else 00634 frac = fraction; 00635 } 00636 else 00637 frac = fraction; 00638 00639 if( distance != -1.0 ) 00640 { 00641 if( distance > paramHigh ) 00642 { 00643 PRINT_ERROR( "Surface %d is not wide enough to support split distance of %f\n", 00644 refFacePtr->id(), distance ); 00645 return CUBIT_FAILURE; 00646 } 00647 param = distance; 00648 } 00649 else 00650 param = frac*paramHigh; 00651 00652 paramList.append( param ); 00653 00654 CubitVector vec; 00655 if( position_from_u( param, vec ) == CUBIT_FAILURE ) 00656 return CUBIT_FAILURE; 00657 00658 coordList.append( new CubitVector( vec ) ); 00659 } 00660 00661 return CUBIT_SUCCESS; 00662 } 00663 00664 CubitStatus 00665 SSSide::syncronize_lists( SSSide *other_side, double param_tol ) 00666 { 00667 // This will syncronize paramList in "this" and other_side, also 00668 // update coordList correspondingly in both. 00669 00670 // Note: sideB and sideD (which we are operating on here) will contain the 00671 // corner coords (sideA and sideC just contain the interior coords) 00672 00673 // This should never happen but check anyway 00674 if( paramHigh == 0.0 && other_side->paramHigh == 0.0 ) 00675 return CUBIT_FAILURE; 00676 00677 paramList.reset(); 00678 other_side->paramList.reset(); 00679 00680 DLIList<double> other_param_list = other_side->paramList; 00681 int i; 00682 double param; 00683 00684 // Reverse other_param_list (which is on side D) so that it is going in the 00685 // same direction as this paramList (side B) 00686 other_param_list.reset(); 00687 for( i=other_param_list.size(); i--; ) 00688 { 00689 param = other_param_list.get(); 00690 other_param_list.change_to( other_side->paramHigh - param ); 00691 other_param_list.step(); 00692 } 00693 00694 other_param_list.reverse(); // May make sort faster 00695 00696 // Parameter lists must be "scaled" to match 00697 double this_factor = 1.0; 00698 double other_factor = 1.0; 00699 double scale_factor = 1.0; 00700 00701 // Only scale if neither side is a zero length side and sides are not equal 00702 // in length 00703 if( !isCollapsed && !other_side->is_collapsed() && 00704 other_side->paramHigh != paramHigh ) 00705 { 00706 // Use longer side as "baseline" - it may have more "features" 00707 // so we will be sure to capture those 00708 if( paramHigh > other_side->paramHigh ) 00709 { 00710 other_param_list.reset(); 00711 00712 other_factor = paramHigh/other_side->paramHigh; 00713 scale_factor = other_factor; 00714 for( i=other_param_list.size(); i--; ) 00715 { 00716 param = other_param_list.get(); 00717 other_param_list.change_to( param*other_factor ); 00718 other_param_list.step(); 00719 } 00720 } 00721 else 00722 { 00723 paramList.reset(); 00724 00725 this_factor = other_side->paramHigh/paramHigh; 00726 scale_factor = this_factor; 00727 for( i=paramList.size(); i--; ) 00728 { 00729 param = paramList.get(); 00730 paramList.change_to( param*this_factor ); 00731 paramList.step(); 00732 } 00733 } 00734 } 00735 00736 DLIList<double> combined_param_list = paramList; 00737 combined_param_list.merge_unique( other_param_list ); 00738 00739 // This should never happen, but check anyway 00740 if( combined_param_list.size() < 2 ) 00741 return CUBIT_FAILURE; 00742 00743 // Sort the list from low to high 00744 combined_param_list.sort(); 00745 00746 // Remove near values 00747 param_tol = param_tol*scale_factor; // Scale tolerance to length 00748 double prev_param; 00749 combined_param_list.reset(); 00750 prev_param = combined_param_list.get_and_step(); 00751 for( i=combined_param_list.size()-2; i--; ) 00752 { 00753 param = combined_param_list.get(); 00754 if( fabs(param - prev_param) < param_tol ) 00755 { 00756 combined_param_list.change_to( -1.0 ); 00757 } 00758 else 00759 { 00760 prev_param = param; 00761 } 00762 combined_param_list.step(); 00763 } 00764 combined_param_list.remove_all_with_value(-1.0); 00765 00766 // We need to check if there are near coincident points at the end of the list 00767 combined_param_list.last(); 00768 prev_param = combined_param_list.get_and_back(); 00769 param = combined_param_list.get(); 00770 // Use 10.0 * GEOMETRY_RESABS because Granite cannot handle points 00771 // any closer together when making a spline 00772 if( fabs( prev_param-param ) < 10.0*GEOMETRY_RESABS*scale_factor ) 00773 { 00774 // Remove the second to last value 00775 combined_param_list.last(); 00776 combined_param_list.back(); 00777 combined_param_list.remove(); 00778 00779 if( combined_param_list.size() < 2 ) 00780 return CUBIT_FAILURE; 00781 } 00782 00783 // Also check if there are near coincident points anywhere along the 00784 // other (shorter) side (very doubtful, but check anyway) 00785 if( scale_factor > 1.0 ) 00786 { 00787 param_tol = 10.0*GEOMETRY_RESABS*scale_factor; 00788 double prev_param; 00789 combined_param_list.reset(); 00790 prev_param = combined_param_list.get_and_step(); 00791 for( i=combined_param_list.size()-2; i--; ) 00792 { 00793 param = combined_param_list.get(); 00794 if( fabs(param - prev_param) < param_tol ) 00795 { 00796 combined_param_list.change_to( -1.0 ); 00797 } 00798 else 00799 { 00800 prev_param = param; 00801 } 00802 combined_param_list.step(); 00803 } 00804 combined_param_list.remove_all_with_value(-1.0); 00805 } 00806 00807 // Update this paramList 00808 if( isCollapsed ) 00809 { 00810 // This is a collapsed triangle side, so just stuff it with the proper 00811 // number of params and coordinates 00812 paramList.clean_out(); 00813 for( i=combined_param_list.size(); i--; ) 00814 paramList.append( 0.0 ); 00815 00816 // It will already have one coordinate - copy it to the others 00817 CubitVector *vec; 00818 vec = coordList.get(); 00819 for( i=combined_param_list.size()-1; i--; ) 00820 coordList.append( new CubitVector( *vec ) ); 00821 } 00822 else 00823 { 00824 paramList.clean_out(); 00825 paramList = combined_param_list; 00826 00827 // Generate this coordList. 00828 CubitVector vec; 00829 paramList.reset(); 00830 for( i=paramList.size(); i--; ) 00831 { 00832 param = paramList.get(); 00833 param = param/this_factor; // Normalize it 00834 paramList.change_to( param ); // Set proper value in paramList 00835 position_from_u( param, vec ); 00836 coordList.append( new CubitVector( vec ) ); 00837 paramList.step(); 00838 } 00839 } 00840 00841 // Do the same for the other side 00842 if( other_side->is_collapsed() ) 00843 { 00844 // This is a collapsed triangle side, so just stuff it with the proper 00845 // number of params and coordinates 00846 other_side->paramList.clean_out(); 00847 for( i=combined_param_list.size(); i--; ) 00848 other_side->paramList.append( 0.0 ); 00849 00850 // It will already have one coordinate - copy it to the others 00851 CubitVector *vec; 00852 vec = other_side->coordList.get(); 00853 for( i=combined_param_list.size()-1; i--; ) 00854 other_side->coordList.append( new CubitVector( *vec ) ); 00855 } 00856 else 00857 { 00858 combined_param_list.reset(); 00859 for( i=combined_param_list.size(); i--; ) 00860 { 00861 param = combined_param_list.get(); 00862 combined_param_list.change_to( other_side->paramHigh-param/other_factor ); 00863 combined_param_list.step(); 00864 } 00865 combined_param_list.reverse(); 00866 00867 CubitVector vec; 00868 other_side->paramList.clean_out(); 00869 other_side->paramList = combined_param_list; 00870 combined_param_list.reset(); 00871 for( i=combined_param_list.size(); i--; ) 00872 { 00873 param = combined_param_list.get_and_step(); 00874 other_side->position_from_u( param, vec ); 00875 other_side->coordList.append( new CubitVector( vec ) ); 00876 } 00877 } 00878 00879 return CUBIT_SUCCESS; 00880 } 00881 00882 //================================================================================ 00883 // Description: This class holds data on vertices for split across extend 00884 // Author : Steve Storm 00885 // Date : 10/7/2007 00886 //================================================================================ 00887 TDSplitSurfaceExtend::TDSplitSurfaceExtend() 00888 { 00889 successFlg = CUBIT_FALSE; 00890 } 00891 00892 TDSplitSurfaceExtend::~TDSplitSurfaceExtend() 00893 { 00894 }