cgma
SegmentedCurve.cpp
Go to the documentation of this file.
00001 //-------------------------------------------------------------------------
00002 // Filename      : SegmentedCurve.cc
00003 //
00004 // Purpose       : 
00005 //
00006 // Special Notes : The parameterization of this is defined such that the
00007 //                 parameter range between two adjacent nodes is one.
00008 //
00009 // Creator       : Jason Kraftcheck
00010 //
00011 // Creation Date : 06/10/98
00012 //-------------------------------------------------------------------------
00013 
00014 #include "SegmentedCurve.hpp"
00015 
00016 #include "PartitionPoint.hpp"
00017 #include "PartitionCoEdge.hpp"
00018 #include "PartitionSurface.hpp"
00019 #include "PartitionLump.hpp"
00020 #include "GMem.hpp"
00021 #include "PartitionEngine.hpp"
00022 #include "CubitTransformMatrix.hpp"
00023 #include "CubitMessage.hpp"
00024 
00025 int SegmentedCurve::segment_from_u( double& param )
00026 {
00027   if( is_periodic() ) 
00028     normalize_periodic_parameter( param );
00029   
00030   int num_segments = point_count() - 1;
00031   if( param < -CUBIT_RESABS ||
00032       param > (num_segments + CUBIT_RESABS) )
00033     return -1;
00034   
00035     // Could call trunc() here, but why?  Need to cast to an
00036     // int anyway.  Also, the cast to int should be save 
00037     // because the magnitude of param is tested above.
00038   int segment_index = (int)param;
00039   if( segment_index == num_segments )
00040     --segment_index;
00041   
00042   param -= segment_index;
00043   return segment_index;
00044 }
00045 
00046 PartitionCurve* SegmentedCurve::split( double param )
00047 {
00048   int seg = segment_from_u(param);
00049   if( seg < 0 )
00050     return 0;  
00051   
00052   CubitVector beg = position(seg);
00053   CubitVector end = position(seg+1);
00054   CubitVector pos = beg + param * (end - beg);
00055   
00056   if( (pos - end).length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS )
00057   {
00058     seg++;
00059     param = 0;
00060     beg = pos = end;
00061     
00062     if( seg == point_count() - 1 )
00063       return 0;
00064   }
00065   else if( (pos - beg).length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS )
00066   {
00067     if( seg == 0 )
00068       return 0;
00069       
00070     pos = beg;
00071     param = 0;
00072   }
00073   
00074   SegmentedCurve* new_curve = new SegmentedCurve( this, point_count() - seg );
00075   
00076   new_curve->point_list[0] = pos;
00077   for( int i = 1; i < new_curve->point_list.size(); i++ )
00078     new_curve->point_list[i] = point_list[seg + i];
00079   if( param == 0 )
00080   {
00081     point_list.size( seg + 1 );
00082   }
00083   else
00084   {
00085     point_list.size( seg + 2 );
00086     point_list[seg+1] = pos;
00087   }
00088     
00089   return new_curve;
00090 }
00091 
00092 CubitStatus SegmentedCurve::combine( PartitionCurve* dead_curve )
00093 {
00094   SegmentedCurve* dead = dynamic_cast<SegmentedCurve*>(dead_curve);
00095   if( !dead || dead->partitioned_entity() != this->partitioned_entity() )
00096     return CUBIT_FAILURE;
00097   
00098   CubitVector this_start = this->position(0);
00099   CubitVector dead_start = dead->position(0);
00100   CubitVector this_end   = this->position( this->point_count() - 1 );
00101   CubitVector dead_end   = dead->position( dead->point_count() - 1 );
00102   
00103   int i;
00104   bool append, reverse;
00105   const double tol_sqr = GEOMETRY_RESABS * GEOMETRY_RESABS;
00106   if( (this_end - dead_start).length_squared() < tol_sqr )
00107   {
00108     append = true;
00109     reverse = false;
00110   }
00111   else if( (this_end - dead_end).length_squared() < tol_sqr )
00112   {
00113     append = true;
00114     reverse = true;
00115   }
00116   else if( (this_start - dead_end).length_squared()  < tol_sqr )
00117   {
00118     append = false;
00119     reverse = false;
00120   }
00121   else if( (this_start - dead_start).length_squared() < tol_sqr )
00122   {
00123     append = false;
00124     reverse = true;
00125   }
00126   else
00127   {
00128     assert(0);
00129     return CUBIT_FAILURE;
00130   }
00131   
00132   if( reverse )
00133     dead->point_list.reverse();
00134   
00135   int this_point_count = this->point_list.size();
00136   int dead_point_count = dead->point_list.size();
00137   int new_point_count = this_point_count + dead_point_count - 1;
00138   this->point_list.size(new_point_count);
00139   
00140   if( append )
00141   {
00142     for( i = 1; i < dead_point_count; i++ )
00143       point_list[this_point_count + i - 1] = dead->point_list[i];
00144   }
00145   else
00146   {
00147     for( i = 1; i <= this_point_count; i++ )
00148       point_list[new_point_count-i] = point_list[this_point_count-1];
00149     
00150     for( i = 0; i < dead_point_count; i++ )
00151       this->point_list[i] = dead->point_list[i];
00152   }
00153     
00154   return CUBIT_SUCCESS;
00155 }  
00156       
00157   
00158 
00159 CubitBoolean SegmentedCurve::is_linear()
00160 {
00161   int i, count = point_count();
00162   if( count == 2 ) return CUBIT_TRUE;
00163   if( is_periodic() ) return CUBIT_FALSE;
00164   
00165   CubitVector mean(0.0,0.0,0.0);
00166   for( i = 1; i < count; i++ ) mean += (position(i)-position(i-1));
00167   mean.normalize();
00168   for( i = 1; i < count; i++ )
00169   {
00170     if( (1-(mean % ~(position(i)-position(i-1)))) > CUBIT_RESABS )
00171       return CUBIT_FALSE;
00172   }
00173   return CUBIT_TRUE;
00174 }
00175 
00176 CubitStatus SegmentedCurve::get_point_direction( 
00177   CubitVector& origin, CubitVector& direction )
00178 {
00179   if( ! is_linear() ) return CUBIT_FAILURE;
00180   origin = position(0);
00181   direction = ~(position(point_count()-1) - origin);
00182   return CUBIT_SUCCESS;
00183 }
00184 
00185 double SegmentedCurve::length_from_u( double param1, double param2 )
00186 {
00187   if( param1 > param2 )
00188   {
00189     double temp = param1;
00190     param1 = param2;
00191     param2 = temp;
00192   }
00193   
00194   if( is_periodic() )
00195   {
00196     normalize_periodic_parameter( param1 );
00197     normalize_periodic_parameter( param2 );
00198   }
00199   
00200   int first = (int)floor( param1 );
00201   int last = (int)floor( param2 );
00202   int seg_count = point_count() - 1;
00203 
00204   //check for errors, round a little
00205   if( first < 0 )
00206   {
00207     if( param1 > -CUBIT_RESABS ) first = 0;
00208     else return -1.0;
00209   }
00210   if( last < 0 )
00211   {
00212     if( param2 > -CUBIT_RESABS ) last = 0;
00213     else return -1.0;
00214   }
00215   if( last >= seg_count )
00216   {
00217     if( param2 < (CUBIT_RESABS + seg_count) )
00218       last--;
00219     else return -1.0;
00220   }
00221   if( first >= seg_count )
00222   {
00223     if( param1 < (CUBIT_RESABS + seg_count) )
00224       first--;
00225     else return -1.0;
00226   }
00227     
00228   //calculate the remaining length on the first segment
00229   
00230   double length_sum = segment_length( first ) * (1 - (param1 - first) );
00231   
00232   //add up the remaining segments upto and including last
00233   
00234   for( int i = first + 1; i <= last; i++ )
00235     length_sum += segment_length( i );
00236     
00237   // by including the last segment, we (may have) gone too far,
00238   // so subtract back off the extra on the last segment
00239   
00240   length_sum -= segment_length(last) * (1 - (param2 - last) );
00241   
00242   return length_sum;
00243 
00244 }
00245 
00246 CubitBoolean SegmentedCurve::get_param_range( double& lower, double& upper )
00247 {
00248   lower = 0.0;
00249   upper = double(point_count() - 1);
00250   return CUBIT_TRUE;
00251 }
00252 
00253 CubitStatus SegmentedCurve::closest_point(
00254   CubitVector const& location,
00255   CubitVector& closest_location,
00256   CubitVector* tangent_ptr,
00257   CubitVector* curvature_ptr,
00258   double* param)
00259 {
00260   double seg_param;
00261   int segment_no = closest_segment( location, &seg_param, &closest_location );
00262   
00263   if ( Surface* surf = dynamic_cast<Surface*>(partitioned_entity()) )
00264   {
00265     CubitVector seg_point(closest_location);
00266     surf->closest_point( seg_point, &closest_location );
00267   }
00268   
00269   if( tangent_ptr != NULL )
00270   {
00271     //First check if the closest point is at the join of
00272     //two segments.  If so, return the average of the two 
00273     //tangets.
00274     if( (seg_param < CUBIT_RESABS) && (segment_no > 0) )
00275     {
00276       CubitVector seg1_start = position( segment_no - 1 );
00277       CubitVector seg2_end   = position( segment_no + 1 );
00278       *tangent_ptr = seg2_end - seg1_start;
00279     }
00280     
00281     //ditto
00282     else if( ( (1.0 - seg_param) < CUBIT_RESABS ) && 
00283              ( segment_no < (point_count() - 2) ) )
00284     {
00285       CubitVector seg1_start = position( segment_no );
00286       CubitVector seg2_end   = position( segment_no + 2 );
00287       *tangent_ptr = seg2_end - seg1_start;
00288     }
00289     
00290     //The segment_no is the index of the point beginning the segment.
00291     //A segment_no equal to point_count() - 1, the last point is 
00292     //possible.  So, for any segment point but the last, return the
00293     //tangent of the segment beginning with the point at segment_no.
00294     else if( segment_no < point_count() - 1 )
00295     {
00296       *tangent_ptr = this->position( segment_no + 1 ) 
00297         - this->position( segment_no );
00298     }
00299     
00300     else if( segment_no == 0 )
00301     {
00302       *tangent_ptr = this->position( segment_no + 1 )
00303         - this->position( segment_no );
00304     }
00305     
00306     //If the point is the last one, return the direction of
00307     //the last segment (this point and the previous one.)
00308     else 
00309     {
00310       *tangent_ptr = this->position( segment_no ) 
00311         - this->position( segment_no - 1 );
00312     }
00313     
00314     tangent_ptr->normalize();
00315   }
00316   
00317   //There is never a valid curvature for a segmented curve.  
00318   //The curvature is either infinity in the interior of segments,
00319   //or zero at the points between segments.  Just return zero.
00320   if( curvature_ptr != NULL )
00321   {
00322     curvature_ptr->set( 0., 0., 0. );
00323   }
00324 
00325   if (param)
00326   {
00327     *param = double(segment_no) + seg_param;
00328   }
00329   
00330   return CUBIT_SUCCESS;
00331 }
00332 
00333 CubitStatus SegmentedCurve::closest_point_trimmed( 
00334   CubitVector const& from_pt, CubitVector& result_pt ) 
00335 {
00336   return closest_point( from_pt, result_pt );
00337 }
00338 
00339 int SegmentedCurve::closest_segment( CubitVector const& location,
00340                                      double* seg_fraction,
00341                                      CubitVector* closest_pt )
00342 {  
00343   int length_ = point_count();
00344   
00345   int segment_no = 0;
00346   CubitVector start = position( 0 );
00347   CubitVector end = position( 1 );
00348   CubitVector dir = end - start;
00349   double seg_param = closest_point_on_segment( start, dir, location );
00350   CubitVector point = start + seg_param * dir;
00351   if( closest_pt ) *closest_pt = point;
00352   double shortest = (point - location ).length_squared();
00353    
00354   for( int i = 2; i < length_; i++ )
00355   {
00356     start = end;
00357     end = position( i );
00358     dir = end - start;
00359     double param = closest_point_on_segment( start, dir, location );
00360     point = start + param * dir;
00361     double dist = (point - location).length_squared();
00362     if( dist < shortest )
00363     {
00364       shortest = dist;
00365       if( closest_pt ) *closest_pt = point;
00366       segment_no = i - 1;
00367       seg_param = param;
00368     }
00369   }
00370   
00371   if( seg_fraction ) *seg_fraction = seg_param;  
00372   return segment_no;
00373 }
00374 
00375 double SegmentedCurve::u_from_position( const CubitVector& position )
00376 {
00377   double seg_param;
00378   int segment = closest_segment( position, &seg_param );
00379   return double(segment) + seg_param;
00380 }
00381 
00382 CubitStatus SegmentedCurve::position_from_u( double u, CubitVector& p)
00383 {
00384   double fraction = u;
00385   int segment_no = segment_from_u(fraction);
00386   if( segment_no < 0 )
00387     return CUBIT_FAILURE;
00388     
00389   CubitVector s = position( segment_no );
00390   CubitVector e = position( segment_no+1 );
00391   p = s + fraction * ( e - s );
00392   
00393   if ( Surface* surf = dynamic_cast<Surface*>(partitioned_entity()) )
00394   {
00395     CubitVector seg_pos(p);
00396     surf->closest_point( seg_pos, &p );
00397   }
00398 
00399   return CUBIT_SUCCESS;
00400 }
00401 
00402 double SegmentedCurve::u_from_arc_length( double param, double length )
00403 {
00404   if( fabs(length) < CUBIT_RESABS ) 
00405     return param;
00406   
00407   double fraction = param;  
00408   int segment = segment_from_u( fraction );
00409   if( segment < 0 )
00410     return param;
00411   
00412   //Find the length of the remaining portion of the first
00413   //segment (after the base param.)
00414   double seg_len = segment_length( segment );
00415 // BWC  double len_sum = seg_len * ( 1.0 - param + segment );
00416   double len_sum;
00417   
00418   if(length < 0.0)
00419     len_sum = seg_len*(param-segment);
00420   else
00421     len_sum = seg_len * ( 1.0 - param + segment );
00422   
00423   //If the passed base param and length correspond to a
00424   //portion of the curve which lies entirely on a single
00425   //segment, return the passed base param plus the 
00426   //fraction of the segment (the parameter range for a 
00427   //segment is one.)
00428 //BWC  if( len_sum >= length ) 
00429   if(length < 0.0)
00430   {
00431     if(-len_sum < length)
00432       return param + ((seg_len > CUBIT_DBL_MIN ) ? length / seg_len : 0.0);
00433   }
00434   else
00435   {
00436     if( len_sum >= length ) 
00437       return param + ((seg_len > CUBIT_DBL_MIN ) ? length / seg_len : 0.0);
00438   }
00439   
00440   //Increment the total length until we have passed up
00441   //the specified arc length.
00442   /*
00443   BWC
00444   while( length > len_sum)
00445   {
00446     segment++;
00447     if( segment >= point_count() - 1 ) return -1.0;
00448     seg_len = segment_length( segment );
00449     len_sum += seg_len;
00450     if(fabs(len_sum-length) < GEOMETRY_RESABS)
00451       len_sum = length;
00452  }
00453  */
00454   if(length < 0.0)
00455   {
00456     while( fabs(length) > len_sum )
00457     {
00458       segment--;
00459       if( segment < 0 ) return -1.0;
00460       seg_len = segment_length( segment );
00461       len_sum += seg_len;
00462       if(fabs(len_sum+length) < GEOMETRY_RESABS)
00463         len_sum = -length;
00464     }
00465   }
00466   else
00467   {
00468     while( length > len_sum )
00469     {
00470       segment++;
00471       if( segment >= point_count() - 1 ) return -1.0;
00472       seg_len = segment_length( segment );
00473       len_sum += seg_len;
00474       if(fabs(len_sum-length) < GEOMETRY_RESABS)
00475         len_sum = length;
00476     }
00477   }
00478   
00479   //Now subtract off the extra length on the last segment,
00480   //the amount passed the specified arc length.  The ratio
00481   //of this length to the total length of the last segment
00482   //is the about we overshot the desired parameter value.
00483   if(length < 0.0)
00484   {
00485     if( seg_len > CUBIT_DBL_MIN )
00486       return (double)(segment) + (len_sum + length)/seg_len;
00487     else 
00488       return (double)(segment);
00489   }
00490   else
00491   {
00492     if( seg_len > CUBIT_DBL_MIN )
00493       return (double)(segment + 1) - (len_sum - length)/seg_len;
00494     else 
00495       return (double)(segment + 1);
00496   }
00497 }
00498 
00499 CubitBoolean SegmentedCurve::is_position_on( const CubitVector& pos )
00500 {
00501   //Get the segment to test on
00502   CubitVector v;
00503   closest_segment( pos, NULL, &v);
00504   
00505   return (pos - v).length() <= GEOMETRY_RESABS ? CUBIT_TRUE : CUBIT_FALSE;
00506 }
00507 
00508 CubitBox SegmentedCurve::bounding_box() const
00509 {
00510   CubitBox b( position( 0 ) );
00511   for( int i = 1; i < point_count(); i++ )
00512     b |= position( i );
00513 
00514   return b;
00515 }
00516 
00517 double SegmentedCurve::measure()
00518 {
00519   double len = 0;
00520   for( int i = 0; i < point_count() - 1; i++ )
00521   {
00522     len += segment_length( i );
00523   }
00524   return len;
00525 }
00526 
00527 CubitStatus SegmentedCurve::get_interior_extrema( 
00528                                 DLIList<CubitVector*>& interior_points,
00529                                 CubitSense& return_sense )
00530 {
00531   return_sense = CUBIT_FORWARD;
00532   
00533   //For each point, check the segments to either side.  If any of deltaX, 
00534   //deltaY or deltaZ have opposite signs for the two segments, then the
00535   //point is an extrema in x, y, or z, respectively.
00536   int count = point_count() - 1; //stop with second-to-last point
00537   int prev_index = 0;
00538 
00539   for( int i = 1; i < count; i++ )
00540   {
00541     CubitVector curr = position(i+1) - position(i);
00542     CubitVector prev = position( i ) - position( prev_index );
00543     if( (prev.x()*curr.x() < 0.0) || (prev.y()*curr.y()<0.0) || (prev.z()*curr.z()<0.0) )
00544     {
00545       interior_points.append( new CubitVector( position(i) ) );
00546       prev_index = i;
00547     }
00548   }
00549   return CUBIT_SUCCESS;
00550 }
00551 
00552 CubitStatus SegmentedCurve::get_center_radius( CubitVector&, double& )
00553   { return CUBIT_FAILURE; }
00554   
00555 
00556 double SegmentedCurve::closest_point_on_segment( 
00557                                               const CubitVector& base,
00558                                               const CubitVector& dir,
00559                                               const CubitVector& location )
00560 {
00561   if( dir.length_squared() < CUBIT_DBL_MIN ) return 0.0;
00562   
00563   //Find closest location to infinite line
00564   double param = dir % ( location - base ) / dir.length_squared();
00565   
00566   //Trim to segment
00567   if( param < 0.0 ) param = 0.0;
00568   else if( param > 1.0 ) param = 1.0;
00569   
00570   return param;
00571 }
00572 
00573 //-------------------------------------------------------------------------
00574 // Purpose       : Check for G1 discontinuities
00575 //
00576 // Special Notes : 
00577 //
00578 // Creator       : Jason Kraftcheck
00579 //
00580 // Creation Date : 05/03/00
00581 //-------------------------------------------------------------------------
00582 CubitBoolean SegmentedCurve::G1_discontinuous( double param,
00583                                             CubitVector* minus_tangent,
00584                                             CubitVector* plus_tangent )
00585 {
00586   if( is_periodic() ) normalize_periodic_parameter( param );
00587   
00588   double lower = floor( param );
00589   double upper = ceil( param );
00590   int first_point = -1;
00591   int last = point_count() - 1;
00592   if( last < 2 ) return CUBIT_FALSE;
00593 
00594   //If the parameter value corresponds to the start of a segment,
00595   //and that segment is not the first one
00596   if( ((param - lower) < CUBIT_RESABS) && (int(lower) != 0) )
00597     first_point = int(lower) - 1;
00598   //If the parameter value corresponds to the end of a segment,
00599   //and that segment is not the last one
00600   else if( ((upper - param) < CUBIT_RESABS) && (int(upper) < last ) )
00601     first_point = int(upper);
00602   //If the parameter value corresponds to the start or end of the
00603   //curve, and the curve is a closed, periodic curve.
00604   else if( is_periodic() && (fabs(start_param() - end_param()) < CUBIT_RESABS) &&
00605            ((((param - lower) < CUBIT_RESABS) && (int(lower) == 0)) ||
00606             (((upper - param) < CUBIT_RESABS) && (int(upper) == last)) ) )
00607     first_point = last - 1;
00608   //Otherwise the point is in the interior of a segment
00609   else return CUBIT_FALSE;
00610   
00611   int third_point = first_point + 2;
00612   if( third_point > last )
00613   {
00614     if( is_periodic() )
00615     {
00616       third_point = (third_point + 1) % point_count();
00617     }
00618     else
00619     {
00620       return CUBIT_FALSE;
00621     }
00622   }
00623 
00624   CubitVector tan1, tan2;
00625   tan1 = position( first_point + 1 ) - position( first_point );
00626   tan2 = position( third_point ) - position( first_point + 1 );
00627   if( (tan1 * tan2).length_squared() < CUBIT_RESABS )
00628     return CUBIT_FALSE;
00629   
00630   if( minus_tangent ) *minus_tangent = tan1;
00631   if( plus_tangent )  *plus_tangent = tan2;
00632   return CUBIT_TRUE;
00633 }
00634 
00635 
00636 //-------------------------------------------------------------------------
00637 // Purpose       : If the curve is periodic, adjust the param value to
00638 //                 be in the base range.
00639 //
00640 // Special Notes : 
00641 //
00642 // Creator       : Jason Kraftcheck
00643 //
00644 // Creation Date : 05/15/00
00645 //-------------------------------------------------------------------------
00646 void SegmentedCurve::normalize_periodic_parameter( double& u ) 
00647 {
00648   //The parameter range for a segmented curve is always (by my implementation)
00649   //from zero to some positive n.  And the period is equal to that n.  This 
00650   //simplifies the following a lot. -jk
00651   double period;
00652   if( is_periodic( period ) )
00653   {
00654     if( u > period )
00655       u = fmod( u, period );
00656     else if( u < -period ) 
00657       u = fmod( u, period ) + period;
00658     else if( u < 0.0 )
00659       u += period;  //fmod() seems to be expensive, so avoid it here.
00660   }
00661 }
00662 
00663 //-------------------------------------------------------------------------
00664 // Purpose       : Constructor
00665 //
00666 // Special Notes : 
00667 //
00668 // Creator       : Jason Kraftcheck
00669 //
00670 // Creation Date : 05/15/00
00671 //-------------------------------------------------------------------------
00672 SegmentedCurve::SegmentedCurve( PartitionSurface* surf, 
00673                                 DLIList<CubitVector*>& points )
00674   : point_list( points.size() )
00675 {
00676   points.reset();
00677   for( int i = 0; i < points.size(); i++ )
00678     point_list[i] = *points.get_and_step();
00679   
00680   surf->sub_entity_set().add_lower_order( this );
00681 }
00682 SegmentedCurve::SegmentedCurve( PartitionLump* vol, 
00683                                 DLIList<CubitVector*>& points )
00684   : point_list( points.size() )
00685 {
00686   points.reset();
00687   for( int i = 0; i < points.size(); i++ )
00688     point_list[i] = *points.get_and_step();
00689   
00690   vol->sub_entity_set().add_lower_order( this );
00691 }
00692 
00693 
00694 SegmentedCurve::SegmentedCurve( SegmentedCurve* curve, int ptcount )
00695   : point_list(ptcount)
00696 {
00697   curve->sub_entity_set().add_lower_order(this);
00698 }
00699  
00700 
00701 SegmentedCurve::~SegmentedCurve()
00702 {
00703 }
00704 
00705 int SegmentedCurve::point_count() const
00706 {
00707   return point_list.size();
00708 }
00709 
00710 double SegmentedCurve::segment_length( int segment_no ) const
00711 {
00712   return (point_list[segment_no+1] - point_list[segment_no]).length();
00713 }
00714 
00715 CubitVector SegmentedCurve::position( int index ) const
00716 {
00717   return point_list[index];
00718 }
00719 
00720   
00721 CubitStatus SegmentedCurve::get_graphics( GMem& result, 
00722                                     double /*angle_tolerance*/,
00723                                     double /*distance_tolerance*/,
00724                                     double /*max_edge_length*/)
00725 {
00726   result.allocate_polylines( point_count()-1 );
00727   for( int i = 0; i < point_count(); i++ )
00728   {
00729     CubitVector v = position(i);
00730     result.point_list()[i].x = (float)(v.x());
00731     result.point_list()[i].y = (float)(v.y());
00732     result.point_list()[i].z = (float)(v.z());
00733   }
00734   result.pointListCount = point_count();
00735   return CUBIT_SUCCESS;
00736 }
00737 
00738 CubitBoolean SegmentedCurve::is_periodic( double& period )
00739 {
00740   if( is_periodic() )
00741   {
00742     period = end_param() - start_param();
00743     return CUBIT_TRUE;
00744   }
00745   return CUBIT_FALSE;
00746 }
00747 
00748 CubitBoolean SegmentedCurve::is_periodic() const
00749 {
00750   return start_point() == end_point();
00751 }
00752 
00753 CubitPointContainment SegmentedCurve::point_containment( const CubitVector& pos )
00754 {
00755   const double tol_sqr = GEOMETRY_RESABS * GEOMETRY_RESABS;
00756   if( (start_point()->coordinates() - pos).length_squared() < tol_sqr )
00757     return CUBIT_PNT_BOUNDARY;
00758   else if( (end_point()->coordinates() - pos).length_squared() < tol_sqr )
00759     return CUBIT_PNT_BOUNDARY;
00760   else if( is_position_on( pos ) )
00761     return CUBIT_PNT_ON;
00762   else 
00763     return CUBIT_PNT_OFF;
00764 }
00765 
00766 
00767 CubitStatus SegmentedCurve::get_segments( DLIList<CubitVector*>& list )
00768 {
00769   for( int i = 0; i < point_count(); i++ )
00770     list.append( new CubitVector( position(i) ) );
00771   return CUBIT_SUCCESS;
00772 }
00773 
00774 void SegmentedCurve::reverse_sense()
00775 {
00776   point_list.reverse();
00777   reverse_point_order();
00778   if( owner() )
00779     owner()->notify_reversed(this);
00780 }
00781 
00782 CubitStatus SegmentedCurve::save( CubitSimpleAttrib& attrib )
00783 {
00784   DLIList<CubitVector*> segments;
00785   get_segments(segments);
00786   
00787   DLIList<int> topo;
00788   get_save_topology( topo );
00789   
00790   int id = sub_entity_set().get_id(this);
00791   
00792   return sub_entity_set().save_geometry( id, 1, &segments, 0, &topo, 0, attrib );
00793 }
00794 
00795 SegmentedCurve* SegmentedCurve::construct( const CubitSimpleAttrib& attrib,
00796                                            PartitionEntity* parent )
00797 {
00798   PartitionSurface* owning_surf = dynamic_cast<PartitionSurface*>(parent);
00799   PartitionLump* owning_lump = dynamic_cast<PartitionLump*>(parent);
00800   if( !owning_surf && !owning_lump )
00801     return 0;
00802   
00803   DLIList<int> vertex_conn;
00804   SegmentedCurve* result = new SegmentedCurve( parent, attrib, vertex_conn );
00805   
00806   if( vertex_conn.size() != 4 )
00807   {
00808     delete result;
00809     return 0;
00810   }
00811   
00812   PartitionPoint *start = 0, *end = 0;
00813   PartitionEntity* ent;
00814   vertex_conn.reset();
00815   int set_id = vertex_conn.get_and_step();
00816   int ent_id = vertex_conn.get_and_step();
00817   ent = PartitionEngine::instance().entity_from_id(set_id,ent_id,parent->sub_entity_set());
00818   start = dynamic_cast<PartitionPoint*>(ent);
00819   set_id = vertex_conn.get_and_step();
00820   ent_id = vertex_conn.get_and_step();
00821   ent = PartitionEngine::instance().entity_from_id(set_id,ent_id,parent->sub_entity_set());
00822   end = dynamic_cast<PartitionPoint*>(ent);
00823   if( !start || !end )
00824   {
00825     delete result;
00826     return 0;
00827   }
00828   
00829   result->start_point(start);
00830   result->end_point(end);
00831   return result;
00832 }
00833   
00834   
00835 SegmentedCurve::SegmentedCurve( PartitionEntity* vol, 
00836                                 const CubitSimpleAttrib& attrib,
00837                                 DLIList<int>& vertex_conn )
00838 {
00839   DLIList<CubitVector*> points;
00840   DLIList<int> junk;
00841   vol->sub_entity_set().add_lower_order( this, attrib, 1, points, junk, vertex_conn, junk );
00842   
00843   points.reset();
00844   point_list.size(points.size());
00845   for( int i = 0; i < points.size(); i++ )
00846   {
00847     CubitVector* pt = points.get_and_step();
00848     point_list[i] = *pt;
00849     delete pt;
00850   }
00851 }
00852 
00853 void SegmentedCurve::transform( const CubitTransformMatrix& xform )
00854 {
00855   PartitionCurve::transform(xform);
00856   for( int i = 0; i < point_list.size(); i++ )
00857     point_list[i] = xform * point_list[i];
00858 }
00859 
00860 void SegmentedCurve::print_debug_info( const char* prefix, bool pss ) const
00861 {
00862   if( prefix == 0 ) prefix = "";
00863   PartitionCurve::print_debug_info( prefix, pss );
00864   PRINT_INFO("%sSegmentedCurve %p\n", prefix, (void*)this);
00865   PRINT_INFO("%s%d segment points:\n", prefix, point_list.size());
00866   int i;
00867   for( i = 0; i  < point_list.size() - 1; i+= 2 )
00868   {
00869     PRINT_INFO("%s  (%f, %f, %f), (%f, %f, %f),\n",
00870       prefix, point_list[i  ].x(), point_list[i  ].y(), point_list[i  ].z(),
00871               point_list[i+1].x(), point_list[i+1].y(), point_list[i+1].z());
00872   }
00873   if( i == point_list.size() - 1 )
00874   {
00875     PRINT_INFO("%s  (%f, %f, %f)\n", prefix, point_list[i].x(), 
00876        point_list[i].y(), point_list[i].z());
00877   }
00878 }
00879 
00880 CubitStatus SegmentedCurve::get_spline_params
00881 (
00882   bool &rational,    // return true/false
00883   int &degree,       // the degree of this spline
00884   DLIList<CubitVector> &cntrl_pts,  // xyz position of controlpoints
00885   DLIList<double> &cntrl_pt_weights, // if rational, a weight for each cntrl point.
00886   DLIList<double> &knots,   // There should be order+cntrl_pts.size()-2 knots
00887   bool &spline_is_reversed
00888 ) const
00889 {
00890   PRINT_ERROR("Currently, Cubit is unable to determine spline parameters for SegmentedCurves.\n");
00891   return CUBIT_FAILURE;
00892 }
00893 
00894 CubitStatus SegmentedCurve::get_ellipse_params
00895 (
00896   CubitVector &center_vec,
00897   CubitVector &normal,
00898   CubitVector &major_axis,
00899   double &radius_ratio
00900 ) const
00901 {
00902   PRINT_ERROR("Currently, Cubit is unable to determine ellipse parameters for SegmentedCurves.\n");
00903   return CUBIT_FAILURE;
00904 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines