cgma
TDSplitSurface.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines