10#include "qwt_spline.h" 
   11#include "qwt_spline_parametrization.h" 
   12#include "qwt_spline_polynomial.h" 
   13#include "qwt_bezier.h" 
   15#include <qpainterpath.h> 
   26        inline double operator()( 
const QPointF& p1, 
const QPointF& p2 )
 const 
   36        inline double operator()( 
const QPointF& p1, 
const QPointF& p2 )
 const 
   44        inline double operator()( 
const QPointF& p1, 
const QPointF& p2 )
 const 
   50    struct paramCentripetal
 
   52        inline double operator()( 
const QPointF& p1, 
const QPointF& p2 )
 const 
   60        inline double operator()( 
const QPointF& p1, 
const QPointF& p2 )
 const 
   68        inline double operator()( 
const QPointF& p1, 
const QPointF& p2 )
 const 
   77        inline void init( 
int size )
 
   82        inline void start( 
double x1, 
double y1 )
 
   84            path.moveTo( x1, y1 );
 
   87        inline void addCubic( 
double cx1, 
double cy1,
 
   88            double cx2, 
double cy2, 
double x2, 
double y2 )
 
   90            path.cubicTo( cx1, cy1, cx2, cy2, x2, y2 );
 
  101    class ControlPointsStore
 
  104        inline ControlPointsStore():
 
  109        inline void init( 
int size )
 
  111            controlPoints.resize( size );
 
  112            m_cp = controlPoints.data();
 
  115        inline void start( 
double x1, 
double y1 )
 
  121        inline void addCubic( 
double cx1, 
double cy1,
 
  122            double cx2, 
double cy2, 
double x2, 
double y2 )
 
  128            l.setLine( cx1, cy1, cx2, cy2 );
 
  141    double slopeBoundary( 
int boundaryCondition, 
double boundaryValue,
 
  142        const QPointF& p1, 
const QPointF& p2, 
double slope1 )
 
  144        const double dx = p2.x() - p1.x();
 
  145        const double dy = p2.y() - p1.y();
 
  149        switch( boundaryCondition )
 
  158                const double c2 = 0.5 * boundaryValue;
 
  159                const double c1 = slope1;
 
  161                m = 0.5 * ( 3.0 * dy / dx - c1 - c2 * dx );
 
  166                const double c3 = boundaryValue / 6.0;
 
  167                m = c3 * dx * dx + 2 * dy / dx - slope1;
 
  172                const double s = dy / dx;
 
  173                const double r = qBound( 0.0, boundaryValue, 1.0 );
 
  175                m = s - r * ( s - slope1 );
 
  188template< 
class SplineStore >
 
  189static inline SplineStore qwtSplineC1PathParamX(
 
  190    const QwtSplineC1* spline, 
const QPolygonF& points )
 
  192    const int n = points.size();
 
  196        return SplineStore();
 
  198    const QPointF* pd = points.constData();
 
  199    const double* md = m.constData();
 
  202    store.init( m.size() - 1 );
 
  203    store.start( pd[0].x(), pd[0].y() );
 
  205    for ( 
int i = 0; i < n - 1; i++ )
 
  207        const double dx3 = ( pd[i + 1].x() - pd[i].x() ) / 3.0;
 
  209        store.addCubic( pd[i].x() + dx3, pd[i].y() + md[i] * dx3,
 
  210            pd[i + 1].x() - dx3, pd[i + 1].y() - md[i + 1] * dx3,
 
  211            pd[i + 1].x(), pd[i + 1].y() );
 
  217template< 
class SplineStore >
 
  218static inline SplineStore qwtSplineC1PathParamY(
 
  219    const QwtSplineC1* spline, 
const QPolygonF& points )
 
  221    const int n = points.size();
 
  223    QPolygonF pointsFlipped( n );
 
  224    for ( 
int i = 0; i < n; i++ )
 
  226        pointsFlipped[i].setX( points[i].y() );
 
  227        pointsFlipped[i].setY( points[i].x() );
 
  232        return SplineStore();
 
  234    const QPointF* pd = pointsFlipped.constData();
 
  235    const double* md = m.constData();
 
  238    store.init( m.size() - 1 );
 
  239    store.start( pd[0].y(), pd[0].x() );
 
  242    for ( 
int i = 0; i < n - 1; i++ )
 
  244        const double dx3 = ( pd[i + 1].x() - pd[i].x() ) / 3.0;
 
  246        store.addCubic( pd[i].y() + md[i] * dx3, pd[i].x() + dx3,
 
  247            pd[i + 1].y() - md[i + 1] * dx3, pd[i + 1].x() - dx3,
 
  248            pd[i + 1].y(), pd[i + 1].x() );
 
  254template< 
