14 #include <qpainterpath.h>
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;
32 double dx1,
double dy1,
double s1,
double dx2,
double dy2,
double s2 )
37 return ( dy1 + dy2 ) / ( dx1 + dx2 );
41 double dx1,
double dy1,
double s1,
double dx2,
double dy2,
double s2 )
46 return ( dx2 * s1 + dx1 * s2 ) / ( dx1 + dx2 );
50 double dx1,
double dy1,
double s1,
double dx2,
double dy2,
double s2 )
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 );
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,
106 if ( points.size() > 0 )
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 )
146 const QPointF&,
double m2 )
159 static inline double value(
double dx1,
double dy1,
double s1,
160 double dx2,
double dy2,
double s2 )
168 static inline double value(
double dx1,
double dy1,
double s1,
169 double dx2,
double dy2,
double s2 )
177 static inline double value(
double dx1,
double dy1,
double s1,
178 double dx2,
double dy2,
double s2 )
185 template<
class Slope >
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 );
211 const QPointF& p3,
const QPointF& p4,
const QPointF& p5 )
221 template<
class Slope >
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 >
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 );
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] );
320 const double m =
qwtSlopeAkima( 0.5 * s1, s1, s2, 0.5 * s2 );
347 template<
class SplineStore >
351 const int size = points.size();
352 const QPointF* p = points.constData();
354 double slopeBegin, slopeEnd;
357 double m1 = slopeBegin;
360 store.init( points );
361 store.start( p[0], m1 );
365 double s1 = 0.5 * s2;
367 for (
int i = 0; i <
size - 3; i++ )
372 store.addCubic( p[i], m1, p[i + 1], m2 );
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 >
395 const int size = points.size();
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() )
417 store = qwtSplineL1< SplineStore, slopeCardinal >( spline, points );
423 store = qwtSplineL1< SplineStore, slopeParabolicBlending >( spline, points );
429 store = qwtSplineL1< SplineStore, slopePChip >( spline, points );
434 store = qwtSplineAkima< SplineStore >( spline, points );
487 return qwtSplineLocal< PathStore >(
this, points).path;
507 return qwtSplineLocal< ControlPointsStore >(
this, points ).controlPoints;
524 return qwtSplineLocal< SlopeStore >(
this, points ).slopes;