10#include "qwt_spline_pleasing.h"
11#include "qwt_spline_parametrization.h"
13#include <qpainterpath.h>
15static inline double qwtChordalLength(
const QPointF& point1,
const QPointF& point2 )
17 const double dx = point2.x() - point1.x();
18 const double dy = point2.y() - point1.y();
20 return std::sqrt( dx * dx + dy * dy );
23template<
class Param >
24static QPointF qwtVector( Param param,
25 const QPointF& p1,
const QPointF& p2 )
27 return ( p2 - p1 ) / param( p1, p2 );
30template<
class Param >
31static QPointF qwtVectorCardinal( Param param,
32 const QPointF& p1,
const QPointF& p2,
const QPointF& p3 )
34 const double t1 = param( p1, p2 );
35 const double t2 = param( p2, p3 );
37 return t2 * ( p3 - p1 ) / ( t1 + t2 );
40namespace QwtSplinePleasingP
55 inline double operator()(
const QPointF& p1,
const QPointF& p2 )
const
65 inline double operator()(
const QPointF& p1,
const QPointF& p2 )
const
74 inline void init(
int )
78 inline void start(
const QPointF& p0 )
83 inline void addCubic(
const QPointF& cp1,
84 const QPointF& cp2,
const QPointF& p2 )
86 path.cubicTo( cp1, cp2, p2 );
92 class ControlPointsStore
95 inline ControlPointsStore():
100 inline void init(
int size )
102 controlPoints.resize( size );
103 m_cp = controlPoints.data();
106 inline void start(
const QPointF& )
110 inline void addCubic(
const QPointF& cp1,
111 const QPointF& cp2,
const QPointF& )
114 l.setPoints( cp1, cp2 );
124static inline QwtSplinePleasingP::Tension qwtTensionPleasing(
125 double d13,
double d23,
double d24,
126 const QPointF& p1,
const QPointF& p2,
127 const QPointF& p3,
const QPointF& p4 )
129 QwtSplinePleasingP::Tension tension;
131 const bool b1 = ( d13 / 3.0 ) < d23;
132 const bool b2 = ( d24 / 3.0 ) < d23;
138 tension.t1 = ( p1 != p2 ) ? ( 1.0 / 3.0 ) : ( 2.0 / 3.0 );
139 tension.t2 = ( p3 != p4 ) ? ( 1.0 / 3.0 ) : ( 2.0 / 3.0 );
143 tension.t1 = tension.t2 = d23 / d24;
150 tension.t1 = tension.t2 = d23 / d13;
154 tension.t1 = d23 / d13;
155 tension.t2 = d23 / d24;
162template<
class SplineStore,
class Param >
163static SplineStore qwtSplinePathPleasing(
const QPolygonF& points,
164 bool isClosed, Param param )
166 using namespace QwtSplinePleasingP;
168 const int size = points.size();
170 const QPointF* p = points.constData();
173 store.init( isClosed ? size : size - 1 );
181 d13 = qwtChordalLength(p[0], p[2]);
183 const Tension t0 = qwtTensionPleasing(
184 qwtChordalLength( p[size - 1], p[1]), qwtChordalLength(p[0], p[1]),
185 d13, p[size - 1], p[0], p[1], p[2] );
187 const QPointF vec0 = qwtVectorCardinal< Param >( param, p[size - 1], p[0], p[1] );
188 vec1 = qwtVectorCardinal< Param >( param, p[0], p[1], p[2] );
190 store.addCubic( p[0] + vec0 * t0.t1, p[1] - vec1 * t0.t2, p[1] );
194 d13 = qwtChordalLength(p[0], p[2]);
196 const Tension t0 = qwtTensionPleasing(
197 qwtChordalLength( p[0], p[1]), qwtChordalLength(p[0], p[1]),
198 d13, p[0], p[0], p[1], p[2] );
200 const QPointF vec0 = 0.5 * qwtVector< Param >( param, p[0], p[1] );
201 vec1 = qwtVectorCardinal< Param >( param, p[0], p[1], p[2] );
203 store.addCubic( p[0] + vec0 * t0.t1, p[1] - vec1 * t0.t2, p[1] );
206 for (
int i = 1; i < size - 2; i++ )
208 const double d23 = qwtChordalLength( p[i], p[i + 1] );
209 const double d24 = qwtChordalLength( p[i], p[i + 2] );
211 const QPointF vec2 = qwtVectorCardinal< Param >( param, p[i], p[i + 1], p[i + 2] );
213 const Tension t = qwtTensionPleasing(
214 d13, d23, d24, p[i - 1], p[i], p[i + 1], p[i + 2] );
216 store.addCubic( p[i] + vec1 * t.t1, p[i + 1] - vec2 * t.t2, p[i + 1] );
224 const double d24 = qwtChordalLength( p[size - 2], p[0] );
226 const Tension tn = qwtTensionPleasing(
227 d13, qwtChordalLength( p[size - 2], p[size - 1] ), d24,
228 p[size - 3], p[size - 2], p[size - 1], p[0] );
230 const QPointF vec2 = qwtVectorCardinal< Param >( param, p[size - 2], p[size - 1], p[0] );
231 store.addCubic( p[size - 2] + vec1 * tn.t1, p[size - 1] - vec2 * tn.t2, p[size - 1] );
233 const double d34 = qwtChordalLength( p[size - 1], p[0] );
234 const double d35 = qwtChordalLength( p[size - 1], p[1] );
236 const Tension tc = qwtTensionPleasing( d24, d34, d35, p[size - 2], p[size - 1], p[0], p[1] );
238 const QPointF vec3 = qwtVectorCardinal< Param >( param, p[size - 1], p[0], p[1] );
240 store.addCubic( p[size - 1] + vec2 * tc.t1, p[0] - vec3 * tc.t2, p[0] );
244 const double d24 = qwtChordalLength( p[size - 2], p[size - 1] );
246 const Tension tn = qwtTensionPleasing(
247 d13, qwtChordalLength( p[size - 2], p[size - 1] ), d24,
248 p[size - 3], p[size - 2], p[size - 1], p[size - 1] );
250 const QPointF vec2 = 0.5 * qwtVector< Param >( param, p[size - 2], p[size - 1] );
251 store.addCubic( p[size - 2] + vec1 * tn.t1, p[size - 1] - vec2 * tn.t2, p[size - 1] );
292 const int size = points.size();
298 using namespace QwtSplinePleasingP;
303 store = qwtSplinePathPleasing< PathStore >( points,
304 isClosing, paramUniform() );
308 store = qwtSplinePathPleasing< PathStore >( points,
313 store.path.closeSubpath();
328 const QPolygonF& points )
const
330 const int size = points.size();
336 using namespace QwtSplinePleasingP;
338 ControlPointsStore store;
341 store = qwtSplinePathPleasing< ControlPointsStore >( points,
342 isClosing, paramUniform() );
346 store = qwtSplinePathPleasing< ControlPointsStore >( points,
350 return store.controlPoints;
virtual QPainterPath painterPath(const QPolygonF &) const =0
const QwtSplineParametrization * parametrization() const
BoundaryType boundaryType() const
void setParametrization(int type)
Curve parametrization used for a spline interpolation.
static double valueIncrementUniform(const QPointF &, const QPointF &)
Calculate the ParameterUniform value increment.
virtual double valueIncrement(const QPointF &, const QPointF &) const
Calculate the parameter value increment for 2 points.
virtual uint locality() const override
virtual QVector< QLineF > bezierControlLines(const QPolygonF &) const override
Interpolate a curve with Bezier curves.
virtual ~QwtSplinePleasing()
Destructor.
virtual QPainterPath painterPath(const QPolygonF &) const override
Interpolate a curve with Bezier curves.
QwtSplinePleasing()
Constructor.