class SplineStore, 
class Param >
 
  255static inline SplineStore qwtSplineC1PathParametric(
 
  256    const QwtSplineC1* spline, 
const QPolygonF& points, Param param )
 
  259    const int n = points.size();
 
  261    QPolygonF pointsX, pointsY;
 
  262    pointsX.resize( isClosing ? n + 1 : n );
 
  263    pointsY.resize( isClosing ? n + 1 : n );
 
  265    QPointF* px = pointsX.data();
 
  266    QPointF* py = pointsY.data();
 
  267    const QPointF* p = points.constData();
 
  271    px[0].rx() = py[0].rx() = t;
 
  272    px[0].ry() = p[0].x();
 
  273    py[0].ry() = p[0].y();
 
  275    int numParamPoints = 1;
 
  276    for ( 
int i = 1; i < n; i++ )
 
  278        const double td = param( points[i - 1], points[i] );
 
  283            px[numParamPoints].rx() = py[numParamPoints].rx() = t;
 
  285            px[numParamPoints].ry() = p[i].x();
 
  286            py[numParamPoints].ry() = p[i].y();
 
  294        const double td = param( points[n - 1], points[0] );
 
  300            px[numParamPoints].rx() = py[numParamPoints].rx() = t;
 
  302            px[numParamPoints].ry() = p[0].x();
 
  303            py[numParamPoints].ry() = p[0].y();
 
  309    if ( pointsX.size() != numParamPoints )
 
  311        pointsX.resize( numParamPoints );
 
  312        pointsY.resize( numParamPoints );
 
  318    const double* mx = slopesX.constData();
 
  319    const double* my = slopesY.constData();
 
  326    store.init( isClosing ? n : n - 1 );
 
  327    store.start( points[0].x(), points[0].y() );
 
  331    for ( 
int i = 0; i < n - 1; i++ )
 
  333        const QPointF& p1 = p[i];
 
  334        const QPointF& p2 = p[i + 1];
 
  336        const double td = param( p1, p2 );
 
  340            const double t3 = td / 3.0;
 
  342            const double cx1 = p1.x() + mx[j] * t3;
 
  343            const double cy1 = p1.y() + my[j] * t3;
 
  345            const double cx2 = p2.x() - mx[j + 1] * t3;
 
  346            const double cy2 = p2.y() - my[j + 1] * t3;
 
  348            store.addCubic( cx1, cy1, cx2, cy2, p2.x(), p2.y() );
 
  355            store.addCubic( p1.x(), p1.y(), p2.x(), p2.y(), p2.x(), p2.y() );
 
  361        const QPointF& p1 = p[n - 1];
 
  362        const QPointF& p2 = p[0];
 
  364        const double td = param( p1, p2 );
 
  368            const double t3 = td / 3.0;
 
  370            const double cx1 = p1.x() + mx[j] * t3;
 
  371            const double cy1 = p1.y() + my[j] * t3;
 
  373            const double cx2 = p2.x() - mx[0] * t3;
 
  374            const double cy2 = p2.y() - my[0] * t3;
 
  376            store.addCubic( cx1, cy1, cx2, cy2, p2.x(), p2.y() );
 
  380            store.addCubic( p1.x(), p1.y(), p2.x(), p2.y(), p2.x(), p2.y() );
 
  389template< QwtSplinePolynomial toPolynomial( const QPo
intF&, 
double, const QPo
intF&, 
double ) >
 
  390static QPolygonF qwtPolygonParametric( 
double distance,
 
  393    QPolygonF fittedPoints;
 
  395    const QPointF* p = points.constData();
 
  396    const double* v = values.constData();
 
  398    fittedPoints += p[0];
 
  401    const int n = points.size();
 
  403    for ( 
int i = 0; i < n - 1; i++ )
 
  405        const QPointF& p1 = p[i];
 
  406        const QPointF& p2 = p[i + 1];
 
  410        const double l = p2.x() - p1.x();
 
  414            fittedPoints += QPointF( p1.x() + t, p1.y() + polynomial.
valueAt( t ) );
 
  420            if ( qFuzzyCompare( fittedPoints.last().x(), p2.x() ) )
 
  421                fittedPoints.last() = p2;
 
  434class QwtSpline::PrivateData
 
  446        boundaryConditions[0].value = 0.0;
 
  449        boundaryConditions[1].value = 0.0;
 
  454        delete parametrization;
 
  465    } boundaryConditions[2];
 
  498    if ( tolerance <= 0.0 )
 
  502    const int n = path.elementCount();
 
  506    const QPainterPath::Element el = path.elementAt( 0 );
 
  507    if ( el.type != QPainterPath::MoveToElement )
 
  510    QPointF p1( el.x, el.y );
 
  515    for ( 
int i = 1; i < n; i += 3 )
 
  517        const QPainterPath::Element el1 = path.elementAt( i );
 
  518        const QPainterPath::Element el2 = path.elementAt( i + 1 );
 
  519        const QPainterPath::Element el3 = path.elementAt( i + 2 );
 
  521        const QPointF cp1( el1.x, el1.y );
 
  522        const QPointF cp2( el2.x, el2.y );
 
  523        const QPointF p2( el3.x, el3.y );
 
 
  542    m_data = 
