opennurbs_polyline.cpp
Go to the documentation of this file.
00001 /* $NoKeywords: $ */
00002 /*
00003 //
00004 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
00005 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
00006 // McNeel & Associates.
00007 //
00008 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
00009 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
00010 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
00011 //                              
00012 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
00013 //
00015 */
00016 
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018 
00019 ON_Polyline::ON_Polyline()
00020 {
00021 }
00022 
00023 ON_Polyline::ON_Polyline(const ON_3dPointArray& src) : ON_3dPointArray(src)
00024 {
00025 }
00026 
00027 
00028 bool ON_Polyline::IsValid( double tolerance ) const
00029 {
00030   bool rc = (m_count>=2)?true:false;
00031   int i;
00032   if ( tolerance > 0.0 )
00033   {
00034     for ( i = 1; rc && i < m_count; i++ )
00035     {
00036       if ( m_a[i].DistanceTo(m_a[i-1]) <= tolerance )
00037         rc = false;
00038     }
00039     if ( rc && m_count < 4 && m_a[0].DistanceTo(m_a[m_count-1]) <= tolerance )
00040       rc = false;
00041   }
00042   else {
00043     for ( i = 1; rc && i < m_count && rc; i++ )
00044     {
00045       if ( m_a[i] == m_a[i-1] )
00046         rc = false;
00047     }
00048     if ( rc && m_count < 4 && m_a[0] == m_a[m_count-1] )
00049       rc = false;
00050   }
00051   return rc;
00052 }
00053 
00054 int ON_Polyline::Clean( double tolerance )
00055 {
00056   // 14 January 2005 Dale Lear
00057   //     Fixed this cleaner so that it did not modify
00058   //     the start and end point.
00059   int count0 = m_count;
00060 
00061   if ( m_count > 2 )
00062   {
00063     int i,j;
00064     j = 0;
00065     for ( i = 1; i < m_count-1; i++ )
00066     {
00067        if ( m_a[j].DistanceTo(m_a[i]) <= tolerance )
00068          continue;
00069        j++;
00070        if ( i > j )
00071          m_a[j] = m_a[i];
00072     }
00073 
00074     if ( m_count > j+2 )
00075     {
00076       m_a[j+1] = m_a[m_count-1];
00077       m_count = j+2;
00078     }
00079 
00080     while ( m_count > 2 && m_a[m_count-2].DistanceTo(m_a[m_count-1]) <= tolerance )
00081     {
00082       m_a[m_count-2] = m_a[m_count-1];
00083       m_count--;
00084     }
00085   }
00086 
00087   return count0-m_count;
00088 }
00089 
00090 ON_Polyline& ON_Polyline::operator=(const ON_3dPointArray& src)
00091 {
00092   ON_3dPointArray::operator=(src);
00093   return *this;
00094 }
00095 
00096 ON_Polyline::~ON_Polyline()
00097 {
00098 }
00099 
00100 int ON_Polyline::PointCount() const
00101 {
00102   return m_count;
00103 }
00104 
00105 int ON_Polyline::SegmentCount() const
00106 {
00107   int i = m_count-1;
00108   if (i < 0 )
00109     i = 0;
00110   return i;
00111 }
00112 
00113 
00114 bool ON_Polyline::IsClosed( double tolerance ) const
00115 {
00116   bool rc = false;
00117   const int count = m_count-1;
00118   int i;
00119   if ( count >= 3 )
00120   {
00121     if ( tolerance > 0.0 )
00122     {
00123       if ( m_a[0].DistanceTo(m_a[count]) <= tolerance ) {
00124         for ( i = 1; i < count; i++ ) {
00125           if (   m_a[i].DistanceTo(m_a[0]) > tolerance 
00126               && m_a[i].DistanceTo(m_a[count]) > tolerance ) 
00127           {
00128              rc = true;
00129              break;
00130           }
00131         }
00132       }
00133     }
00134     else
00135     {
00136       if ( ON_PointsAreCoincident(3,false,&m_a[0].x,&m_a[count].x) ) 
00137       {
00138         for ( i = 1; i < count; i++ ) {
00139           if (    !ON_PointsAreCoincident(3,false,&m_a[i].x,&m_a[0].x) 
00140                && !ON_PointsAreCoincident(3,false,&m_a[i].x,&m_a[count].x) 
00141              )
00142           {
00143             rc = true;
00144             break;
00145           }
00146         }
00147       }
00148     }
00149   }
00150   return rc;
00151 }
00152 
00153 
00154 double ON_Polyline::Length() const 
00155 {
00156   const int count = m_count;
00157   double d = 0;
00158   int i;
00159   for ( i = 1; i < count; i++ ) 
00160   {
00161     d += m_a[i].DistanceTo(m_a[i-1]);
00162   }
00163   return d;
00164 }
00165 
00166 ON_3dVector ON_Polyline::SegmentDirection( int segment_index ) const
00167 {
00168   ON_3dVector v;
00169   if ( segment_index >= 0 && segment_index < m_count-1 ) {
00170     v = m_a[segment_index+1] - m_a[segment_index];
00171   }
00172   else {
00173     v.Zero();
00174   }
00175   return v;
00176 }
00177 
00178 ON_3dVector ON_Polyline::SegmentTangent( int segment_index ) const
00179 {
00180   ON_3dVector v = SegmentDirection(segment_index);
00181   v.Unitize();
00182   return v;
00183 }
00184 
00185 ON_3dPoint ON_Polyline::PointAt( double t ) const
00186 {
00187   const int count = m_count;
00188   int segment_index = 0;
00189   if ( count < 0 ) {
00190     return ON_origin;
00191   }
00192   else if (count == 1 ) {
00193     return m_a[0];
00194   }
00195   else {
00196     segment_index = (int)floor(t);
00197     if ( segment_index < 0 ) {
00198       segment_index = 0;
00199       t = 0.0;
00200     }
00201     else if ( segment_index >= count-1 ) {
00202       segment_index = count-1;
00203       t = 1.0;
00204     }
00205     else {
00206       t -= ((double)segment_index);
00207     }
00208   }
00209 
00210   return (1-t)*m_a[segment_index] + t*m_a[segment_index+1];
00211 }
00212 
00213 ON_3dVector ON_Polyline::DerivativeAt( double t ) const
00214 {
00215   const int count = m_count;
00216   int segment_index = 0;
00217   if ( count < 2 )
00218     return ON_origin;
00219   else {
00220     segment_index = (int)floor(t);
00221     if ( segment_index < 0 )
00222       segment_index = 0;
00223     else if ( segment_index >= count-1 )
00224       segment_index = count-1;
00225   }
00226   return m_a[segment_index+1]-m_a[segment_index];
00227 }
00228 
00229 ON_3dVector ON_Polyline::TangentAt( double t ) const
00230 {
00231   ON_3dVector v = DerivativeAt(t);
00232   v.Unitize();
00233   return v;
00234 }
00235 
00236 bool ON_Polyline::ClosestPointTo( const ON_3dPoint& point, double *t, int segment_index0, int segment_index1 ) const
00237 {
00238   bool rc = false;
00239   int segment_index;
00240   double segment_t, segment_d, best_t, best_d;
00241   best_t = 0.0; // to keep lint quiet
00242   best_d = 0.0; // to keep lint quiet
00243   if ( t ) {
00244     if ( segment_index0 < 0 )
00245       segment_index0 = 0;
00246     if ( segment_index1 > SegmentCount() )
00247       segment_index1 = SegmentCount();
00248     for ( segment_index = segment_index0; segment_index < segment_index1; segment_index++ ) {
00249       double seg_length = m_a[segment_index].DistanceTo(m_a[segment_index + 1]);
00250       if (seg_length < ON_EPSILON)
00251         segment_t = 0.0;
00252       else {
00253         const ON_3dVector D = SegmentTangent(segment_index);
00254         const int i = ( point.DistanceTo(m_a[segment_index]) <= point.DistanceTo(m_a[segment_index+1]) ) ? 0 : 1;
00255         segment_t = (point - m_a[segment_index+i])*D/seg_length;
00256         if ( i ) {
00257           segment_t = 1.0 + segment_t;
00258         }
00259         if ( segment_t < 0.0 )
00260           segment_t = 0.0;
00261         else if (segment_t > 1.0 )
00262           segment_t = 1.0;
00263       }
00264       segment_d = point.DistanceTo((1-segment_t)*m_a[segment_index] + segment_t*m_a[segment_index+1]);
00265       if ( !rc || segment_d < best_d ) 
00266       {
00267         best_t = segment_t + ((double)segment_index);
00268         best_d = segment_d;
00269       }
00270       rc = true;
00271     }
00272   }
00273   if (rc)
00274     *t = best_t;
00275   return rc;
00276 }
00277 
00278 bool ON_Polyline::ClosestPointTo( const ON_3dPoint& point, double *t ) const
00279 {
00280   return ClosestPointTo( point, t, 0, SegmentCount() );
00281 }
00282 
00283 ON_3dPoint ON_Polyline::ClosestPointTo( const ON_3dPoint& point ) const
00284 {
00285   double t;
00286   ON_BOOL32 rc = ClosestPointTo( point, &t );
00287   if ( !rc )
00288     t = 0.0;
00289   return PointAt(t);
00290 }
00291 
00292 bool ON_Polyline::CreateInscribedPolygon(
00293   const ON_Circle& circle,
00294   int side_count
00295   )
00296 {
00297   bool rc = ( circle.IsValid() && side_count >= 3 ) ? true : false;
00298   if ( rc )
00299   {
00300     SetCapacity(side_count+1);
00301     SetCount(side_count+1);
00302     double a = 2.0*ON_PI/side_count;
00303     int i;
00304     for ( i = 0; i < side_count; i++ )
00305     {
00306       m_a[i] = circle.PointAt(a*i);
00307     }
00308     m_a[side_count] = m_a[0];
00309   }
00310   else
00311     Destroy();
00312   return rc;
00313 }
00314 
00315 bool ON_Polyline::CreateCircumscribedPolygon(
00316             const ON_Circle& circle,
00317             int side_count
00318             )
00319 {
00320   bool rc = ( circle.IsValid() && side_count >= 3 ) ? true : false;
00321   if ( rc )
00322   {
00323     SetCapacity(side_count+1);
00324     SetCount(side_count+1);
00325     double half_a = ON_PI/side_count;
00326     int i;
00327     ON_Circle c = circle;
00328     c.radius = circle.radius/cos(half_a);
00329     for ( i = 0; i < side_count; i++ )
00330     {
00331       m_a[i] = c.PointAt(half_a*(1+2*i));
00332     }
00333     m_a[side_count] = m_a[0];
00334   }
00335   else
00336     Destroy();
00337   return rc;
00338 }
00339 
00340 bool ON_Polyline::CreateStarPolygon(
00341             const ON_Circle& circle,
00342             double other_radius,
00343             int side_count
00344             )
00345 {
00346   bool rc = ( circle.IsValid() && side_count >= 3 && other_radius >= 0.0 ) 
00347           ? true 
00348           : false;
00349   if ( rc )
00350   {
00351     SetCapacity(2*side_count+1);
00352     SetCount(2*side_count+1);
00353     double half_a = ON_PI/side_count;
00354     int i;
00355     ON_Circle other_circle = circle;
00356     other_circle.radius = other_radius;
00357     for ( i = 0; i < side_count; i++ )
00358     {
00359       m_a[i*2]   = circle.PointAt(half_a*2*i);
00360       m_a[i*2+1] = other_circle.PointAt(half_a*(1+2*i));
00361     }
00362     m_a[side_count*2] = m_a[0];
00363   }
00364   else
00365     Destroy();
00366   return rc;
00367 }
00368 


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:27:03