cgma
SubCurve.cpp
Go to the documentation of this file.
00001 #include "SubCurve.hpp"
00002 #include "GMem.hpp"
00003 #include "GeometryQueryEngine.hpp"
00004 
00005 PartitionCurve* SubCurve::split( double param )
00006 {
00007   if( startParam <= endParam )
00008   {
00009     if( (param <= startParam) || (param >= endParam) )
00010       return 0;
00011   }
00012   else if( (param >= startParam) || (param <= endParam) )
00013     return 0;
00014     
00015   return new SubCurve( this, param );
00016 }
00017 
00018 CubitStatus SubCurve::combine( PartitionCurve* dead_curve )
00019 {
00020   SubCurve* curve = dynamic_cast<SubCurve*>(dead_curve);
00021   if( !curve || curve->real_curve() != this->real_curve() )
00022     return CUBIT_FAILURE;
00023   
00024   double dse = fabs(start_param() - dead_curve->end_param());
00025   double des = fabs(end_param() - dead_curve->start_param());
00026   
00027   if( des <= dse )
00028     endParam = curve->endParam;
00029   else 
00030     startParam = curve->startParam;
00031   
00032   return CUBIT_SUCCESS;
00033 }
00034   
00035   
00036        
00037 
00038 SubCurve::SubCurve( Curve* curve_ptr ) 
00039 {
00040   assert( dynamic_cast<SubEntitySet*>(curve_ptr->owner()) == 0 );
00041   new SubEntitySet( curve_ptr, this );
00042   
00043   
00044   startParam = curve_ptr->start_param();
00045   endParam = curve_ptr->end_param();
00046   
00047   double period;
00048   if( fabs( startParam - endParam ) < CUBIT_RESABS )
00049   {
00050     if( ! curve_ptr->is_periodic( period ) )
00051     {
00052       assert( 0 );
00053     }
00054     endParam = startParam + period ;
00055   }
00056   
00057   if( curve_ptr->bridge_sense() != this->bridge_sense() )
00058     reverse_bridge_sense();
00059 }
00060 
00061 SubCurve::SubCurve( SubCurve* split_from, double start )
00062 {
00063   split_from->sub_entity_set().add_partition( this, split_from );
00064   
00065   endParam = split_from->endParam;
00066   startParam = split_from->endParam = start;
00067 
00068   if( CUBIT_REVERSED == split_from->bridge_sense() )
00069     this->reverse_bridge_sense();
00070 }
00071 
00072 SubCurve::~SubCurve()
00073 {
00074 }
00075 
00076 int SubCurve::num_partitions() const
00077 {
00078   DLIList<TopologyBridge*> tmp;
00079   get_all_partitions( tmp );
00080   return tmp.size();
00081 }
00082 
00083 void SubCurve::get_all_partitions( DLIList<TopologyBridge*>& curves ) const
00084 {
00085   sub_entity_set().get_owners(curves);
00086 }
00087 
00088 CubitBox SubCurve::bounding_box() const
00089 {
00090 /*
00091   CubitVector start, end;
00092   SubCurve* me = (SubCurve*)this;
00093   me->position_from_u( me->start_param(), start );
00094   me->position_from_u( me->  end_param(),   end );
00095   CubitBox box( start, end );
00096   
00097   DLIList<CubitVector*> extrema;
00098   CubitSense sense;
00099   me->get_interior_extrema( extrema, sense );
00100   if( sense == CUBIT_REVERSED )
00101     extrema.reverse();
00102   while( extrema.size() )
00103   {
00104     CubitVector* v = extrema.pop();
00105     box |= *v;
00106     delete v;
00107   }
00108 */  
00109   return dynamic_cast<Curve*>(partitioned_entity())->bounding_box();
00110 }
00111 
00112 double SubCurve::measure()
00113 {
00114   return fabs(real_curve()->length_from_u( startParam, endParam ));
00115 }
00116 
00117 GeometryType SubCurve::geometry_type()
00118 {
00119   return real_curve()->geometry_type();
00120 }
00121 
00122 CubitStatus SubCurve::closest_point( const CubitVector& from, 
00123                                      CubitVector& closest,
00124                      CubitVector* tangent,
00125                      CubitVector* curvature,
00126                      double* param )
00127 {
00128   double u;
00129   CubitStatus result =
00130      real_curve()->closest_point( from, closest, tangent, curvature, &u );
00131   if( param )
00132     *param = u;
00133 
00134   // Snap position to the ends of the SubCurve if
00135   // necessary.
00136   if(result)
00137   {
00138     double lower, upper;
00139     double period;
00140 
00141     // If curve is periodic we first need to see if our location
00142     // can be mapped to the subcurve range just by adding or
00143     // subtracting multiples of the period.  If no then we
00144     // will snap it to one of the ends.
00145     int is_per = is_periodic(period);
00146 
00147     // Get the param range of the SubCurve (will probably 
00148     // be different from that of the underlying real curve).
00149     get_ordered_param_range(lower, upper);
00150 
00151     // If we are past the low end...
00152     if(u < lower)
00153     {
00154       // Adjust for periodic curve.
00155       if(is_per)
00156       {
00157         double tmp_u = u;
00158         while(tmp_u < upper + GEOMETRY_RESABS)
00159         {
00160           tmp_u += period;
00161           if(tmp_u > lower - GEOMETRY_RESABS &&
00162             tmp_u < upper + GEOMETRY_RESABS)
00163           {
00164             u = tmp_u;
00165           }
00166         }
00167       }
00168       // If the value of u was not adjusted because
00169       // of a periodic curve go ahead and snap to
00170       // the lower bound.
00171       if(u < lower)
00172       {
00173         u = lower;
00174       }
00175       // Update the position we will return.
00176       position_from_u(u, closest);
00177     }
00178     // If we are past the high end...
00179     else if(u > upper)
00180     {
00181       // Adjust for periodic curve.
00182       if(is_per)
00183       {
00184         double tmp_u = u;
00185         while(tmp_u > upper - GEOMETRY_RESABS)
00186         {
00187           tmp_u -= period;
00188           if(tmp_u > lower - GEOMETRY_RESABS &&
00189             tmp_u < upper + GEOMETRY_RESABS)
00190           {
00191             u = tmp_u;
00192           }
00193         }
00194       }
00195       // If the value of u was not adjusted because
00196       // of a periodic curve go ahead and snap to
00197       // the upper bound.
00198       if(u > upper)
00199       {
00200         u = upper;
00201       }
00202       // Update the position we will return.
00203       position_from_u(u, closest);
00204     }
00205   }
00206 
00207   if( result && tangent )
00208   {
00209     CubitVector start, end;
00210     if( !position_from_u( start_param(), start ) ||
00211         !position_from_u( end_param(), end ) )
00212       return CUBIT_FAILURE;
00213       
00214     double ds = (start - from).length_squared();
00215     double de = (end   - from).length_squared();
00216     const double rsq = GEOMETRY_RESABS * GEOMETRY_RESABS;
00217     if( ds < rsq && G1_discontinuous( u, &end, &start ) )
00218       *tangent = start;
00219     else if( de < rsq && G1_discontinuous( u, &end, &start ) )
00220       *tangent = end;
00221   }
00222   
00223   return result;
00224 }
00225 
00226 CubitPointContainment SubCurve::point_containment( const CubitVector& point )
00227 {
00228   CubitPointContainment cpc = real_curve()->point_containment( point );
00229   if( (cpc == CUBIT_PNT_INSIDE) || (cpc == CUBIT_PNT_ON) ||
00230       (cpc == CUBIT_PNT_BOUNDARY) )
00231   {
00232     double u = real_curve()->u_from_position( point );
00233     double lower, upper;
00234     get_ordered_param_range( lower, upper );
00235     if( u < lower || u > upper )
00236       cpc = CUBIT_PNT_OFF;
00237   }
00238 
00239   if( (cpc == CUBIT_PNT_INSIDE) || (cpc == CUBIT_PNT_ON) )
00240   {
00241     CubitVector start, end;
00242     position_from_u( start_param(), start );
00243     position_from_u( end_param(), end );
00244     if( (point-start).length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS ||
00245         (point-end  ).length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS )
00246     {
00247       cpc = CUBIT_PNT_BOUNDARY;
00248     }
00249   }
00250   
00251   return cpc;
00252 }
00253 
00254 CubitBoolean SubCurve::is_position_on( const CubitVector& position )
00255 {
00256   return real_curve()->is_position_on( position );
00257 }
00258 
00259 CubitBoolean SubCurve::G1_discontinuous( double param, 
00260                                          CubitVector* minus_tan,
00261                      CubitVector* plus_tan )
00262 {
00263   double lower, upper;
00264   get_ordered_param_range( lower, upper );
00265   if( param <= lower || param >= upper )
00266     return CUBIT_FALSE;
00267   
00268   CubitVector pos, start, end;
00269   if( !position_from_u( lower, start ) ||
00270       !position_from_u( upper, end   ) ||
00271       !position_from_u( param, pos   ) )
00272     assert(0);
00273   
00274   double ds = (pos - start).length_squared();
00275   double de = (pos - end  ).length_squared();
00276   const double grs = GEOMETRY_RESABS * GEOMETRY_RESABS;
00277   if( ds < grs || de < grs )
00278     return CUBIT_FALSE;
00279   
00280   return real_curve()->G1_discontinuous( param, minus_tan, plus_tan );
00281 }
00282 
00283 CubitStatus SubCurve::get_interior_extrema( DLIList<CubitVector*>& points, 
00284                                             CubitSense& sense )
00285 {
00286   assert( !points.size() );
00287   
00288   double lower, upper;
00289   get_ordered_param_range( lower, upper );
00290   
00291   CubitVector start, end;
00292   if( ! real_curve()->position_from_u( lower, start ) ||
00293       ! real_curve()->position_from_u( upper, end ) )
00294     return CUBIT_FAILURE;
00295   
00296   DLIList<CubitVector*> list;
00297   if( ! real_curve()->get_interior_extrema( list, sense ) ) 
00298     return CUBIT_FAILURE;
00299   if( list.size() == 0 )
00300     return CUBIT_SUCCESS;
00301   
00302   list.last();
00303   double param = real_curve()->u_from_position( *list.get() );
00304   while( (param <= lower) || (param >= upper) )
00305   {
00306     delete list.pop();
00307     if( list.size() == 0 )
00308       return CUBIT_SUCCESS;
00309     list.last();
00310     param = real_curve()->u_from_position( *list.get() );
00311   }
00312   
00313   double ds = (*list.get() - start).length_squared();
00314   double de = (*list.get() = end  ).length_squared();
00315   const double grs = GEOMETRY_RESABS * GEOMETRY_RESABS;
00316   if( ds < grs || de < grs )
00317   {
00318     delete list.pop();
00319     if( list.size() == 0 )
00320       return CUBIT_SUCCESS;
00321     list.last();
00322     param = real_curve()->u_from_position( *list.get() );
00323   }
00324   
00325   while( (param > lower) && (param < upper) )
00326   {
00327     points.append( list.pop() );
00328     if( list.size() == 0 )
00329       break;
00330     list.last();
00331     param = real_curve()->u_from_position( *list.get() );
00332   }
00333   
00334   while( list.size() )
00335     delete list.pop();
00336   
00337   if( sense == CUBIT_FORWARD )
00338     sense = CUBIT_REVERSED;
00339   else if( sense == CUBIT_REVERSED )
00340     sense = CUBIT_FORWARD;
00341   
00342   return CUBIT_SUCCESS;
00343 }
00344 
00345 CubitStatus SubCurve::get_center_radius( CubitVector& center, double& radius )
00346   { return real_curve()->get_center_radius(center,radius); }
00347 
00348 
00349 CubitBoolean SubCurve::get_param_range( double& lower, double& upper )
00350 {
00351   lower = startParam;
00352   upper = endParam;
00353   return CUBIT_TRUE;
00354 }
00355 
00356 CubitBoolean SubCurve::get_ordered_param_range( double& lower, double& upper )
00357 {
00358   if( startParam < endParam )
00359   {
00360     lower = startParam;
00361     upper = endParam;
00362   }
00363   else
00364   {
00365     lower = endParam;
00366     upper = startParam;
00367   }
00368   return CUBIT_TRUE;
00369 }
00370 
00371 double SubCurve::start_param()
00372   { return startParam; }
00373 double SubCurve::end_param()
00374   { return endParam; }
00375 
00376 CubitBoolean SubCurve::is_periodic( double& period )
00377 {
00378   return real_curve()->is_periodic( period );
00379 }
00380 
00381 double SubCurve::length_from_u( double u1, double u2 )
00382 {
00383   return real_curve()->length_from_u( u1, u2 );
00384 }
00385 
00386 double SubCurve::u_from_position( const CubitVector& p )
00387 {
00388   double result = real_curve()->u_from_position( p );
00389   fixup_periodic_param(result);
00390   return result;
00391 }
00392 
00393 CubitStatus SubCurve::position_from_u( double u, CubitVector& p )
00394 {
00395   return real_curve()->position_from_u( u, p );
00396 }
00397 
00398 double SubCurve::u_from_arc_length( double root, double length )
00399 {
00400   return real_curve()->u_from_arc_length( root, length );
00401 }
00402 
00403 void SubCurve::fixup_periodic_param( double& param ) const
00404 {
00405   double period;
00406   if( ! real_curve()->is_periodic(period) )
00407     return;
00408   
00409   assert(period > GEOMETRY_RESABS);
00410   double start, end;
00411   if ( startParam < endParam ) {
00412     start = startParam;
00413     end = endParam;
00414   } else {
00415     start = endParam;
00416     end = startParam;
00417   }
00418   
00419   if( fabs( start-param ) < GEOMETRY_RESABS )
00420     param = start;
00421   if( fabs( end-param ) < GEOMETRY_RESABS )
00422     param = end;
00423 
00424   while ( param > end )
00425     param -= period;
00426   while ( param < start )
00427     param += period;
00428 }
00429 
00430 CubitStatus SubCurve::get_graphics( GMem& result,
00431                             double angle_tolerance,
00432                             double distance_tolerance,
00433                             double max_edge_length )
00434 {
00435   if (POINT_CURVE_TYPE == this->geometry_type())
00436   {
00437     result.pointListCount = 0;
00438     return CUBIT_SUCCESS;
00439   }
00440 
00441   int i;
00442   if( !real_curve()->get_geometry_query_engine()->
00443     get_graphics( real_curve(), &result, angle_tolerance, distance_tolerance, max_edge_length ) )
00444     return CUBIT_FAILURE;
00445 
00446   if (0 == result.pointListCount)
00447     return CUBIT_FAILURE;
00448   
00449   double lo, hi, start_param, end_param;
00450   get_ordered_param_range( lo, hi );
00451   get_param_range(start_param, end_param);
00452   DLIList<double> param_list( result.pointListCount );
00453 
00454   // don't use first and last points -- this avoids projection
00455   // close to a seam on a periodic curve.  The projection can
00456   // jump the seam and cause endpoints of the curve to incorrectly
00457   // fall inside the parameter range causing extra segments to be drawn
00458   for( i = 1; i < result.pointListCount-1; i++ )
00459   {
00460     CubitVector v( result.point_list()[i].x, 
00461                    result.point_list()[i].y,
00462                    result.point_list()[i].z );
00463     double u = real_curve()->u_from_position( v );
00464     if( (u >= lo) && (u <= hi) ) 
00465       param_list.append( u );
00466   }
00467   
00468   CubitVector start_pt, end_pt;
00469   position_from_u( start_param, start_pt );
00470   position_from_u( end_param, end_pt );
00471   
00472   bool append_start = true, append_end = true;
00473   if( param_list.size() > 0 )
00474   {
00475     CubitVector first_pt, last_pt;
00476     param_list.last();
00477     position_from_u( param_list.get(), last_pt );
00478     param_list.reset();
00479     position_from_u( param_list.get(), first_pt );
00480   
00481     double d1 = (start_pt - first_pt).length_squared();
00482     double d2 = (start_pt - last_pt ).length_squared();
00483     double d4 = (  end_pt - first_pt).length_squared();
00484     double d3 = (  end_pt - last_pt ).length_squared();
00485     double forward = d1 + d3;
00486     double reverse = d2 + d4;
00487     if( reverse < forward )
00488     {
00489       CubitVector tmp( start_pt );
00490       start_pt = end_pt;
00491       end_pt = tmp;
00492       d1 = d2;
00493       d3 = d4;
00494     }
00495     
00496     if( d1 < (GEOMETRY_RESABS*GEOMETRY_RESABS) )
00497       append_start = false;
00498     if( d3 < (GEOMETRY_RESABS*GEOMETRY_RESABS) )
00499       append_end = false;
00500   }
00501       
00502   int index = 0;
00503   result.allocate_polylines( param_list.size() + 1 );
00504 
00505   if( append_start )
00506   {
00507     result.point_list()[index].x = (float)(start_pt.x());
00508     result.point_list()[index].y = (float)(start_pt.y());
00509     result.point_list()[index].z = (float)(start_pt.z());
00510     index++;
00511   }
00512   
00513   param_list.reset();
00514   CubitVector position;
00515   for( i = param_list.size(); i--; )
00516   {
00517     position_from_u( param_list.get_and_step(), position );
00518     result.point_list()[index].x = (float)(position.x());
00519     result.point_list()[index].y = (float)(position.y());
00520     result.point_list()[index].z = (float)(position.z());
00521     index++;
00522   }
00523 
00524   if( append_end )
00525   {
00526     result.point_list()[index].x = (float)(end_pt.x());
00527     result.point_list()[index].y = (float)(end_pt.y());
00528     result.point_list()[index].z = (float)(end_pt.z());
00529     index++;
00530   }
00531   
00532   result.pointListCount = index;
00533   return CUBIT_SUCCESS;
00534 }
00535 
00536   
00537 void SubCurve::reverse_sense()
00538 {
00539   reverse_point_order();
00540   if( owner() )
00541     owner()->notify_reversed(this);
00542 }
00543 
00544 CubitStatus SubCurve::save( CubitSimpleAttrib& attrib )
00545 {
00546   int id = sub_entity_set().get_id(this);
00547   if( id <= 0 ) return CUBIT_FAILURE;
00548   
00549   DLIList<int> end_points(4);
00550   get_save_topology(end_points);
00551 
00552   return sub_entity_set().save_geometry( id, 1, 0, 0, &end_points, 0, attrib );
00553 }
00554 
00555 CubitStatus SubCurve::get_spline_params
00556 (
00557   bool &rational,    // return true/false
00558   int &degree,       // the degree of this spline
00559   DLIList<CubitVector> &cntrl_pts,  // xyz position of controlpoints
00560   DLIList<double> &cntrl_pt_weights, // if rational, a weight for each cntrl point.
00561   DLIList<double> &knots,   // There should be order+cntrl_pts.size()-2 knots
00562   bool &spline_is_reversed
00563 ) const
00564 {
00565   PRINT_ERROR("Currently, Cubit is unable to determine spline parameters for SubCurves.\n");
00566   return CUBIT_FAILURE;
00567 }
00568 
00569 CubitStatus SubCurve::get_ellipse_params
00570 (
00571   CubitVector &center_vec,
00572   CubitVector &normal,
00573   CubitVector &major_axis,
00574   double &radius_ratio
00575 ) const
00576 {
00577   PRINT_ERROR("Currently, Cubit is unable to determine ellipse parameters for SubCurves.\n");
00578   return CUBIT_FAILURE;
00579 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines