10 #include "qwt_spline_local.h" 
   11 #include "qwt_spline_parametrization.h" 
   12 #include "qwt_spline_polynomial.h" 
   14 #include <qpainterpath.h> 
   16 static inline bool qwtIsStrictlyMonotonic( 
double dy1, 
double dy2 )
 
   18     if ( dy1 == 0.0 || dy2 == 0.0 )
 
   21     return ( dy1 > 0.0 ) == ( dy2 > 0.0 );
 
   24 static inline double qwtSlopeLine( 
const QPointF& p1, 
const QPointF& p2 )
 
   27     const double dx = p2.x() - p1.x();
 
   28     return dx ? ( p2.y() - p1.y() ) / dx : 0.0;
 
   31 static inline double qwtSlopeCardinal(
 
   32     double dx1, 
double dy1, 
double s1, 
double dx2, 
double dy2, 
double s2 )
 
   37     return ( dy1 + dy2 ) / ( dx1 + dx2 );
 
   40 static inline double qwtSlopeParabolicBlending(
 
   41     double dx1, 
double dy1, 
double s1, 
double dx2, 
double dy2, 
double s2 )
 
   46     return ( dx2 * s1 + dx1 * s2 ) / ( dx1 + dx2 );
 
   49 static inline double qwtSlopePChip(
 
   50     double dx1, 
double dy1, 
double s1, 
double dx2, 
double dy2, 
double s2 )
 
   52     if ( qwtIsStrictlyMonotonic( dy1, dy2 ) )
 
   56         const double w1 = ( 3 * dx1 + 3 * dx2 ) / ( 2 * dx1 + 4 * dx2 );
 
   57         const double w2 = ( 3 * dx1 + 3 * dx2 ) / ( 4 * dx1 + 2 * dx2 );
 
   63         return 2.0 / ( 1.0 / s1 + 1.0 / s2 );
 
   67         const double s12 = ( dy1 + dy2 ) / ( dx1 + dx2 );
 
   68         return 3.0 * ( s1 * s2 ) / ( s1 + s2 + s12 );
 
   74 namespace QwtSplineLocalP
 
   83         inline void start( 
const QPointF& p0, 
double )
 
   88         inline void addCubic( 
const QPointF& p1, 
double m1,
 
   89             const QPointF& p2, 
double m2 )
 
   91             const double dx3 = ( p2.x() - p1.x() ) / 3.0;
 
   93             path.cubicTo( p1.x() + dx3, p1.y() + m1 * dx3,
 
   94                 p2.x() - dx3, p2.y() - m2 * dx3,
 
  101     class ControlPointsStore
 
  106             if ( points.size() > 0 )
 
  107                 controlPoints.resize( points.size() - 1 );
 
  108             m_cp = controlPoints.data();
 
  111         inline void start( 
const QPointF&, 
double )
 
  115         inline void addCubic( 
const QPointF& p1, 
double m1,
 
  116             const QPointF& p2, 
double m2 )
 
  118             const double dx3 = ( p2.x() - p1.x() ) / 3.0;
 
  121             l.setLine( p1.x() + dx3, p1.y() + m1 * dx3,
 
  122                 p2.x() - dx3, p2.y() - m2 * dx3 );
 
  136             slopes.resize( points.size() );
 
  140         inline void start( 
const QPointF&, 
double m0 )
 
  145         inline void addCubic( 
const QPointF&, 
double,
 
  146             const QPointF&, 
double m2 )
 
  159         static inline double value( 
double dx1, 
double dy1, 
double s1,
 
  160             double dx2, 
double dy2, 
double s2 )
 
  162             return qwtSlopeCardinal( dx1, dy1, s1, dx2, dy2, s2 );
 
  166     struct slopeParabolicBlending
 
  168         static inline double value( 
double dx1, 
double dy1, 
double s1,
 
  169             double dx2, 
double dy2, 
double s2 )
 
  171             return qwtSlopeParabolicBlending( dx1, dy1, s1, dx2, dy2, s2 );
 
  177         static inline double value( 
double dx1, 
double dy1, 
double s1,
 
  178             double dx2, 
double dy2, 
double s2 )
 
  180             return qwtSlopePChip( dx1, dy1, s1, dx2, dy2, s2 );
 
  185 template< 
class Slope >
 
  186 static inline double qwtSlopeP3(
 
  187     const QPointF& p1, 
const QPointF& p2, 
const QPointF& p3 )
 
  189     const double dx1 = p2.x() - p1.x();
 
  190     const double dy1 = p2.y() - p1.y();
 
  191     const double dx2 = p3.x() - p2.x();
 
  192     const double dy2 = p3.y() - p2.y();
 
  194     return Slope::value( dx1, dy1, dy1 / dx1, dx2, dy2, dy2 / dx2 );
 
  197 static inline double qwtSlopeAkima( 
double s1, 
double s2, 
double s3, 
double s4 )
 
  199     if ( ( s1 == s2 ) && ( s3 == s4 ) )
 
  201         return 0.5 * ( s2 + s3 );
 
  204     const double ds12 = qAbs( s2 - s1 );
 
  205     const double ds34 = qAbs( s4 - s3 );
 
  207     return ( s2 * ds34 + s3 * ds12 ) / ( ds12 + ds34 );
 
  210 static inline double qwtSlopeAkima( 
const QPointF& p1, 
const QPointF& p2,
 
  211     const QPointF& p3, 
const QPointF& p4, 
const QPointF& p5 )
 
  213     const double s1 = qwtSlopeLine( p1, p2 );
 
  214     const double s2 = qwtSlopeLine( p2, p3 );
 
  215     const double s3 = qwtSlopeLine( p3, p4 );
 
  216     const double s4 = qwtSlopeLine( p4, p5 );
 
  218     return qwtSlopeAkima( s1, s2, s3, s4 );
 
  221 template< 
class Slope >
 
  222 static void qwtSplineBoundariesL1(
 
  224     double& slopeBegin, 
double& slopeEnd )
 
  226     const int n = points.size();
 
  227     const QPointF* p = points.constData();
 
  232         const QPointF pn = p[0] - ( p[n - 1] - p[n - 2] );
 
  233         slopeBegin = slopeEnd = qwtSlopeP3< Slope >( pn, p[0], p[1] );
 
  237         const double m2 = qwtSlopeP3< Slope >( p[0], p[1], p[2] );
 
  240         const double mn2 = qwtSlopeP3< Slope >( p[n - 3], p[n - 2], p[n - 1] );
 
  245 template< 
class SplineStore, 
class Slope >
 
  246 static inline SplineStore qwtSplineL1(
 
  249     const int size = points.size();
 
  250     const QPointF* p = points.constData();
 
  252     double slopeBegin, slopeEnd;
 
  253     qwtSplineBoundariesL1< Slope >( spline, points, slopeBegin, slopeEnd );
 
  255     double m1 = slopeBegin;
 
  258     store.init( points );
 
  259     store.start( p[0], m1 );
 
  261     double dx1 = p[1].x() - p[0].x();
 
  262     double dy1 = p[1].y() - p[0].y();
 
  263     double s1 = dy1 / dx1;
 
  265     for ( 
int i = 1; i < size - 1; i++ )
 
  267         const double dx2 = p[i + 1].x() - p[i].x();
 
  268         const double dy2 = p[i + 1].y() - p[i].y();
 
  272         const double s2 = dy2 / dx2;
 
  274         const double m2 = Slope::value( dx1, dy1, s1, dx2, dy2, s2 );
 
  276         store.addCubic( p[i - 1], m1, p[i], m2 );
 
  284     store.addCubic( p[size - 2], m1, p[size - 1], slopeEnd );
 
  289 static inline void qwtSplineAkimaBoundaries(
 
  291     double& slopeBegin, 
double& slopeEnd )
 
  293     const int n = points.size();
 
  294     const QPointF* p = points.constData();
 
  299         const QPointF p2 = p[0] - ( p[n - 1] - p[n - 2] );
 
  300         const QPointF p1 = p2 - ( p[n - 2] - p[n - 3] );
 
  302         slopeBegin = slopeEnd = qwtSlopeAkima( p1, p2, p[0], p[1], p[2] );
 
  318         const double s1 = qwtSlopeLine( p[0], p[1] );
 
  319         const double s2 = qwtSlopeLine( p[1], p[2] );
 
  320         const double m = qwtSlopeAkima( 0.5 * s1, s1, s2, 0.5 * s2 );
 
  329         s[0] = qwtSlopeLine( p[0], p[1] );
 
  330         s[1] = qwtSlopeLine( p[1], p[2] );
 
  331         s[2] = qwtSlopeLine( p[2], p[3] );
 
  333         const double m2 = qwtSlopeAkima( 0.5 * s[0], s[0], s[1], s[2] );
 
  337         s[0] = qwtSlopeLine( p[n - 4], p[n - 3] );
 
  338         s[1] = qwtSlopeLine( p[n - 3], p[n - 2] );
 
  339         s[2] = qwtSlopeLine( p[n - 2], p[n - 1] );
 
  341         const double mn2 = qwtSlopeAkima( s[0], s[1], s[2], 0.5 * s[2] );
 
  347 template< 
class SplineStore >
 
  348 static inline SplineStore qwtSplineAkima(
 
  351     const int size = points.size();
 
  352     const QPointF* p = points.constData();
 
  354     double slopeBegin, slopeEnd;
 
  355     qwtSplineAkimaBoundaries( spline, points, slopeBegin, slopeEnd );
 
  357     double m1 = slopeBegin;
 
  360     store.init( points );
 
  361     store.start( p[0], m1 );
 
  363     double s2 = qwtSlopeLine( p[0], p[1] );
 
  364     double s3 = qwtSlopeLine( p[1], p[2] );
 
  365     double s1 = 0.5 * s2;
 
  367     for ( 
int i = 0; i < size - 3; i++ )
 
  369         const double s4 = qwtSlopeLine( p[i + 2],  p[i + 3] );
 
  371         const double m2 = qwtSlopeAkima( s1, s2, s3, s4 );
 
  372         store.addCubic( p[i], m1, p[i + 1], m2 );
 
  381     const double m2 = qwtSlopeAkima( s1, s2, s3, 0.5 * s3 );
 
  383     store.addCubic( p[size - 3], m1, p[size - 2], m2 );
 
  384     store.addCubic( p[size - 2], m2, p[size - 1], slopeEnd );
 
  389 template< 
class SplineStore >
 
  390 static inline SplineStore qwtSplineLocal(
 
  395     const int size = points.size();
 
  401         const double s0 = qwtSlopeLine( points[0], points[1] );
 
  403         const double m2 = spline->
slopeAtEnd( points, s0 );
 
  405         store.init( points );
 
  406         store.start( points[0], m1 );
 
  407         store.addCubic( points[0], m1, points[1], m2 );
 
  412     switch( spline->
type() )
 
  416             using namespace QwtSplineLocalP;
 
  417             store = qwtSplineL1< SplineStore, slopeCardinal >( spline, points );
 
  422             using namespace QwtSplineLocalP;
 
  423             store = qwtSplineL1< SplineStore, slopeParabolicBlending >( spline, points );
 
  428             using namespace QwtSplineLocalP;
 
  429             store = qwtSplineL1< SplineStore, slopePChip >( spline, points );
 
  434             store = qwtSplineAkima< SplineStore >( spline, points );
 
  486         using namespace QwtSplineLocalP;
 
  487         return qwtSplineLocal< PathStore >( 
this, points).path;
 
  506         using namespace QwtSplineLocalP;
 
  507         return qwtSplineLocal< ControlPointsStore >( 
this, points ).controlPoints;
 
  523     using namespace QwtSplineLocalP;
 
  524     return qwtSplineLocal< SlopeStore >( 
this, points ).slopes;
 
virtual double slopeAtBeginning(const QPolygonF &, double slopeNext) const
virtual QPainterPath painterPath(const QPolygonF &) const override
Calculate an interpolated painter path.
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.
@ AtBeginning
the condition is at the beginning of the polynomial
@ AtEnd
the condition is at the end of the polynomial
double boundaryValue(BoundaryPosition) const
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
void setBoundaryValue(BoundaryPosition, double value)
Define the boundary value.
A spline with C1 continuity.
Type
Spline interpolation type.
virtual ~QwtSplineLocal()
Destructor.
virtual uint locality() const override
virtual QPainterPath painterPath(const QPolygonF &) const override
Interpolate a curve with Bezier curves.
QwtSplineLocal(Type type)
Constructor.
virtual QVector< QLineF > bezierControlLines(const QPolygonF &) const override
Interpolate a curve with Bezier curves.
virtual QVector< double > slopes(const QPolygonF &) const override
Find the first derivative at the control points.
virtual QVector< QwtSplinePolynomial > polynomials(const QPolygonF &) const override
Calculate the interpolating polynomials for a non parametric spline.