new PrivateData;
 
 
  578    if ( m_data->parametrization->
type() != type )
 
  580        delete m_data->parametrization;
 
 
  596        delete m_data->parametrization;
 
 
  607    return m_data->parametrization;
 
 
  628    return m_data->boundaryType;
 
 
  642        m_data->boundaryConditions[position].type = condition;
 
 
  654        return m_data->boundaryConditions[position].type;
 
  656    return m_data->boundaryConditions[0].type; 
 
 
  673        m_data->boundaryConditions[position].value = value;
 
 
  685        return m_data->boundaryConditions[position].value;
 
  687    return m_data->boundaryConditions[0].value; 
 
 
  701    int condition, 
double valueBegin, 
double valueEnd )
 
 
  750    const int n = points.size();
 
  758        path.moveTo( points[0] );
 
  764        path.addPolygon( points );
 
  769    if ( controlLines.size() < n - 1 )
 
  772    const QPointF* p = points.constData();
 
  773    const QLineF* l = controlLines.constData();
 
  776    for ( 
int i = 0; i < n - 1; i++ )
 
  777        path.cubicTo( l[i].p1(), l[i].p2(), p[i + 1] );
 
  780        && ( controlLines.size() >= n ) )
 
  782        path.cubicTo( l[n - 1].p1(), l[n - 1].p2(), p[0] );
 
 
  806    const QPolygonF& points, 
double tolerance )
 const 
  808    if ( tolerance <= 0.0 )
 
  812    if ( controlLines.isEmpty() )
 
  819    const QPointF* p = points.constData();
 
  820    const QLineF* cl = controlLines.constData();
 
  822    const int n = controlLines.size();
 
  826    for ( 
int i = 0; i < n - 1; i++ )
 
  828        const QLineF& l = cl[i];
 
  832    const QPointF& pn = isClosed ? p[0] : p[n];
 
  833    const QLineF& l = cl[n - 1];
 
 
  864    double distance, 
