Qwt User's Guide 6.3.0
Loading...
Searching...
No Matches
qwt_spline_basis.cpp
1/******************************************************************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
9
10#include "qwt_spline_basis.h"
11#include "qwt_spline_parametrization.h"
12#include <qpainterpath.h>
13
14#if 0
15static QPolygonF qwtBasisUniformKnots( const QPolygonF& points )
16{
17 const int n = points.size();
18
19 if ( n < 3 )
20 return points;
21
22 QVector< double > u( n - 2 );
23 QVector< double > kx( n - 2 );
24 QVector< double > ky( n - 2 );
25
26 u[n - 3] = 4.0;
27 kx[n - 3] = 6.0 * points[n - 2].x() - points[n - 1].x();
28 ky[n - 3] = 6.0 * points[n - 2].y() - points[n - 1].y();
29
30 for ( int i = n - 4; i >= 0; i-- )
31 {
32 u[i] = 4.0 - 1.0 / u[i + 1];
33 kx[i] = 6.0 * points[i + 1].x() - kx[i + 1] / u[i + 1];
34 ky[i] = 6.0 * points[i + 1].y() - ky[i + 1] / u[i + 1];
35 }
36
37 QVector< QPointF > knots( n );
38
39 knots[0] = points[0];
40
41 for ( int i = 1; i < n - 1; i++ )
42 {
43 knots[i].rx() = ( kx[i - 1] - knots[i - 1].x() ) / u[i - 1];
44 knots[i].ry() = ( ky[i - 1] - knots[i - 1].y() ) / u[i - 1];
45 }
46
47 knots[n - 1] = points[n - 1];
48
49 return knots;
50}
51#endif
52
53#if 0
54static inline void qwtSplineBezierControlPoints( const QwtSplineParametrization* param,
55 const QPointF& p1, const QPointF& p2, const QPointF& p3, const QPointF& p4,
56 QPointF& cp1, QPointF& cp2 )
57{
58 const double t1 = param->valueIncrement( p1, p2 );
59 const double t2 = param->valueIncrement( p2, p3 );
60 const double t3 = param->valueIncrement( p3, p4 );
61
62 const double t123 = t1 + t2 + t3;
63
64 cp1 = ( t2 + t3 ) / t123 * p2 + t1 / t123 * p3;
65 cp2 = ( t3 * p2 + ( t1 + t2 ) * p3 ) / t123;
66}
67#endif
68
69static QPainterPath qwtSplineBasisPathUniform( const QPolygonF& points,
70 QwtSpline::BoundaryType boundaryType )
71{
72 const int n = points.size();
73 const QPointF* pd = points.constData();
74
75 QPainterPath path;
76
77 QPointF cp1 = ( 2.0 * pd[0] + pd[1] ) / 3.0;;
78
79 if ( boundaryType == QwtSpline::ConditionalBoundaries )
80 {
81 path.moveTo( pd[0] );
82 }
83 else
84 {
85 const QPointF cpN = ( pd[n - 1] + 2.0 * pd[0] ) / 3.0;
86 path.moveTo( 0.5 * ( cpN + cp1 ) );
87 }
88
89 for ( int i = 1; i < n - 1; i++ )
90 {
91 const QPointF cp2 = ( pd[i - 1] + 2.0 * pd[i] ) / 3.0;
92 const QPointF cp3 = ( 2.0 * pd[i] + pd[i + 1] ) / 3.0;
93
94 path.cubicTo( cp1, cp2, 0.5 * ( cp2 + cp3 ) );
95
96 cp1 = cp3;
97 }
98
99 if ( boundaryType == QwtSpline::ConditionalBoundaries )
100 {
101 const QPointF cp2 = ( pd[n - 2] + 2.0 * pd[n - 1] ) / 3.0;
102 path.cubicTo( cp1, cp2, pd[n - 1] );
103 }
104 else
105 {
106 const QPointF cp2 = ( pd[n - 2] + 2.0 * pd[n - 1] ) / 3.0;
107 const QPointF cp3 = ( 2.0 * pd[n - 1] + pd[0] ) / 3.0;
108
109 path.cubicTo( cp1, cp2, 0.5 * ( cp2 + cp3 ) );
110
111 if ( boundaryType == QwtSpline::ClosedPolygon )
112 {
113 const QPointF cp4 = ( pd[n - 1] + 2.0 * pd[0] ) / 3.0;
114 const QPointF cp5 = ( 2.0 * pd[0] + pd[1] ) / 3.0;
115
116 path.cubicTo( cp3, cp4, 0.5 * ( cp4 + cp5 ) );
117 }
118 }
119
120 return path;
121}
122
123static QPainterPath qwtSplineBasisPath( const QPolygonF& points,
124 const QwtSplineParametrization* param,
125 QwtSpline::BoundaryType boundaryType )
126{
127 const int n = points.size();
128 const QPointF* pd = points.constData();
129
130 QPointF p0;
131
132 double t1 = param->valueIncrement( pd[0], pd[1] );
133 double t2 = param->valueIncrement( pd[1], pd[2] );
134
135 double t0;
136 if ( boundaryType == QwtSpline::ConditionalBoundaries )
137 t0 = t1;
138 else
139 t0 = param->valueIncrement( pd[n - 1], pd[0] );
140
141 double t012 = t0 + t1 + t2;
142 QPointF cp1 = ( ( t1 + t2 ) * pd[0] + t0 * pd[1] ) / t012;
143
144 if ( boundaryType == QwtSpline::ConditionalBoundaries )
145 {
146 p0 = pd[0];
147 }
148 else
149 {
150 const double tN = param->valueIncrement( pd[n - 2], pd[n - 1] );
151 const QPointF cpN = ( t1 * pd[n - 1] + ( tN + t0 ) * pd[0] ) / ( tN + t0 + t1 );
152
153 p0 = ( t1 * cpN + t0 * cp1 ) / ( t0 + t1 );
154 }
155
156 QPainterPath path;
157 path.moveTo( p0 );
158
159 for ( int i = 1; i < n - 2; i++ )
160 {
161 const double t3 = param->valueIncrement( pd[i + 1], pd[i + 2] );
162 const double t123 = t1 + t2 + t3;
163
164 const QPointF cp2 = ( t2 * pd[i - 1] + ( t0 + t1 ) * pd[i] ) / t012;
165 const QPointF cp3 = ( ( t2 + t3 ) * pd[i] + t1 * pd[i + 1] ) / t123;
166
167 const QPointF p2 = ( t2 * cp2 + t1 * cp3 ) / ( t1 + t2 );
168
169 path.cubicTo( cp1, cp2, p2 );
170
171 cp1 = cp3;
172
173 t0 = t1;
174 t1 = t2;
175 t2 = t3;
176 t012 = t123;
177 }
178
179 {
180 double t3;
181 if ( boundaryType == QwtSpline::ConditionalBoundaries )
182 t3 = t2;
183 else
184 t3 = param->valueIncrement( pd[n - 1], pd[0] );
185
186 const double t123 = t1 + t2 + t3;
187
188 const QPointF cp2 = ( t2 * pd[n - 3] + ( t0 + t1 ) * pd[n - 2] ) / t012;
189 const QPointF cp3 = ( ( t2 + t3 ) * pd[n - 2] + t1 * pd[n - 1] ) / t123;
190
191 const QPointF p2 = ( t2 * cp2 + t1 * cp3 ) / ( t1 + t2 );
192
193 path.cubicTo( cp1, cp2, p2 );
194
195 cp1 = cp3;
196
197 t0 = t1;
198 t1 = t2;
199 t2 = t3;
200 t012 = t123;
201 }
202
203 const QPointF cp2 = ( t2 * pd[n - 2] + ( t0 + t1 ) * pd[n - 1] ) / t012;
204
205 if ( boundaryType == QwtSpline::ConditionalBoundaries )
206 {
207 path.cubicTo( cp1, cp2, pd[n - 1] );
208 }
209 else
210 {
211 const double t3 = param->valueIncrement( pd[0], pd[1] );
212 const double t123 = t1 + t2 + t3;
213
214 const QPointF cp3 = ( t2 + t3 ) / t123 * pd[n - 1] + t1 / t123 * pd[0];
215 const QPointF cp4 = ( t3 * pd[n - 1] + ( t1 + t2 ) * pd[0] ) / t123;
216
217 const QPointF pN = ( t2 * cp2 + t1 * cp3 ) / ( t1 + t2 );
218
219 path.cubicTo( cp1, cp2, pN );
220 path.cubicTo( cp3, cp4, p0 );
221 }
222
223 return path;
224}
225
230
235
238{
239 return 2;
240}
241
249QPainterPath QwtSplineBasis::painterPath( const QPolygonF& points ) const
250{
251 if ( points.size() < 4 )
252 return QPainterPath();
253
254 QPainterPath path;
255
256 switch( parametrization()->type() )
257 {
259 {
260 path = qwtSplineBasisPathUniform( points, boundaryType() );
261 break;
262 }
263 default:
264 {
265 path = qwtSplineBasisPath( points, parametrization(), boundaryType() );
266 }
267 }
268
269 return path;
270}
virtual uint locality() const override
The locality is always 2.
virtual ~QwtSplineBasis()
Destructor.
QwtSplineBasis()
Constructor.
virtual QPainterPath painterPath(const QPolygonF &) const override
const QwtSplineParametrization * parametrization() const
BoundaryType boundaryType() const
@ ClosedPolygon
Definition qwt_spline.h:92
@ ConditionalBoundaries
Definition qwt_spline.h:72
Curve parametrization used for a spline interpolation.
virtual double valueIncrement(const QPointF &, const QPointF &) const
Calculate the parameter value increment for 2 points.