static inline SplineStore qwtSplinePathX( const QwtSplineC1 *spline, const QPolygonF &points ) { SplineStore store; const int n = points.size(); const QVector<double> m = spline->slopesX( points ); if ( m.size() != n ) return store; const QPointF *pd = points.constData(); const double *md = m.constData(); store.init( m.size() - 1 ); store.start( pd[0].x(), pd[0].y() ); for ( int i = 0; i < n - 1; i++ ) { const double dx3 = ( pd[i+1].x() - pd[i].x() ) / 3.0; store.addCubic( pd[i].x() + dx3, pd[i].y() + md[i] * dx3, pd[i+1].x() - dx3, pd[i+1].y() - md[i+1] * dx3, pd[i+1].x(), pd[i+1].y() ); } return store; }
static SplineStore qwtSplinePathPleasing( const QPolygonF &points, bool isClosed, Param param ) { const int size = points.size(); const QPointF *p = points.constData(); SplineStore store; store.init( isClosed ? size : size - 1 ); store.start( p[0] ); const QPointF &p0 = isClosed ? p[size-1] : p[0]; double d13 = param(p[0], p[2]); const QwtSplineCardinalG1::Tension t0 = qwtTension( param(p0, p[1]), param(p[0], p[1]), d13, p0, p[0], p[1], p[2] ); const QPointF vec0 = ( p[1] - p0 ) * 0.5; QPointF vec1 = ( p[2] - p[0] ) * 0.5; store.addCubic( p[0] + vec0 * t0.t1, p[1] - vec1 * t0.t2, p[1] ); for ( int i = 1; i < size - 2; i++ ) { const double d23 = param(p[i], p[i+1]); const double d24 = param(p[i], p[i+2]); const QPointF vec2 = ( p[i+2] - p[i] ) * 0.5; const QwtSplineCardinalG1::Tension t = qwtTension( d13, d23, d24, p[i-1], p[i], p[i+1], p[i+2] ); store.addCubic( p[i] + vec1 * t.t1, p[i+1] - vec2 * t.t2, p[i+1] ); d13 = d24; vec1 = vec2; } const QPointF &pn = isClosed ? p[0] : p[size-1]; const double d24 = param( p[size-2], pn ); const QwtSplineCardinalG1::Tension tn = qwtTension( d13, param( p[size-2], p[size-1] ), d24, p[size-3], p[size-2], p[size-1], pn ); const QPointF vec2 = 0.5 * ( pn - p[size-2] ); store.addCubic( p[size-2] + vec1 * tn.t1, p[size-1] - vec2 * tn.t2, p[size-1] ); if ( isClosed ) { const double d34 = param( p[size-1], p[0] ); const double d35 = param( p[size-1], p[1] ); const QPointF vec3 = 0.5 * ( p[1] - p[size-1] ); const QwtSplineCardinalG1::Tension tn = qwtTension( d24, d34, d35, p[size-2], p[size-1], p[0], p[1] ); store.addCubic( p[size-1] + vec2 * tn.t1, p[0] - vec3 * tn.t2, p[0] ); } return store; }
static inline SplineStore qwtSplinePathParam( const QwtSplineC1 *spline, const QPolygonF &points, Param param ) { const int n = points.size(); QPolygonF px, py; px += QPointF( 0.0, points[0].x() ); py += QPointF( 0.0, points[0].y() ); double t = 0.0; for ( int i = 1; i < n; i++ ) { t += param( points[i-1], points[i] ); px += QPointF( t, points[i].x() ); py += QPointF( t, points[i].y() ); } const QVector<double> mx = spline->slopesX( px ); const QVector<double> my = spline->slopesX( py ); SplineStore store; store.init( n - 1 ); store.start( points[0].x(), points[0].y() ); for ( int i = 1; i < n; i++ ) { const double t3 = param( points[i-1], points[i] ) / 3.0; const double cx1 = points[i-1].x() + mx[i-1] * t3; const double cy1 = points[i-1].y() + my[i-1] * t3; const double cx2 = points[i].x() - mx[i] * t3; const double cy2 = points[i].y() - my[i] * t3; store.addCubic( cx1, cy1, cx2, cy2, points[i].x(), points[i].y() ); } if ( spline->isClosing() ) { const double t3 = param( points[n-1], points[0] ) / 3.0; const double cx1 = points[n-1].x() + mx[n-1] * t3; const double cy1 = points[n-1].y() + my[n-1] * t3; const double cx2 = points[0].x() - mx[0] * t3; const double cy2 = points[0].y() - my[0] * t3; store.addCubic( cx1, cy1, cx2, cy2, points[0].x(), points[0].y() ); store.end(); } return store; }
static SplineStore qwtSplinePathG1( const QwtSplineCardinalG1 *spline, const QPolygonF &points ) { const int size = points.size(); const int numTensions = spline->isClosing() ? size : size - 1; const QVector<QwtSplineCardinalG1::Tension> tensions2 = spline->tensions( points ); if ( tensions2.size() != numTensions ) return SplineStore(); const QPointF *p = points.constData(); const QwtSplineCardinalG1::Tension *t = tensions2.constData(); SplineStore store; store.init( numTensions ); store.start( p[0] ); const QPointF &p0 = spline->isClosing() ? p[size-1] : p[0]; QPointF vec1 = ( p[1] - p0 ) * 0.5; for ( int i = 0; i < size - 2; i++ ) { const QPointF vec2 = ( p[i+2] - p[i] ) * 0.5; store.addCubic( p[i] + vec1 * t[i].t1, p[i+1] - vec2 * t[i].t2, p[i+1] ); vec1 = vec2; } const QPointF &pn = spline->isClosing() ? p[0] : p[size-1]; const QPointF vec2 = 0.5 * ( pn - p[size - 2] ); store.addCubic( p[size - 2] + vec1 * t[size-2].t1, p[size - 1] - vec2 * t[size-2].t2, p[size - 1] ); if ( spline->isClosing() ) { const QPointF vec3 = 0.5 * ( p[1] - p[size-1] ); store.addCubic( p[size-1] + vec2 * t[size-1].t1, p[0] - vec3 * t[size-1].t2, p[0] ); } return store; }
static SplineStore qwtSplinePathPleasing( const QPolygonF &points, bool isClosed, Param param ) { using namespace QwtSplinePleasingP; const int size = points.size(); const QPointF *p = points.constData(); SplineStore store; store.init( isClosed ? size : size - 1 ); store.start( p[0] ); double d13; QPointF vec1; if ( isClosed ) { d13 = qwtChordalLength(p[0], p[2]); const Tension t0 = qwtTensionPleasing( qwtChordalLength( p[size-1], p[1]), qwtChordalLength(p[0], p[1]), d13, p[size-1], p[0], p[1], p[2] ); const QPointF vec0 = qwtVectorCardinal<Param>( param, p[size-1], p[0], p[1] ); vec1 = qwtVectorCardinal<Param>( param, p[0], p[1], p[2] ); store.addCubic( p[0] + vec0 * t0.t1, p[1] - vec1 * t0.t2, p[1] ); } else { d13 = qwtChordalLength(p[0], p[2]); const Tension t0 = qwtTensionPleasing( qwtChordalLength( p[0], p[1]), qwtChordalLength(p[0], p[1]), d13, p[0], p[0], p[1], p[2] ); const QPointF vec0 = 0.5 * qwtVector<Param>( param, p[0], p[1] ); vec1 = qwtVectorCardinal<Param>( param, p[0], p[1], p[2] ); store.addCubic( p[0] + vec0 * t0.t1, p[1] - vec1 * t0.t2, p[1] ); } for ( int i = 1; i < size - 2; i++ ) { const double d23 = qwtChordalLength( p[i], p[i+1] ); const double d24 = qwtChordalLength( p[i], p[i+2] ); const QPointF vec2 = qwtVectorCardinal<Param>( param, p[i], p[i+1], p[i+2] ); const Tension t = qwtTensionPleasing( d13, d23, d24, p[i-1], p[i], p[i+1], p[i+2] ); store.addCubic( p[i] + vec1 * t.t1, p[i+1] - vec2 * t.t2, p[i+1] ); d13 = d24; vec1 = vec2; } if ( isClosed ) { const double d24 = qwtChordalLength( p[size-2], p[0] ); const Tension tn = qwtTensionPleasing( d13, qwtChordalLength( p[size-2], p[size-1] ), d24, p[size-3], p[size-2], p[size-1], p[0] ); const QPointF vec2 = qwtVectorCardinal<Param>( param, p[size-2], p[size-1], p[0] ); store.addCubic( p[size-2] + vec1 * tn.t1, p[size-1] - vec2 * tn.t2, p[size-1] ); const double d34 = qwtChordalLength( p[size-1], p[0] ); const double d35 = qwtChordalLength( p[size-1], p[1] ); const Tension tc = qwtTensionPleasing( d24, d34, d35, p[size-2], p[size-1], p[0], p[1] ); const QPointF vec3 = qwtVectorCardinal<Param>( param, p[size-1], p[0], p[1] ); store.addCubic( p[size-1] + vec2 * tc.t1, p[0] - vec3 * tc.t2, p[0] ); } else { const double d24 = qwtChordalLength( p[size-2], p[size-1] ); const Tension tn = qwtTensionPleasing( d13, qwtChordalLength( p[size-2], p[size-1] ), d24, p[size-3], p[size-2], p[size-1], p[size-1] ); const QPointF vec2 = 0.5 * qwtVector<Param>( param, p[size-2], p[size-1] ); store.addCubic( p[size-2] + vec1 * tn.t1, p[size-1] - vec2 * tn.t2, p[size-1] ); } return store; }