bool withNodes )
 const 
  866    if ( distance <= 0.0 )
 
  869    const int n = points.size();
 
  883    if ( controlLines.size() < n - 1 )
 
  886    path += points.first();
 
  889    const QPointF* p = points.constData();
 
  890    const QLineF* cl = controlLines.constData();
 
  894    for ( 
int i = 0; i < n - 1; i++ )
 
  901                cl[i].p2(), p[i + 1], t / l );
 
  908            if ( qFuzzyCompare( path.last().x(), p[i + 1].x() ) )
 
  909                path.last() = p[i + 1];
 
  922        && ( controlLines.size() >= n ) )
 
  929                cl[n - 1].p2(), p[0], t / l );
 
  934        if ( qFuzzyCompare( path.last().x(), p[0].x() ) )
 
 
  981    if ( points.size() < 2 )
 
  984    return QwtSplineC1P::slopeBoundary(
 
  987        points[0], points[1], slopeNext );
 
 
  999    const int n = points.size();
 
 1001    const QPointF p1( points[n - 1].x(), -points[n - 1].y() );
 
 1002    const QPointF p2( points[n - 2].x(), -points[n - 2].y() );
 
 1014    const double slope = QwtSplineC1P::slopeBoundary( condition, value, p1, p2, -slopeBefore );
 
 
 1045    const int n = points.size();
 
 1049    using namespace QwtSplineC1P;
 
 1056            store = qwtSplineC1PathParamX< PathStore >( 
this, points );
 
 1061            store = qwtSplineC1PathParamY< PathStore >( 
this, points );
 
 1066            store = qwtSplineC1PathParametric< PathStore >(
 
 1067                this, points, paramUniform() );
 
 1072            store = qwtSplineC1PathParametric< PathStore >(
 
 1073                this, points, paramCentripetal() );
 
 1078            store = qwtSplineC1PathParametric< PathStore >(
 
 1079                this, points, paramChordal() );
 
 1084            store = qwtSplineC1PathParametric< PathStore >(
 
 
 1103    using namespace QwtSplineC1P;
 
 1105    const int n = points.size();
 
 1109    ControlPointsStore store;
 
 1114            store = qwtSplineC1PathParamX< ControlPointsStore >( 
this, points );
 
 1119            store = qwtSplineC1PathParamY< ControlPointsStore >( 
this, points );
 
 1124            store = qwtSplineC1PathParametric< ControlPointsStore >(
 
 1125                this, points, paramUniform() );
 
 1130            store = qwtSplineC1PathParametric< ControlPointsStore >(
 
 1131                this, points, paramCentripetal() );
 
 1136            store = qwtSplineC1PathParametric< ControlPointsStore >(
 
 1137                this, points, paramChordal() );
 
 1142            store = qwtSplineC1PathParametric< ControlPointsStore >(
 
 1147    return store.controlPoints;
 
 
 1168    double distance, 
bool withNodes )
 const 
 1172        if ( points.size() > 2 )
 
 1175            if ( m.size() != points.size() )
 
 1178            return qwtPolygonParametric< QwtSplinePolynomial::fromSlopes >(
 
 1179                distance, points, m, withNodes );
 
 
 1202    const QPolygonF& points )
 const 
 1211    for ( 
int i = 1; i < m.size(); i++ )
 
 1214            points[i - 1], m[i - 1], points[i], m[i] );
 
 
 1296    double distance, 
bool withNodes )
 const 
 1300        if ( points.size() > 2 )
 
 1303            if ( cv.size() != points.size() )
 
 1306            return qwtPolygonParametric< QwtSplinePolynomial::fromCurvatures >(
 
 1307                distance, points, cv, withNodes );
 
 
 1348    double* m = 
slopes.data();
 
 1350    const int n = points.size();
 
 1351    const QPointF* p = points.constData();
 
 1355    for ( 
int i = 0; i < n - 1; i++ )
 
 1358        m[i] = polynomial.
c1;
 
 1361    m[n - 1] = polynomial.
slopeAt( p[n - 1].x() - p[n - 2].x() );
 
 
 1389    const QPointF* p = points.constData();
 
 1394    for ( 
int i = 1; i < n; i++ )
 
 1397            p[i - 1], cv[i - 1], p[i], cv[i] );
 
 
