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