Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00057
00058
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;
00242 best_d = 0.0;
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