An implementation of the de Casteljau’s Algorithm for interpolating Bézier curves.
void appendToPolygon(const QPointF &p1, const QPointF &cp1, const QPointF &cp2, const QPointF &p2, QPolygonF &polygon) const
Interpolate a Bézier curve by a polygon.
static QPointF pointAt(const QPointF &p1, const QPointF &cp1, const QPointF &cp2, const QPointF &p2, double t)
Base class for spline interpolations providing a first order parametric continuity ( C1 ) between adj...
virtual QVector< double > slopes(const QPolygonF &) const =0
Find the first derivative at the control points.
virtual ~QwtSplineC1()
Destructor.
QwtSplineC1()
Constructor.
virtual double slopeAtBeginning(const QPolygonF &, double slopeNext) const
virtual QPainterPath painterPath(const QPolygonF &) const override
Calculate an interpolated painter path.
virtual QPolygonF equidistantPolygon(const QPolygonF &, double distance, bool withNodes) const override
Find an interpolated polygon with "equidistant" points.
virtual QVector< QLineF > bezierControlLines(const QPolygonF &) const override
Interpolate a curve with Bezier curves.
virtual double slopeAtEnd(const QPolygonF &, double slopeBefore) const
virtual QVector< QwtSplinePolynomial > polynomials(const QPolygonF &) const
Calculate the interpolating polynomials for a non parametric spline.
virtual QPolygonF equidistantPolygon(const QPolygonF &, double distance, bool withNodes) const override
Find an interpolated polygon with "equidistant" points.
virtual QVector< double > slopes(const QPolygonF &) const override
Find the first derivative at the control points.
QwtSplineC2()
Constructor.
virtual QVector< double > curvatures(const QPolygonF &) const =0
Find the second derivative at the control points.
virtual QVector< QLineF > bezierControlLines(const QPolygonF &) const override
Interpolate a curve with Bezier curves.
virtual QVector< QwtSplinePolynomial > polynomials(const QPolygonF &) const override
Calculate the interpolating polynomials for a non parametric spline.
virtual ~QwtSplineC2()
Destructor.
virtual QPainterPath painterPath(const QPolygonF &) const override
Interpolate a curve with Bezier curves.
virtual ~QwtSplineG1()
Destructor.
QwtSplineG1()
Constructor.
Base class for all splines.
@ AtBeginning
the condition is at the beginning of the polynomial
@ AtEnd
the condition is at the end of the polynomial
virtual QPainterPath painterPath(const QPolygonF &) const =0
double boundaryValue(BoundaryPosition) const
void setBoundaryType(BoundaryType)
void setBoundaryCondition(BoundaryPosition, int condition)
Define the condition for an endpoint of the spline.
const QwtSplineParametrization * parametrization() const
int boundaryCondition(BoundaryPosition) const
BoundaryType boundaryType() const
virtual uint locality() const
virtual ~QwtSpline()
Destructor.
virtual QPolygonF polygon(const QPolygonF &, double tolerance) const
Interpolate a curve by a polygon.
void setBoundaryConditions(int condition, double valueBegin=0.0, double valueEnd=0.0)
Define the condition at the endpoints of a spline.
void setBoundaryValue(BoundaryPosition, double value)
Define the boundary value.
void setParametrization(int type)
virtual ~QwtSplineInterpolating()
Destructor.
virtual QPolygonF equidistantPolygon(const QPolygonF &, double distance, bool withNodes) const
Find an interpolated polygon with "equidistant" points.
virtual QVector< QLineF > bezierControlLines(const QPolygonF &) const =0
Interpolate a curve with Bezier curves.
QwtSplineInterpolating()
Constructor.
virtual QPolygonF polygon(const QPolygonF &, double tolerance) const override
Interpolate a curve by a polygon.
virtual QPainterPath painterPath(const QPolygonF &) const override
Interpolate a curve with Bezier curves.
Curve parametrization used for a spline interpolation.
static double valueIncrementChordal(const QPointF &, const QPointF &)
Calculate the ParameterChordal value increment for 2 points.
static double valueIncrementCentripetal(const QPointF &, const QPointF &)
Calculate the ParameterCentripetal value increment for 2 points.
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.
static double valueIncrementManhattan(const QPointF &, const QPointF &)
Calculate the ParameterManhattan value increment for 2 points.
static double valueIncrementY(const QPointF &, const QPointF &)
Calculate the ParameterY value increment for 2 points.
A cubic polynomial without constant term.
double slopeAt(double x) const
static QwtSplinePolynomial fromSlopes(const QPointF &p1, double m1, const QPointF &p2, double m2)
double valueAt(double x) const
static QwtSplinePolynomial fromCurvatures(const QPointF &p1, double cv1, const QPointF &p2, double cv2)
double c1
coefficient of the linear summand