10#include "qwt_weeding_curve_fitter.h" 
   13#include <qpainterpath.h> 
   18class QwtWeedingCurveFitter::PrivateData
 
   31class 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 ) );
 
 
  158QPolygonF 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