opennurbs_curveproxy.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_OBJECT_IMPLEMENT(ON_CurveProxy,ON_Curve,"4ED7D4D9-E947-11d3-BFE5-0010830122F0");
00020 
00021 ON_CurveProxy::ON_CurveProxy() : m_real_curve(0), m_bReversed(0)
00022 {}
00023 
00024 ON_CurveProxy::ON_CurveProxy( const ON_CurveProxy& src ) 
00025              : ON_Curve(src), m_real_curve(0), m_bReversed(0)
00026 {
00027   *this = src;
00028 }
00029 
00030 ON_CurveProxy::ON_CurveProxy( const ON_Curve* c ) 
00031               : m_real_curve(c), m_bReversed(0)
00032 {
00033   if ( m_real_curve )
00034     m_real_curve_domain =m_this_domain = m_real_curve->Domain();
00035 }
00036 
00037 ON_CurveProxy::ON_CurveProxy( const ON_Curve* c, ON_Interval domain ) 
00038              : m_real_curve(c), 
00039                m_bReversed(0),
00040                m_real_curve_domain(domain),
00041                m_this_domain(domain)
00042 {
00043 }
00044 
00045 unsigned int ON_CurveProxy::SizeOf() const
00046 {
00047   unsigned int sz = ON_Curve::SizeOf();
00048   sz += (sizeof(*this) - sizeof(ON_Curve));
00049   // Do not add in size of m_real_curve - its memory is not
00050   // managed by this class.
00051   return sz;
00052 }
00053 
00054 ON__UINT32 ON_CurveProxy::DataCRC(ON__UINT32 current_remainder) const
00055 {
00056   if ( m_real_curve )
00057     current_remainder = m_real_curve->DataCRC(current_remainder);
00058   current_remainder = ON_CRC32(current_remainder,sizeof(m_bReversed),&m_bReversed);
00059   current_remainder = ON_CRC32(current_remainder,sizeof(m_real_curve_domain),&m_real_curve_domain);
00060   current_remainder = ON_CRC32(current_remainder,sizeof(m_this_domain),&m_this_domain);
00061   return current_remainder;
00062 }
00063 
00064 ON_CurveProxy& ON_CurveProxy::operator=( const ON_CurveProxy& src )
00065 {
00066   if ( this != &src ) 
00067   {
00068     ON_Curve::operator=(src);
00069     m_real_curve = src.m_real_curve;
00070     m_bReversed = src.m_bReversed;
00071     m_real_curve_domain = src.m_real_curve_domain;
00072     m_this_domain = src.m_this_domain;
00073   }
00074   return *this;
00075 }
00076 
00077 ON_CurveProxy::~ON_CurveProxy()
00078 {
00079   m_real_curve = 0;
00080 }
00081 
00082 double ON_CurveProxy::RealCurveParameter( double t ) const
00083 {
00084   // change a "this" curve parameter into an m_real_curve parameter
00085   double s;
00086   if ( m_bReversed || m_real_curve_domain != m_this_domain )
00087   {
00088     s = m_this_domain.NormalizedParameterAt(t);
00089     if (m_bReversed)
00090       s = 1.0 - s;
00091     t = m_real_curve_domain.ParameterAt(s);
00092   }
00093   return t;
00094 }
00095 
00096 double ON_CurveProxy::ThisCurveParameter( double real_curve_parameter ) const
00097 {
00098   // change an m_real_curve curve parameter into a "this" parameter
00099   double s;
00100   double t = real_curve_parameter;
00101   if ( m_bReversed || m_real_curve_domain != m_this_domain )
00102   {
00103     s = m_real_curve_domain.NormalizedParameterAt(real_curve_parameter);
00104     if (m_bReversed)
00105       s = 1.0 - s;
00106     t = m_this_domain.ParameterAt(s);
00107   }
00108   return t;
00109 }
00110 
00111 ON_Interval ON_CurveProxy::RealCurveInterval( const ON_Interval* sub_domain ) const
00112 {
00113   if ( !sub_domain )
00114     return m_real_curve_domain;
00115   ON_Interval d = m_this_domain;
00116   d.Intersection(*sub_domain);
00117   double t0 = RealCurveParameter( d[m_bReversed?1:0] );
00118   double t1 = RealCurveParameter( d[m_bReversed?0:1] );
00119   return ON_Interval(t0,t1);
00120 }
00121 
00122 
00123 bool ON_CurveProxy::ProxyCurveIsReversed() const
00124 {
00125   return m_bReversed;
00126 }
00127 
00128 void ON_CurveProxy::SetProxyCurve( const ON_Curve* real_curve )
00129 {
00130   // setting m_real_curve=0 prevents crashes if user has deleted
00131   // the "real" curve before calling SetProxyCurve().
00132   m_real_curve = 0;
00133 
00134   if ( real_curve )
00135     SetProxyCurve( real_curve, real_curve->Domain() );
00136   else
00137   {
00138     DestroyCurveTree();
00139     m_real_curve_domain.Destroy();
00140     m_this_domain.Destroy();
00141     m_bReversed = false;
00142   }
00143 }
00144 
00145 void ON_CurveProxy::SetProxyCurve( const ON_Curve* real_curve, 
00146                                    ON_Interval real_curve_subdomain)
00147 {
00148   if ( real_curve != this )
00149   {
00150     // setting m_real_curve=0 prevents crashes if user has deleted
00151     // the "real" curve before calling SetProxyCurve().
00152     m_real_curve = 0;
00153     DestroyCurveTree();
00154     m_real_curve_domain.Destroy();
00155     m_this_domain.Destroy();
00156     m_bReversed = false;
00157   }
00158   else
00159   {
00160     // If you are debugging and end up here, there is a 99% chance
00161     // that you passed the wrong pointer to SetProxyCurve().
00162     // However, I will assume you really meant to use a fancy self
00163     // reference to adjust domains.
00164     if ( IsValid() && m_this_domain.Includes(real_curve_subdomain) )
00165     {
00166       real_curve = m_real_curve;
00167       // because input real_curve_subdomain was with respect to "this".
00168       double r0 = RealCurveParameter(real_curve_subdomain[0]);
00169       double r1 = RealCurveParameter(real_curve_subdomain[1]);
00170       real_curve_subdomain.Set(r0,r1);
00171     }
00172     else
00173     {
00174       real_curve = 0;
00175     }
00176 
00177     // setting m_real_curve=0 prevents crashes if user has deleted
00178     // the "real" curve before calling SetProxyCurve().
00179     m_real_curve = 0;
00180     DestroyCurveTree();
00181   }
00182 
00183   m_real_curve = real_curve;
00184   if ( m_real_curve )
00185   {
00186     SetProxyCurveDomain( real_curve_subdomain );
00187   }
00188   else
00189   {
00190     m_real_curve_domain = real_curve_subdomain;
00191   }
00192   m_this_domain = m_real_curve_domain;
00193 }
00194 
00195 const ON_Curve* ON_CurveProxy::ProxyCurve() const
00196 {
00197   return m_real_curve;
00198 }
00199 
00200 bool ON_CurveProxy::SetProxyCurveDomain( ON_Interval proxy_curve_subdomain )
00201 {
00202   DestroyCurveTree();
00203   bool rc = proxy_curve_subdomain.IsIncreasing();
00204   if ( rc )
00205   {
00206     if ( m_real_curve )
00207     {
00208       ON_Interval cdom = m_real_curve->Domain();
00209       cdom.Intersection( proxy_curve_subdomain );
00210       rc = cdom.IsIncreasing();
00211       if (rc )
00212         m_real_curve_domain = cdom;
00213     }
00214     else
00215     {
00216       m_real_curve_domain = proxy_curve_subdomain;
00217     }
00218   }
00219   return rc;
00220 }
00221 
00222 ON_Interval ON_CurveProxy::ProxyCurveDomain() const
00223 {
00224   return m_real_curve_domain;
00225 }
00226 
00227 ON_Curve* ON_CurveProxy::DuplicateCurve() const
00228 {
00229   // duplicate underlying curve
00230   ON_Curve* dup_crv = 0;
00231   if ( m_real_curve && m_real_curve != this )
00232   {
00233     dup_crv = m_real_curve->DuplicateCurve();
00234     if ( dup_crv )
00235     {
00236       dup_crv->Trim(m_real_curve_domain);
00237       if( m_bReversed )
00238         dup_crv->Reverse();
00239       dup_crv->SetDomain( m_this_domain );
00240     }
00241   }
00242   return dup_crv;
00243 }
00244 
00245 
00246 ON_BOOL32
00247 ON_CurveProxy::IsValid( ON_TextLog* text_log ) const
00248 {
00249   ON_BOOL32 rc = ( m_real_curve ) ? m_real_curve->IsValid(text_log) : false;
00250 
00251   if ( rc && !m_real_curve_domain.IsIncreasing() )
00252   {
00253     rc = false;
00254     if ( text_log) 
00255       text_log->Print("ON_CurveProxy.m_real_curve_domain is not increasing.\n");
00256   }
00257 
00258   if ( rc && !m_real_curve->Domain().Includes( m_real_curve_domain ) )
00259   {
00260     rc = false;
00261     if ( text_log) 
00262       text_log->Print("ON_CurveProxy.m_real_curve_domain is not included m_real_curve->Domain().\n");
00263   }
00264 
00265   if ( rc && !m_this_domain.IsIncreasing() )
00266   {
00267     rc = false;
00268     if ( text_log) 
00269       text_log->Print("ON_CurveProxy.m_this_domain is not increasing.\n");
00270   }
00271 
00272   return rc;
00273 }
00274 
00275 void
00276 ON_CurveProxy::Dump( ON_TextLog& dump ) const
00277 {
00278   dump.Print("ON_CurveProxy uses %x on [%g,%g]\n",m_real_curve,m_real_curve_domain[0],m_real_curve_domain[1]);
00279 }
00280 
00281 ON_BOOL32 
00282 ON_CurveProxy::Write(
00283        ON_BinaryArchive&  // open binary file
00284      ) const
00285 {
00286   return false;
00287 }
00288 
00289 ON_BOOL32 
00290 ON_CurveProxy::Read(
00291        ON_BinaryArchive&  // open binary file
00292      )
00293 {
00294   return false;
00295 }
00296 
00297 int 
00298 ON_CurveProxy::Dimension() const
00299 {
00300   return ( m_real_curve ) ? m_real_curve->Dimension() : 0;
00301 }
00302 
00303 ON_BOOL32 
00304 ON_CurveProxy::GetBBox( // returns true if successful
00305          double* boxmin,    // minimum
00306          double* boxmax,    // maximum
00307          ON_BOOL32 bGrowBox
00308          ) const
00309 {
00310   return ( m_real_curve ) ? m_real_curve->GetBBox(boxmin,boxmax,bGrowBox) : false;
00311 }
00312 
00313 ON_BOOL32
00314 ON_CurveProxy::Transform( const ON_Xform& )
00315 {
00316   return false; // cannot modify proxy objects
00317 }
00318 
00319 ON_Interval ON_CurveProxy::Domain() const
00320 {
00321   return m_this_domain;
00322 }
00323 
00324 ON_BOOL32 ON_CurveProxy::SetDomain( double t0, double t1 )
00325 {
00326   ON_BOOL32 rc = false;
00327   if (t0 < t1)
00328   {
00329                 DestroyCurveTree();
00330     m_this_domain.Set(t0, t1);
00331     rc = true;
00332   }
00333   return rc;
00334 }
00335 
00336 
00337 bool ON_CurveProxy::SetDomain( ON_Interval domain )
00338 {
00339   return SetDomain( domain[0], domain[1] ) ? true : false;
00340 }
00341 
00342 //Do not change SpanCount() without making sure it gives the correct result for use in GetSpanVector()
00343 int ON_CurveProxy::SpanCount() const
00344 {
00345   if (!m_real_curve) return 0;
00346   int rsc = m_real_curve->SpanCount();
00347   ON_Interval domain = m_real_curve->Domain();
00348   if (m_real_curve_domain == domain) 
00349     return rsc;
00350   double* rsv = (double*)onmalloc((rsc+1)*sizeof(double));
00351   if (!rsv) return 0;
00352   if (!m_real_curve->GetSpanVector(rsv)){
00353     onfree((void*)rsv);
00354     return 0;
00355   }
00356 
00357   int i=0;
00358   int sc = 0;
00359   
00360   while (i <= rsc && rsv[i] <= m_real_curve_domain[0]) i++;
00361   while (i <= rsc && rsv[i] < m_real_curve_domain[1]){
00362     sc++;
00363     i++;
00364   }
00365   sc++;
00366   onfree((void*)rsv);
00367 
00368   return sc;
00369 }
00370 
00371 
00372 //Do not change GetSpanVector() without making sure it is consistent with SpanCount()
00373 ON_BOOL32 ON_CurveProxy::GetSpanVector( double* d ) const
00374 {
00375 
00376 #if 0
00377   ON_BOOL32 rc = m_real_curve ? m_real_curve->GetSpanVector(d) : false;
00378   if (rc && (m_bReversed || m_this_domain != m_real_curve_domain) ) 
00379   {
00380     double x;
00381     int i, j, count = SpanCount();
00382     for ( i = 0; i <= count; i++ )
00383     {
00384       x = m_real_curve_domain.NormalizedParameterAt(d[i]);
00385       d[i] = x;
00386     }
00387     if ( m_bReversed )
00388     {
00389       for ( i = 0, j = count; i <= j; i++, j-- ) 
00390       {
00391         x = d[i];
00392         d[i] = 1.0-d[j];
00393         d[j] = 1.0-x;
00394       }
00395     }
00396     for ( i = 0; i <= count; i++ )
00397     {
00398       d[i] = m_this_domain.ParameterAt(d[i]);
00399     }
00400   }
00401   return rc;
00402 #endif
00403 
00404   if (!m_real_curve) return false;
00405   int rsc = m_real_curve->SpanCount();
00406   if (rsc < 1) return false;
00407   double* rsv = (double*)onmalloc((rsc+1)*sizeof(double));
00408   if (!rsv || !m_real_curve->GetSpanVector(rsv)) return false;
00409   ON_Interval domain = m_real_curve->Domain();
00410 
00411   if (m_real_curve_domain == m_this_domain && m_real_curve_domain == domain){
00412     int i;
00413     for (i=0; i <= rsc; i++) d[i] = rsv[i];
00414     onfree((void*)rsv);
00415     return true;
00416   }
00417 
00418   if (m_real_curve_domain[1] <= domain[0] || m_real_curve_domain[0] >= domain[1]){
00419     onfree((void*)rsv);
00420     return false;
00421   }
00422 
00423   int i=0;
00424   int sc = 0;
00425   d[0] = m_real_curve_domain[0];
00426   
00427   while (i<= rsc && rsv[i] <= d[0]) i++;
00428   while (i <= rsc && rsv[i] < m_real_curve_domain[1]){
00429     sc++;
00430     d[sc] = rsv[i];
00431     i++;
00432   }
00433   sc++;
00434   d[sc] = m_real_curve_domain[1];
00435 
00436   onfree((void*)rsv);
00437 
00438   if (m_bReversed || m_real_curve_domain != m_this_domain){
00439     double x;
00440     int j;
00441     for ( i = 0; i <= sc; i++ )
00442     {
00443       x = m_real_curve_domain.NormalizedParameterAt(d[i]);
00444       d[i] = x;
00445     }
00446     if ( m_bReversed )
00447     {
00448       for ( i = 0, j = sc; i <= j; i++, j-- ) 
00449       {
00450         x = d[i];
00451         d[i] = 1.0-d[j];
00452         d[j] = 1.0-x;
00453       }
00454     }
00455     for ( i = 0; i <= sc; i++ )
00456     {
00457       d[i] = m_this_domain.ParameterAt(d[i]);
00458     }
00459   }
00460 
00461   return true;
00462 }
00463 
00464 int ON_CurveProxy::Degree() const
00465 {
00466   return m_real_curve ? m_real_curve->Degree() : 0;
00467 }
00468 
00469 ON_BOOL32 
00470 ON_CurveProxy::GetParameterTolerance(
00471          double t,  // t = parameter in domain
00472          double* tminus, // tminus
00473          double* tplus   // tplus
00474          ) const
00475 {
00476   ON_BOOL32 rc = ( m_real_curve ) 
00477           ? m_real_curve->GetParameterTolerance( RealCurveParameter(t),tminus,tplus) 
00478           : false;
00479   if (rc)
00480   {
00481     if ( tminus )
00482       *tminus = ThisCurveParameter(*tminus);
00483     if ( tplus )
00484       *tplus = ThisCurveParameter(*tplus);
00485   }
00486   return rc;
00487 }
00488 
00489 
00490 ON_BOOL32
00491 ON_CurveProxy::IsLinear( // true if curve locus is a line segment
00492       double tolerance // tolerance to use when checking linearity
00493       ) const
00494 {
00495   // 12 December 2003 Dale Lear - fixed bug so this works
00496   //     when a proxy is restricted to using a linear portion
00497   //     of a non-linear real curve.
00498   bool rc = false;
00499   if ( 0 != m_real_curve )
00500   {
00501     ON_Interval cdom = m_real_curve->Domain();
00502     if ( cdom == m_real_curve_domain )
00503     {
00504       rc = m_real_curve->IsLinear(tolerance) ? true : false;
00505     }
00506     else
00507     {
00508       // The ON_CurveProxy::DuplicateCurve() scope is critical
00509       // because there are situation where people derive a 
00510       // class from ON_CurveProxy, and override the virtual
00511       // DuplicateCurve().  In this situation I rely on getting
00512       // the result returned by ON_CurveProxy::DuplicateCurve().
00513       ON_Curve* temp_curve = ON_CurveProxy::DuplicateCurve();
00514       if ( 0 != temp_curve )
00515       {
00516         rc = temp_curve->IsLinear(tolerance) ? true : false;
00517         delete temp_curve;
00518       }
00519     }
00520   }
00521   return rc;
00522 }
00523 
00524 int ON_CurveProxy::IsPolyline(
00525       ON_SimpleArray<ON_3dPoint>* pline_points,
00526       ON_SimpleArray<double>* pline_t
00527       ) const
00528 {
00529   ON_SimpleArray<double> tmp_t;
00530 
00531   if ( pline_points )
00532     pline_points->SetCount(0);
00533   if ( pline_t )
00534     pline_t->SetCount(0);
00535   if ( !m_real_curve_domain.IsIncreasing() )
00536     return 0;
00537   if ( !m_real_curve )
00538     return 0;
00539   const ON_Interval cdom = m_real_curve->Domain();
00540   if ( !cdom.Includes(m_real_curve_domain) )
00541     return 0;
00542 
00543   // See if the "real" curve is a polyline
00544   int rc = 0;
00545   if ( m_real_curve_domain == cdom )
00546   {
00547     // proxy uses entire curve
00548     rc = m_real_curve->IsPolyline(pline_points,pline_t);
00549     if ( rc < 2 )
00550       rc = 0;
00551 
00552     if ( pline_points && pline_points->Count() != rc)
00553     {
00554       // The pline_points info is bogus, clear everything and
00555       // return 0.
00556       pline_points->SetCount(0);
00557       if ( pline_t )
00558         pline_t->SetCount(0);
00559       rc = 0;
00560     }
00561 
00562     if ( pline_t && pline_t->Count() != rc)
00563     {
00564       // The pline_t info is bogus, clear everything and
00565       // return 0.
00566       pline_t->SetCount(0);
00567       if ( pline_points )
00568         pline_points->SetCount(0);
00569       rc = 0;
00570     }
00571 
00572     if ( rc )
00573     {
00574       if ( m_bReversed )
00575       {
00576         if ( pline_points )
00577           pline_points->Reverse();
00578         if ( pline_t )
00579           pline_t->Reverse();
00580       }
00581 
00582       if ( pline_points && IsClosed() && pline_points->Count() > 3 )
00583       {
00584         // 27 February 2003 Dale Lear
00585         //     If proxy curve says it's closed, then
00586         //     make sure end point of returned polyline
00587         //     is exactly equal to start point.
00588         *pline_points->Last() = *pline_points->First();
00589       }
00590       
00591       if ( pline_t && (m_bReversed || m_real_curve_domain != m_this_domain) )
00592       {
00593         int i;
00594         for ( i = 0; i < rc; i++ )
00595         {
00596           (*pline_t)[i] = ThisCurveParameter( (*pline_t)[i] );
00597         }
00598       }
00599     }
00600   }
00601   else
00602   {
00603     // 12 December 2003 Dale Lear
00604     //   We have to extract a sub curve for the test, because
00605     //   the region in question may be a polyline and the unused
00606     //   portion may not be a polyline.  This tends to happen
00607     //   when the "real" curve is a polycurve that contains 
00608     //   a polyline and the polycurve has been parametrically
00609     //   trimmed during a brep operation (like a boolean).
00610     //
00611     // The ON_CurveProxy::DuplicateCurve() scope is critical
00612     // because there are situation where people derive a 
00613     // class from ON_CurveProxy, and override the virtual
00614     // DuplicateCurve().  In this situation I rely on getting
00615     // the result returned by ON_CurveProxy::DuplicateCurve().
00616     ON_Curve* temp_curve = ON_CurveProxy::DuplicateCurve();
00617     if ( temp_curve )
00618     {
00619       rc = temp_curve->IsPolyline(pline_points,pline_t);
00620       delete temp_curve;
00621     }
00622   }
00623 
00624   return rc;
00625 }
00626 
00627 
00628 
00629 ON_BOOL32
00630 ON_CurveProxy::IsArc( // true if curve locus in an arc or circle
00631       const ON_Plane* plane, // if not NULL, test is performed in this plane
00632       ON_Arc* arc,         // if not NULL and true is returned, then arc
00633                               // arc parameters are filled in
00634       double tolerance // tolerance to use when checking linearity
00635       ) const
00636 {
00637   ON_BOOL32 rc = false;
00638   const ON_Interval cdom = m_real_curve->Domain();
00639   if ( cdom == m_real_curve_domain )
00640   {
00641     rc = m_real_curve->IsArc(plane,arc,tolerance) ? true : false;
00642     if ( rc && arc  && m_bReversed )
00643       arc->Reverse();
00644   }
00645   else
00646   {
00647     // The ON_CurveProxy::DuplicateCurve() scope is critical
00648     // because there are situation where people derive a 
00649     // class from ON_CurveProxy, and override the virtual
00650     // DuplicateCurve().  In this situation I rely on getting
00651     // the result returned by ON_CurveProxy::DuplicateCurve().
00652     ON_Curve* temp_curve = ON_CurveProxy::DuplicateCurve();
00653     if ( 0 != temp_curve )
00654     {
00655       rc = temp_curve->IsArc(plane,arc,tolerance) ? true : false;
00656       delete temp_curve;
00657     }
00658   }
00659   return rc;
00660 }
00661 
00662 ON_BOOL32
00663 ON_CurveProxy::IsPlanar(
00664       ON_Plane* plane, // if not NULL and true is returned, then plane parameters
00665                          // are filled in
00666       double tolerance // tolerance to use when checking linearity
00667       ) const
00668 {
00669   return ( m_real_curve ) ? m_real_curve->IsPlanar(plane,tolerance) : false;
00670 }
00671 
00672 ON_BOOL32
00673 ON_CurveProxy::IsInPlane(
00674       const ON_Plane& plane, // plane to test
00675       double tolerance // tolerance to use when checking linearity
00676       ) const
00677 {
00678   return ( m_real_curve ) ? m_real_curve->IsInPlane(plane,tolerance) : false;
00679 }
00680 
00681 ON_BOOL32 
00682 ON_CurveProxy::IsClosed() const
00683 {
00684   ON_BOOL32 rc = false;
00685   if ( m_real_curve && m_real_curve->Domain() == m_real_curve_domain )
00686   {
00687     rc = m_real_curve->IsClosed();
00688   }
00689   return rc;
00690 }
00691 
00692 ON_BOOL32 
00693 ON_CurveProxy::IsPeriodic() const
00694 {
00695   ON_BOOL32 rc = false;
00696   if ( m_real_curve && m_real_curve->Domain() == m_real_curve_domain )
00697   {
00698     rc = m_real_curve->IsPeriodic();
00699   }
00700   return rc;
00701 }
00702 
00703 bool ON_CurveProxy::GetNextDiscontinuity( 
00704                 ON::continuity c,
00705                 double t0,
00706                 double t1,
00707                 double* t,
00708                 int* hint,
00709                 int* dtype,
00710                 double cos_angle_tolerance,
00711                 double curvature_tolerance
00712                 ) const
00713 {
00714   bool rc = false;
00715   if ( 0 != dtype )
00716     *dtype = 0;
00717 
00718   if ( 0 != m_real_curve )
00719   {
00720     double s;
00721 
00722     // convert to "real" curve parameters
00723     double s0 = RealCurveParameter( t0 );
00724     double s1 = RealCurveParameter( t1 );
00725 
00726     // 21 October 2005 Dale Lear:
00727     //
00728     // NOTE: If m_bReversed is true, then RealCurveParameter
00729     //       will reverse the direction of the search.
00730     //       The commented out code below just messed things up.
00731     //
00732     //if ( m_bReversed )
00733     //{
00734     //  // NOTE: GetNextDiscontinuity search begins at 
00735     //  //       "t0" and goes towards "t1" so it is ok if s0 > s1.
00736     //  s = s0; s0 = s1; s1 = s;
00737     //}
00738 
00739     ON::continuity parametric_c = ON::ParametricContinuity(c);
00740 
00741     int realcrv_dtype = 0;
00742     bool realcrv_rc = m_real_curve->GetNextDiscontinuity(parametric_c,s0,s1,&s,hint,&realcrv_dtype,cos_angle_tolerance,curvature_tolerance);
00743 
00744     if ( realcrv_rc ) 
00745     {
00746       double thiscrv_t = ThisCurveParameter(s);
00747       if ( !(t0 < thiscrv_t && thiscrv_t < t1) && !(t1 < thiscrv_t && thiscrv_t < t0) )
00748       {
00749         realcrv_rc = false;
00750         realcrv_dtype = 0;
00751         // Sometimes proxy domain adjustments kill all the precision.
00752         // To avoid infinite loops, it is critical that *t != t0
00753         double s2 = ON_SQRT_EPSILON*s1 + (1.0 - ON_SQRT_EPSILON)*s0;
00754         if ( (s0 < s2 && s2 < s1) || (s1 < s2 && s2 < s0) )
00755         {
00756           realcrv_rc = m_real_curve->GetNextDiscontinuity(parametric_c,s2,s1,&s,hint,&realcrv_dtype,cos_angle_tolerance,curvature_tolerance);
00757           if ( realcrv_rc )
00758             thiscrv_t = ThisCurveParameter(s);
00759         }
00760       }
00761       if ( realcrv_rc )
00762       {
00763         if ( (t0 < thiscrv_t && thiscrv_t < t1) || (t1 < thiscrv_t && thiscrv_t < t0) )
00764         {
00765           *t = thiscrv_t;
00766           if ( dtype )
00767             *dtype = realcrv_dtype;
00768           rc = true;
00769         }
00770       }
00771     }
00772 
00773     if ( !rc && parametric_c != c )
00774     {
00775       // 20 March 2003 Dale Lear:
00776       //   Let base class test decide locus continuity questions at ends 
00777       rc = ON_Curve::GetNextDiscontinuity( c, t0, t1, t, hint, dtype, cos_angle_tolerance, curvature_tolerance );
00778     }
00779   }
00780 
00781   return rc;
00782 }
00783 
00784 
00785 bool ON_CurveProxy::IsContinuous(
00786     ON::continuity desired_continuity,
00787     double t, 
00788     int* hint, // default = NULL,
00789     double point_tolerance, // default=ON_ZERO_TOLERANCE
00790     double d1_tolerance, // default==ON_ZERO_TOLERANCE
00791     double d2_tolerance, // default==ON_ZERO_TOLERANCE
00792     double cos_angle_tolerance, // default==ON_DEFAULT_ANGLE_TOLERANCE_COSINE
00793     double curvature_tolerance  // default==ON_SQRT_EPSILON
00794     ) const
00795 {
00796   bool rc = true;
00797   if ( m_real_curve )
00798   {
00799     if ( m_real_curve_domain != m_real_curve->Domain() )
00800     {
00801       // 20 March 2003 Dale Lear
00802       //      Added this code to correctly handle the new locus
00803       //      flavors of ON::continuity.
00804       switch(desired_continuity)
00805       {
00806       case ON::unknown_continuity:
00807       case ON::C0_continuous:
00808       case ON::C1_continuous:
00809       case ON::C2_continuous:
00810       case ON::G1_continuous:
00811       case ON::G2_continuous:
00812       case ON::Cinfinity_continuous:
00813       case ON::Gsmooth_continuous:
00814         break;
00815 
00816       case ON::C0_locus_continuous:
00817       case ON::C1_locus_continuous:
00818       case ON::C2_locus_continuous:
00819       case ON::G1_locus_continuous:
00820       case ON::G2_locus_continuous:
00821         if ( t >= Domain()[1] )
00822         {
00823           // Since the proxy curve is using a subset of the real curve,
00824           // the proxy can't be closed.  So if the query parameter
00825           // is >= domain max, the curve cannot be locus continuous.
00826           rc = false;
00827         }
00828         else
00829         {
00830           // otherwise we want the answer for a non-locus test
00831           desired_continuity = ON::ParametricContinuity(desired_continuity);
00832         }
00833         break;
00834       }
00835     }
00836     if (rc)
00837       rc = m_real_curve->IsContinuous( desired_continuity, 
00838                            RealCurveParameter(t), hint, 
00839                            point_tolerance, d1_tolerance, d2_tolerance, 
00840                            cos_angle_tolerance, curvature_tolerance );
00841   }
00842   return rc;
00843 }
00844 
00845 
00846 ON_BOOL32
00847 ON_CurveProxy::Reverse()
00848 {
00849   if ( m_this_domain.IsIncreasing() )
00850   {
00851     m_bReversed = (m_bReversed) ? false : true;
00852           DestroyCurveTree();
00853     m_this_domain.Reverse();
00854   }
00855   return true;
00856 }
00857 
00858 ON_BOOL32 
00859 ON_CurveProxy::Evaluate( // returns false if unable to evaluate
00860        double t,       // evaluation parameter
00861        int der_count,  // number of derivatives (>=0)
00862        int v_stride,   // v[] array stride (>=Dimension())
00863        double* v,      // v[] array of length stride*(ndir+1)
00864        int side,       // optional - determines which side to evaluate from
00865                        //         0 = default
00866                        //      <  0 to evaluate from below, 
00867                        //      >  0 to evaluate from above
00868        int* hint       // optional - evaluation hint (int) used to speed
00869                        //            repeated evaluations
00870        ) const
00871 {
00872   // When the proxy domain is a proper subdomain of the 
00873   // real curve and we are evaluating at the end, we
00874   // need to be certain we are getting the values
00875   // from the active part of the curve.
00876   double normt = m_this_domain.NormalizedParameterAt(t);
00877   if( fabs( normt )<ON_ZERO_TOLERANCE)
00878     side = (abs(side) <= 1) ? 1 : 2;
00879   else if( fabs(1.0 - normt)<ON_ZERO_TOLERANCE)
00880     side = (abs(side) <= 1) ? -1 : -2;
00881   
00882   if ( 0 != side )
00883   {
00884     if ( m_bReversed )
00885     {
00886       side = -side;
00887     }
00888     if (m_bReversed || m_real_curve_domain != m_this_domain )
00889     {
00890       // 9 November 2010 Dale Lear - ON_TuneupEvaluationParameter fix
00891       //  If we have to adjust the evaluation parameter for the 
00892       //  real curve and the evaluation side was specified, then
00893       //  set side to +2 or -2 to trigger the use of
00894       //  ON_TuneupEvaluationParameter() when it matters.
00895       if ( -1 == side )
00896         side = -2;
00897       else if ( 1 == side )
00898         side = 2;
00899     }
00900   }
00901 
00902   double r = RealCurveParameter(t);
00903   ON_BOOL32 rc = ( m_real_curve ) 
00904           ? m_real_curve->Evaluate( r,der_count,v_stride,v,side,hint) 
00905           : false;
00906   if ( rc && m_bReversed ) 
00907   {
00908     // negate odd derivatives
00909     const int dim = m_real_curve->Dimension();
00910     int di, i;
00911     for ( di = 1; di <= der_count; di+=2 ) 
00912     {
00913       v += v_stride;
00914       for ( i = 0; i < dim; i++ ) 
00915       {
00916         v[i] = -v[i];
00917       }
00918       v += v_stride;
00919     }
00920   }
00921   return rc;
00922 }
00923 
00924 ON_BOOL32 ON_CurveProxy::Trim(
00925   const ON_Interval& domain
00926   )
00927 {
00928   bool rc = false;
00929   if ( m_this_domain.IsIncreasing() && m_real_curve_domain.IsIncreasing() )
00930   {
00931     ON_Interval trim_dom = m_this_domain;
00932     trim_dom.Intersection(domain);
00933     if ( trim_dom.IsIncreasing() )
00934     {
00935       ON_Interval real_dom = RealCurveInterval( &trim_dom );
00936       if ( real_dom.IsIncreasing() )
00937       {
00938         DestroyCurveTree();
00939         m_real_curve_domain = real_dom;
00940         m_this_domain = trim_dom;
00941         rc = true;
00942       }
00943     }
00944   }
00945   return rc;
00946 }
00947 
00948 
00949 // override of virtual ON_Curve::Split
00950 ON_BOOL32 ON_CurveProxy::Split(
00951     double t,
00952     ON_Curve*& left_side,
00953     ON_Curve*& right_side
00954   ) const
00955 {
00956   ON_BOOL32 rc = false;
00957   if ( m_this_domain.IsIncreasing() && m_real_curve_domain.IsIncreasing() && m_this_domain.Includes(t,true) )
00958   {
00959     double crv_t = RealCurveParameter(t);
00960     if ( m_real_curve_domain.Includes(crv_t,true) )
00961     {
00962       ON_CurveProxy* left_proxy = 0;
00963       ON_CurveProxy* right_proxy = 0;
00964       if ( left_side )
00965       {
00966         left_proxy = ON_CurveProxy::Cast(left_side);
00967         if ( !left_proxy )
00968           return false;
00969       }
00970       if ( right_side )
00971       {
00972         right_proxy = ON_CurveProxy::Cast(right_side);
00973         if ( !right_proxy )
00974           return false;
00975         if ( right_side == left_side )
00976           return false;
00977       }
00978 
00979       bool bRev = m_bReversed;
00980 
00981       ON_Interval left_real_dom, right_real_dom;
00982       if ( bRev )
00983       {
00984         left_real_dom.Set(crv_t,m_real_curve_domain[1]);
00985         right_real_dom.Set(m_real_curve_domain[0],crv_t);
00986       }
00987       else
00988       {
00989         left_real_dom.Set(m_real_curve_domain[0],crv_t);
00990         right_real_dom.Set(crv_t,m_real_curve_domain[1]);
00991       }
00992 
00993       ON_Interval left_this_dom(m_this_domain[0],t);
00994       ON_Interval right_this_dom(t,m_this_domain[1]);
00995 
00996       if (    left_real_dom.IsIncreasing() 
00997            && right_real_dom.IsIncreasing()
00998            && left_this_dom.IsIncreasing()
00999            && right_this_dom.IsIncreasing()
01000            )
01001       {
01002         // note well that left_proxy or right_proxy might also be this
01003         const ON_Curve* real_crv = m_real_curve;
01004         if ( real_crv )
01005         {
01006           ON_Interval d = real_crv->Domain();
01007           if ( !d.Includes(left_real_dom) )
01008             return false;
01009           if ( !d.Includes(right_real_dom) )
01010             return false;
01011         }
01012 
01013         if ( !left_proxy )
01014           left_proxy = new ON_CurveProxy();
01015         if ( !right_proxy )
01016           right_proxy = new ON_CurveProxy();
01017 
01018         left_proxy->SetProxyCurve( real_crv, left_real_dom );
01019         right_proxy->SetProxyCurve( real_crv, right_real_dom );
01020 
01021         if ( bRev )
01022         {
01023           left_proxy->Reverse();
01024           right_proxy->Reverse();
01025         }
01026 
01027         left_proxy->SetDomain(left_this_dom[0],left_this_dom[1]);
01028         right_proxy->SetDomain(right_this_dom[0],right_this_dom[1]);
01029 
01030         if (!left_side) left_side = left_proxy;
01031         if (!right_side) right_side = right_proxy;
01032 
01033         rc = true;
01034       }
01035     }
01036   }
01037   return rc;
01038 }
01039 
01040 int 
01041 ON_CurveProxy::GetNurbForm( // returns 0: unable to create NURBS representation
01042                  //            with desired accuracy.
01043                  //         1: success - returned NURBS parameterization
01044                  //            matches the curve's to wthe desired accuracy
01045                  //         2: success - returned NURBS point locus matches
01046                  //            the curve's to the desired accuracy but, on
01047                  //            the interior of the curve's domain, the 
01048                  //            curve's parameterization and the NURBS
01049                  //            parameterization may not match to the 
01050                  //            desired accuracy.
01051       ON_NurbsCurve& nurbs,
01052       double tolerance,  // (>=0)
01053       const ON_Interval* sub_domain  // OPTIONAL subdomain of ON::ProxyCurve::Domain()
01054       ) const
01055 {
01056   ON_BOOL32 rc = false;
01057   if ( m_real_curve ) 
01058   {
01059     ON_Interval scratch_domain = RealCurveInterval( sub_domain );
01060     rc = m_real_curve->GetNurbForm(nurbs,tolerance,&scratch_domain);
01061     if ( rc )
01062     {
01063       if ( m_bReversed )
01064         nurbs.Reverse();
01065       ON_Interval d = m_this_domain;
01066       if ( sub_domain )
01067         d.Intersection( *sub_domain );
01068       nurbs.SetDomain( d[0], d[1] );
01069 
01070       if ( nurbs.m_dim <= 3 && nurbs.m_dim >= 1 )
01071       {
01072         double t0 = Domain()[0];
01073         double t1 = Domain()[1];
01074         if ( 0 != sub_domain )
01075         {
01076           if ( t0 < sub_domain->Min() )
01077             t0 = sub_domain->Min();
01078           if ( sub_domain->Max() < t1 )
01079             t1 = sub_domain->Max();
01080         }
01081         // set ends of NURBS curve to be exactly on ends of proxy curve
01082         ON_3dPoint P0 = PointAt(t0);
01083         ON_3dPoint P1 = PointAt(t1);
01084         ON_3dPoint N0 = nurbs.PointAtStart();
01085         ON_3dPoint N1 = nurbs.PointAtEnd();
01086                                 
01087                                 // 22 September 2003, GBA.  The end tuning code below should only  be applied
01088                                 //                                      to clamped nurbs curves.  In particular it should not be used on
01089                                 //                                      periodic nurbs curves.  Fixes TRR#11502.
01090                                 ON_BOOL32 clamped = nurbs.IsClamped(2);
01091         if ( clamped && (P0 != N0 || P1 != N1) )
01092         {
01093           if ( 0==nurbs.m_is_rat )
01094           {
01095             nurbs.SetCV(0,P0);
01096             nurbs.SetCV(nurbs.m_cv_count-1,P1);
01097           }
01098           else
01099           {
01100             ON_4dPoint H0, H1;
01101             H0 = P0;
01102             H0.w = nurbs.Weight(0);
01103             H0.x *= H0.w;
01104             H0.y *= H0.w;
01105             H0.z *= H0.w;
01106             nurbs.SetCV(0,H0);
01107 
01108             H1 = P1;
01109             H1.w = nurbs.Weight(nurbs.m_cv_count-1);
01110             H1.x *= H1.w;
01111             H1.y *= H1.w;
01112             H1.z *= H1.w;
01113             nurbs.SetCV(nurbs.m_cv_count-1,H1);
01114           }
01115         }
01116       }
01117     }
01118   }
01119   return rc;
01120 }
01121 
01122 int 
01123 ON_CurveProxy::HasNurbForm( // returns 0: unable to create NURBS representation
01124                  //            with desired accuracy.
01125                  //         1: success - returned NURBS parameterization
01126                  //            matches the curve's to wthe desired accuracy
01127                  //         2: success - returned NURBS point locus matches
01128                  //            the curve's to the desired accuracy but, on
01129                  //            the interior of the curve's domain, the 
01130                  //            curve's parameterization and the NURBS
01131                  //            parameterization may not match to the 
01132                  //            desired accuracy.
01133       ) const
01134 
01135 {
01136   if (!m_real_curve)
01137     return 0;
01138   return m_real_curve->HasNurbForm();
01139 }
01140 
01141 ON_BOOL32 ON_CurveProxy::GetCurveParameterFromNurbFormParameter(
01142       double nurbs_t,
01143       double* curve_t
01144       ) const
01145 {
01146   ON_BOOL32 rc = false;
01147   if ( m_real_curve ) 
01148   {
01149     // 18 June 2003 Dale Lear and Chuck
01150     //     Fixing joining bug in STEP TEST 2 caused by error
01151     //     in converting NURBS parameter to arc parameter.
01152     const ON_Curve* real_crv = m_real_curve;
01153 
01154     ON_Curve* tmp_real_crv = 0;
01155     if ( m_real_curve_domain != m_real_curve->Domain() )
01156     {
01157       const ON_ArcCurve* arc_curve = ON_ArcCurve::Cast(m_real_curve);
01158       if ( 0 != arc_curve )
01159       {
01160         tmp_real_crv = arc_curve->DuplicateCurve();
01161         if ( 0 != tmp_real_crv )
01162         {
01163           if ( tmp_real_crv->Trim(m_real_curve_domain) )
01164           {
01165             real_crv = tmp_real_crv;
01166           }
01167         }
01168       }
01169     }
01170 
01171     rc = real_crv->GetCurveParameterFromNurbFormParameter( RealCurveParameter(nurbs_t),curve_t);
01172     if ( rc )
01173       *curve_t = ThisCurveParameter(*curve_t);
01174 
01175     if ( 0 != tmp_real_crv )
01176       delete tmp_real_crv;
01177   }
01178   return rc;
01179 }
01180 
01181 ON_BOOL32 ON_CurveProxy::GetNurbFormParameterFromCurveParameter(
01182       double curve_t,
01183       double* nurbs_t
01184       ) const
01185 {
01186   ON_BOOL32 rc = false;
01187   if ( m_real_curve ) 
01188   {
01189     // 18 June 2003 Dale Lear and Chuck
01190     //     Fixing joining bug in STEP TEST 2 caused by error
01191     //     in converting NURBS parameter to arc parameter.
01192     const ON_Curve* real_crv = m_real_curve;
01193 
01194     ON_Curve* tmp_real_crv = 0;
01195     if ( m_real_curve_domain != m_real_curve->Domain() )
01196     {
01197       const ON_ArcCurve* arc_curve = ON_ArcCurve::Cast(m_real_curve);
01198       if ( 0 != arc_curve )
01199       {
01200         tmp_real_crv = arc_curve->DuplicateCurve();
01201         if ( 0 != tmp_real_crv )
01202         {
01203           if ( tmp_real_crv->Trim(m_real_curve_domain) )
01204           {
01205             real_crv = tmp_real_crv;
01206           }
01207         }
01208       }
01209     }
01210 
01211     rc = real_crv->GetNurbFormParameterFromCurveParameter( RealCurveParameter(curve_t),nurbs_t);
01212     if ( rc )
01213       *nurbs_t = ThisCurveParameter(*nurbs_t);
01214 
01215     if ( 0 != tmp_real_crv )
01216       delete tmp_real_crv;
01217   }
01218   return rc;
01219 }


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