10 #include "qwt_weeding_curve_fitter.h" 
   13 #include <qpainterpath.h> 
   18 class QwtWeedingCurveFitter::PrivateData
 
   31 class QwtWeedingCurveFitter::Line
 
   34     Line( 
int i1 = 0, 
int i2 = 0 )
 
   53     m_data = 
new PrivateData;
 
   78     m_data->tolerance = qwtMaxF( 
tolerance, 0.0 );
 
   87     return m_data->tolerance;
 
  104         numPoints = qMax( numPoints, 3U );
 
  106     m_data->chunkSize = numPoints;
 
  116     return m_data->chunkSize;
 
  126     if ( points.isEmpty() )
 
  129     QPolygonF fittedPoints;
 
  130     if ( m_data->chunkSize == 0 )
 
  132         fittedPoints = simplify( points );
 
  136         for ( 
int i = 0; i < points.size(); i += m_data->chunkSize )
 
  138             const QPolygonF p = points.mid( i, m_data->chunkSize );
 
  139             fittedPoints += simplify( p );
 
  154     path.addPolygon( 
fitCurve( points ) );
 
  158 QPolygonF QwtWeedingCurveFitter::simplify( 
const QPolygonF& points )
 const 
  160     const double toleranceSqr = m_data->tolerance * m_data->tolerance;
 
  163     stack.reserve( 500 );
 
  165     const QPointF* p = points.data();
 
  166     const int nPoints = points.size();
 
  170     stack.push( Line( 0, nPoints - 1 ) );
 
  172     while ( !stack.isEmpty() )
 
  174         const Line r = stack.pop();
 
  177         const double vecX = p[r.to].x() - p[r.from].x();
 
  178         const double vecY = p[r.to].y() - p[r.from].y();
 
  180         const double vecLength = std::sqrt( vecX * vecX + vecY * vecY );
 
  182         const double unitVecX = ( vecLength != 0.0 ) ? vecX / vecLength : 0.0;
 
  183         const double unitVecY = ( vecLength != 0.0 ) ? vecY / vecLength : 0.0;
 
  185         double maxDistSqr = 0.0;
 
  186         int nVertexIndexMaxDistance = r.from + 1;
 
  187         for ( 
int i = r.from + 1; i < r.to; i++ )
 
  190             const double fromVecX = p[i].x() - p[r.from].x();
 
  191             const double fromVecY = p[i].y() - p[r.from].y();
 
  193             double distToSegmentSqr;
 
  194             if ( fromVecX * unitVecX + fromVecY * unitVecY < 0.0 )
 
  196                 distToSegmentSqr = fromVecX * fromVecX + fromVecY * fromVecY;
 
  200                 const double toVecX = p[i].x() - p[r.to].x();
 
  201                 const double toVecY = p[i].y() - p[r.to].y();
 
  202                 const double toVecLength = toVecX * toVecX + toVecY * toVecY;
 
  204                 const double s = toVecX * ( -unitVecX ) + toVecY * ( -unitVecY );
 
  207                     distToSegmentSqr = toVecLength;
 
  211                     distToSegmentSqr = std::fabs( toVecLength - s * s );
 
  215             if ( maxDistSqr < distToSegmentSqr )
 
  217                 maxDistSqr = distToSegmentSqr;
 
  218                 nVertexIndexMaxDistance = i;
 
  221         if ( maxDistSqr <= toleranceSqr )
 
  223             usePoint[r.from] = 
true;
 
  224             usePoint[r.to] = 
true;
 
  228             stack.push( Line( r.from, nVertexIndexMaxDistance ) );
 
  229             stack.push( Line( nVertexIndexMaxDistance, r.to ) );
 
  234     for ( 
int i = 0; i < nPoints; i++ )
 
Abstract base class for a curve fitter.
virtual QPolygonF fitCurve(const QPolygonF &) const override
void setTolerance(double)
QwtWeedingCurveFitter(double tolerance=1.0)
virtual ~QwtWeedingCurveFitter()
Destructor.
virtual QPainterPath fitCurvePath(const QPolygonF &) const override