Qwt User's Guide: qwt_spline.cpp Source File

Qwt User's Guide 6.2.0

qwt_spline.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.h"
11 #include "qwt_spline_parametrization.h"
12 #include "qwt_spline_polynomial.h"
13 #include "qwt_bezier.h"
14
15 #include <qpainterpath.h>
16
17 namespace QwtSplineC1P
18 {
19 struct param
20 {
21 param( const QwtSplineParametrization* p ):
22 parameter( p )
23 {
24 }
25
26 inline double operator()( const QPointF& p1, const QPointF& p2 ) const
27 {
28 return parameter->valueIncrement( p1, p2 );
29 }
30
31 const QwtSplineParametrization* parameter;
32 };
33
34 struct paramY
35 {
36 inline double operator()( const QPointF& p1, const QPointF& p2 ) const
37 {
38 return QwtSplineParametrization::valueIncrementY( p1, p2 );
39 }
40 };
41
42 struct paramUniform
43 {
44 inline double operator()( const QPointF& p1, const QPointF& p2 ) const
45 {
46 return QwtSplineParametrization::valueIncrementUniform( p1, p2 );
47 }
48 };
49
50 struct paramCentripetal
51 {
52 inline double operator()( const QPointF& p1, const QPointF& p2 ) const
53 {
54 return QwtSplineParametrization::valueIncrementCentripetal( p1, p2 );
55 }
56 };
57
58 struct paramChordal
59 {
60 inline double operator()( const QPointF& p1, const QPointF& p2 ) const
61 {
62 return QwtSplineParametrization::valueIncrementChordal( p1, p2 );
63 }
64 };
65
66 struct paramManhattan
67 {
68 inline double operator()( const QPointF& p1, const QPointF& p2 ) const
69 {
70 return QwtSplineParametrization::valueIncrementManhattan( p1, p2 );
71 }
72 };
73
74 class PathStore
75 {
76 public:
77 inline void init( int size )
78 {
79 Q_UNUSED(size);
80 }
81
82 inline void start( double x1, double y1 )
83 {
84 path.moveTo( x1, y1 );
85 }
86
87 inline void addCubic( double cx1, double cy1,
88 double cx2, double cy2, double x2, double y2 )
89 {
90 path.cubicTo( cx1, cy1, cx2, cy2, x2, y2 );
91 }
92
93 inline void end()
94 {
95 path.closeSubpath();
96 }
97
98 QPainterPath path;
99 };
100
101 class ControlPointsStore
102 {
103 public:
104 inline ControlPointsStore():
105 m_cp( NULL )
106 {
107 }
108
109 inline void init( int size )
110 {
111 controlPoints.resize( size );
112 m_cp = controlPoints.data();
113 }
114
115 inline void start( double x1, double y1 )
116 {
117 Q_UNUSED( x1 );
118 Q_UNUSED( y1 );
119 }
120
121 inline void addCubic( double cx1, double cy1,
122 double cx2, double cy2, double x2, double y2 )
123 {
124 Q_UNUSED( x2 );
125 Q_UNUSED( y2 );
126
127 QLineF& l = *m_cp++;
128 l.setLine( cx1, cy1, cx2, cy2 );
129 }
130
131 inline void end()
132 {
133 }
134
135 QVector< QLineF > controlPoints;
136
137 private:
138 QLineF* m_cp;
139 };
140
141 double slopeBoundary( int boundaryCondition, double boundaryValue,
142 const QPointF& p1, const QPointF& p2, double slope1 )
143 {
144 const double dx = p2.x() - p1.x();
145 const double dy = p2.y() - p1.y();
146
147 double m = 0.0;
148
149 switch( boundaryCondition )
150 {
151 case QwtSpline::Clamped1:
152 {
153 m = boundaryValue;
154 break;
155 }
156 case QwtSpline::Clamped2:
157 {
158 const double c2 = 0.5 * boundaryValue;
159 const double c1 = slope1;
160
161 m = 0.5 * ( 3.0 * dy / dx - c1 - c2 * dx );
162 break;
163 }
164 case QwtSpline::Clamped3:
165 {
166 const double c3 = boundaryValue / 6.0;
167 m = c3 * dx * dx + 2 * dy / dx - slope1;
168 break;
169 }
170 case QwtSpline::LinearRunout:
171 {
172 const double s = dy / dx;
173 const double r = qBound( 0.0, boundaryValue, 1.0 );
174
175 m = s - r * ( s - slope1 );
176 break;
177 }
178 default:
179 {
180 m = dy / dx; // something
181 }
182 }
183
184 return m;
185 }
186 }
187
188 template< class SplineStore >
189 static inline SplineStore qwtSplineC1PathParamX(
190 const QwtSplineC1* spline, const QPolygonF& points )
191 {
192 const int n = points.size();
193
194 const QVector< double > m = spline->slopes( points );
195 if ( m.size() != n )
196 return SplineStore();
197
198 const QPointF* pd = points.constData();
199 const double* md = m.constData();
200
201 SplineStore store;
202 store.init( m.size() - 1 );
203 store.start( pd[0].x(), pd[0].y() );
204
205 for ( int i = 0; i < n - 1; i++ )
206 {
207 const double dx3 = ( pd[i + 1].x() - pd[i].x() ) / 3.0;
208
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() );
212 }
213
214 return store;
215 }
216
217 template< class SplineStore >
218 static inline SplineStore qwtSplineC1PathParamY(
219 const QwtSplineC1* spline, const QPolygonF& points )
220 {
221 const int n = points.size();
222
223 QPolygonF pointsFlipped( n );
224 for ( int i = 0; i < n; i++ )
225 {
226 pointsFlipped[i].setX( points[i].y() );
227 pointsFlipped[i].setY( points[i].x() );
228 }
229
230 const QVector< double > m = spline->slopes( pointsFlipped );
231 if ( m.size() != n )
232 return SplineStore();
233
234 const QPointF* pd = pointsFlipped.constData();
235 const double* md = m.constData();
236
237 SplineStore store;
238 store.init( m.size() - 1 );
239 store.start( pd[0].y(), pd[0].x() );
240
241 QVector< QLineF > lines( n );
242 for ( int i = 0; i < n - 1; i++ )
243 {
244 const double dx3 = ( pd[i + 1].x() - pd[i].x() ) / 3.0;
245
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() );
249 }
250
251 return store;
252 }
253
254 template< class SplineStore, class Param >
255 static inline SplineStore qwtSplineC1PathParametric(
256 const QwtSplineC1* spline, const QPolygonF& points, Param param )
257 {
258 const bool isClosing = ( spline->boundaryType() == QwtSpline::ClosedPolygon );
259 const int n = points.size();
260
261 QPolygonF pointsX, pointsY;
262 pointsX.resize( isClosing ? n + 1 : n );
263 pointsY.resize( isClosing ? n + 1 : n );
264
265 QPointF* px = pointsX.data();
266 QPointF* py = pointsY.data();
267 const QPointF* p = points.constData();
268
269 double t = 0.0;
270
271 px[0].rx() = py[0].rx() = t;
272 px[0].ry() = p[0].x();
273 py[0].ry() = p[0].y();
274
275 int numParamPoints = 1;
276 for ( int i = 1; i < n; i++ )
277 {
278 const double td = param( points[i - 1], points[i] );
279 if ( td > 0.0 )
280 {
281 t += td;
282
283 px[numParamPoints].rx() = py[numParamPoints].rx() = t;
284
285 px[numParamPoints].ry() = p[i].x();
286 py[numParamPoints].ry() = p[i].y();
287
288 numParamPoints++;
289 }
290 }
291
292 if ( isClosing )
293 {
294 const double td = param( points[n - 1], points[0] );
295
296 if ( td > 0.0 )
297 {
298 t += td;
299
300 px[numParamPoints].rx() = py[numParamPoints].rx() = t;
301
302 px[numParamPoints].ry() = p[0].x();
303 py[numParamPoints].ry() = p[0].y();
304
305 numParamPoints++;
306 }
307 }
308
309 if ( pointsX.size() != numParamPoints )
310 {
311 pointsX.resize( numParamPoints );
312 pointsY.resize( numParamPoints );
313 }
314
315 const QVector< double > slopesX = spline->slopes( pointsX );
316 const QVector< double > slopesY = spline->slopes( pointsY );
317
318 const double* mx = slopesX.constData();
319 const double* my = slopesY.constData();
320
321 // we don't need it anymore
322 pointsX.clear();
323 pointsY.clear();
324
325 SplineStore store;
326 store.init( isClosing ? n : n - 1 );
327 store.start( points[0].x(), points[0].y() );
328
329 int j = 0;
330
331 for ( int i = 0; i < n - 1; i++ )
332 {
333 const QPointF& p1 = p[i];
334 const QPointF& p2 = p[i + 1];
335
336 const double td = param( p1, p2 );
337
338 if ( td != 0.0 )
339 {
340 const double t3 = td / 3.0;
341
342 const double cx1 = p1.x() + mx[j] * t3;
343 const double cy1 = p1.y() + my[j] * t3;
344
345 const double cx2 = p2.x() - mx[j + 1] * t3;
346 const double cy2 = p2.y() - my[j + 1] * t3;
347
348 store.addCubic( cx1, cy1, cx2, cy2, p2.x(), p2.y() );
349
350 j++;
351 }
352 else
353 {
354 // setting control points to the ends
355 store.addCubic( p1.x(), p1.y(), p2.x(), p2.y(), p2.x(), p2.y() );
356 }
357 }
358
359 if ( isClosing )
360 {
361 const QPointF& p1 = p[n - 1];
362 const QPointF& p2 = p[0];
363
364 const double td = param( p1, p2 );
365
366 if ( td != 0.0 )
367 {
368 const double t3 = td / 3.0;
369
370 const double cx1 = p1.x() + mx[j] * t3;
371 const double cy1 = p1.y() + my[j] * t3;
372
373 const double cx2 = p2.x() - mx[0] * t3;
374 const double cy2 = p2.y() - my[0] * t3;
375
376 store.addCubic( cx1, cy1, cx2, cy2, p2.x(), p2.y() );
377 }
378 else
379 {
380 store.addCubic( p1.x(), p1.y(), p2.x(), p2.y(), p2.x(), p2.y() );
381 }
382
383 store.end();
384 }
385
386 return store;
387 }
388
389 template< QwtSplinePolynomial toPolynomial( const QPointF&, double, const QPointF&, double ) >
390 static QPolygonF qwtPolygonParametric( double distance,
391 const QPolygonF& points, const QVector< double >& values, bool withNodes )
392 {
393 QPolygonF fittedPoints;
394
395 const QPointF* p = points.constData();
396 const double* v = values.constData();
397
398 fittedPoints += p[0];
399 double t = distance;
400
401 const int n = points.size();
402
403 for ( int i = 0; i < n - 1; i++ )
404 {
405 const QPointF& p1 = p[i];
406 const QPointF& p2 = p[i + 1];
407
408 const QwtSplinePolynomial polynomial = toPolynomial( p1, v[i], p2, v[i + 1] );
409
410 const double l = p2.x() - p1.x();
411
412 while ( t < l )
413 {
414 fittedPoints += QPointF( p1.x() + t, p1.y() + polynomial.valueAt( t ) );
415 t += distance;
416 }
417
418 if ( withNodes )
419 {
420 if ( qFuzzyCompare( fittedPoints.last().x(), p2.x() ) )
421 fittedPoints.last() = p2;
422 else
423 fittedPoints += p2;
424 }
425 else
426 {
427 t -= l;
428 }
429 }
430
431 return fittedPoints;
432 }
433
434 class QwtSpline::PrivateData
435 {
436 public:
437 PrivateData()
438 : boundaryType( QwtSpline::ConditionalBoundaries )
439 {
440 parametrization = new QwtSplineParametrization(
441 QwtSplineParametrization::ParameterChordal );
442
443 // parabolic runout at both ends
444
445 boundaryConditions[0].type = QwtSpline::Clamped3;
446 boundaryConditions[0].value = 0.0;
447
448 boundaryConditions[1].type = QwtSpline::Clamped3;
449 boundaryConditions[1].value = 0.0;
450 }
451
452 ~PrivateData()
453 {
454 delete parametrization;
455 }
456
457 QwtSplineParametrization* parametrization;
458 QwtSpline::BoundaryType boundaryType;
459
460 struct
461 {
462 int type;
463 double value;
464
465 } boundaryConditions[2];
466 };
467
496 QPolygonF QwtSpline::polygon( const QPolygonF& points, double tolerance ) const
497 {
498 if ( tolerance <= 0.0 )
499 return QPolygonF();
500
501 const QPainterPath path = painterPath( points );
502 const int n = path.elementCount();
503 if ( n == 0 )
504 return QPolygonF();
505
506 const QPainterPath::Element el = path.elementAt( 0 );
507 if ( el.type != QPainterPath::MoveToElement )
508 return QPolygonF();
509
510 QPointF p1( el.x, el.y );
511
512 QPolygonF polygon;
513 QwtBezier bezier( tolerance );
514
515 for ( int i = 1; i < n; i += 3 )
516 {
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 );
520
521 const QPointF cp1( el1.x, el1.y );
522 const QPointF cp2( el2.x, el2.y );
523 const QPointF p2( el3.x, el3.y );
524
525 bezier.appendToPolygon( p1, cp1, cp2, p2, polygon );
526
527 p1 = p2;
528 }
529
530 return polygon;
531 }
532
540 QwtSpline::QwtSpline()
541 {
542 m_data = new PrivateData;
543 }
544
546 QwtSpline::~QwtSpline()
547 {
548 delete m_data;
549 }
550
564 uint QwtSpline::locality() const
565 {
566 return 0;
567 }
568
576 void QwtSpline::setParametrization( int type )
577 {
578 if ( m_data->parametrization->type() != type )
579 {
580 delete m_data->parametrization;
581 m_data->parametrization = new QwtSplineParametrization( type );
582 }
583 }
584
592 void QwtSpline::setParametrization( QwtSplineParametrization* parametrization )
593 {
594 if ( ( parametrization != NULL ) && ( m_data->parametrization != parametrization ) )
595 {
596 delete m_data->parametrization;
597 m_data->parametrization = parametrization;
598 }
599 }
600
605 const QwtSplineParametrization* QwtSpline::parametrization() const
606 {
607 return m_data->parametrization;
608 }
609
617 void QwtSpline::setBoundaryType( BoundaryType boundaryType )
618 {
619 m_data->boundaryType = boundaryType;
620 }
621
626 QwtSpline::BoundaryType QwtSpline::boundaryType() const
627 {
628 return m_data->boundaryType;
629 }
630
639 void QwtSpline::setBoundaryCondition( BoundaryPosition position, int condition )
640 {
641 if ( ( position == QwtSpline::AtBeginning ) || ( position == QwtSpline::AtEnd ) )
642 m_data->boundaryConditions[position].type = condition;
643 }
644
651 int QwtSpline::boundaryCondition( BoundaryPosition position ) const
652 {
653 if ( ( position == QwtSpline::AtBeginning ) || ( position == QwtSpline::AtEnd ) )
654 return m_data->boundaryConditions[position].type;
655
656 return m_data->boundaryConditions[0].type; // should never happen
657 }
658
670 void QwtSpline::setBoundaryValue( BoundaryPosition position, double value )
671 {
672 if ( ( position == QwtSpline::AtBeginning ) || ( position == QwtSpline::AtEnd ) )
673 m_data->boundaryConditions[position].value = value;
674 }
675
682 double QwtSpline::boundaryValue( BoundaryPosition position ) const
683 {
684 if ( ( position == QwtSpline::AtBeginning ) || ( position == QwtSpline::AtEnd ) )
685 return m_data->boundaryConditions[position].value;
686
687 return m_data->boundaryConditions[0].value; // should never happen
688 }
689
700 void QwtSpline::setBoundaryConditions(
701 int condition, double valueBegin, double valueEnd )
702 {
703 setBoundaryCondition( QwtSpline::AtBeginning, condition );
704 setBoundaryValue( QwtSpline::AtBeginning, valueBegin );
705
706 setBoundaryCondition( QwtSpline::AtEnd, condition );
707 setBoundaryValue( QwtSpline::AtEnd, valueEnd );
708 }
709
711 QwtSplineInterpolating::QwtSplineInterpolating()
712 {
713 }
714
716 QwtSplineInterpolating::~QwtSplineInterpolating()
717 {
718 }
719
748 QPainterPath QwtSplineInterpolating::painterPath( const QPolygonF& points ) const
749 {
750 const int n = points.size();
751
752 QPainterPath path;
753 if ( n == 0 )
754 return path;
755
756 if ( n == 1 )
757 {
758 path.moveTo( points[0] );
759 return path;
760 }
761
762 if ( n == 2 )
763 {
764 path.addPolygon( points );
765 return path;
766 }
767
768 const QVector< QLineF > controlLines = bezierControlLines( points );
769 if ( controlLines.size() < n - 1 )
770 return path;
771
772 const QPointF* p = points.constData();
773 const QLineF* l = controlLines.constData();
774
775 path.moveTo( p[0] );
776 for ( int i = 0; i < n - 1; i++ )
777 path.cubicTo( l[i].p1(), l[i].p2(), p[i + 1] );
778
779 if ( ( boundaryType() == QwtSpline::ClosedPolygon )
780 && ( controlLines.size() >= n ) )
781 {
782 path.cubicTo( l[n - 1].p1(), l[n - 1].p2(), p[0] );
783 path.closeSubpath();
784 }
785
786 return path;
787 }
788
805 QPolygonF QwtSplineInterpolating::polygon(
806 const QPolygonF& points, double tolerance ) const
807 {
808 if ( tolerance <= 0.0 )
809 return QPolygonF();
810
811 const QVector< QLineF > controlLines = bezierControlLines( points );
812 if ( controlLines.isEmpty() )
813 return QPolygonF();
814
815 const bool isClosed = boundaryType() == QwtSpline::ClosedPolygon;
816
817 QwtBezier bezier( tolerance );
818
819 const QPointF* p = points.constData();
820 const QLineF* cl = controlLines.constData();
821
822 const int n = controlLines.size();
823
824 QPolygonF polygon;
825
826 for ( int i = 0; i < n - 1; i++ )
827 {
828 const QLineF& l = cl[i];
829 bezier.appendToPolygon( p[i], l.p1(), l.p2(), p[i + 1], polygon );
830 }
831
832 const QPointF& pn = isClosed ? p[0] : p[n];
833 const QLineF& l = cl[n - 1];
834
835 bezier.appendToPolygon( p[n - 1], l.p1(), l.p2(), pn, polygon );
836
837 return polygon;
838 }
839
863 QPolygonF QwtSplineInterpolating::equidistantPolygon( const QPolygonF& points,
864 double distance, bool withNodes ) const
865 {
866 if ( distance <= 0.0 )
867 return QPolygonF();
868
869 const int n = points.size();
870 if ( n <= 1 )
871 return points;
872
873 if ( n == 2 )
874 {
875 // TODO
876 return points;
877 }
878
879 QPolygonF path;
880
881 const QVector< QLineF > controlLines = bezierControlLines( points );
882
883 if ( controlLines.size() < n - 1 )
884 return path;
885
886 path += points.first();
887 double t = distance;
888
889 const QPointF* p = points.constData();
890 const QLineF* cl = controlLines.constData();
891
892 const QwtSplineParametrization* param = parametrization();
893
894 for ( int i = 0; i < n - 1; i++ )
895 {
896 const double l = param->valueIncrement( p[i], p[i + 1] );
897
898 while ( t < l )
899 {
900 path += QwtBezier::pointAt( p[i], cl[i].p1(),
901 cl[i].p2(), p[i + 1], t / l );
902
903 t += distance;
904 }
905
906 if ( withNodes )
907 {
908 if ( qFuzzyCompare( path.last().x(), p[i + 1].x() ) )
909 path.last() = p[i + 1];
910 else
911 path += p[i + 1];
912
913 t = distance;
914 }
915 else
916 {
917 t -= l;
918 }
919 }
920
921 if ( ( boundaryType() == QwtSpline::ClosedPolygon )
922 && ( controlLines.size() >= n ) )
923 {
924 const double l = param->valueIncrement( p[n - 1], p[0] );
925
926 while ( t < l )
927 {
928 path += QwtBezier::pointAt( p[n - 1], cl[n - 1].p1(),
929 cl[n - 1].p2(), p[0], t / l );
930
931 t += distance;
932 }
933
934 if ( qFuzzyCompare( path.last().x(), p[0].x() ) )
935 path.last() = p[0];
936 else
937 path += p[0];
938 }
939
940 return path;
941 }
942
944 QwtSplineG1::QwtSplineG1()
945 {
946 }
947
949 QwtSplineG1::~QwtSplineG1()
950 {
951 }
952
962 QwtSplineC1::QwtSplineC1()
963 {
964 setParametrization( QwtSplineParametrization::ParameterX );
965 }
966
968 QwtSplineC1::~QwtSplineC1()
969 {
970 }
971
979 double QwtSplineC1::slopeAtBeginning( const QPolygonF& points, double slopeNext ) const
980 {
981 if ( points.size() < 2 )
982 return 0.0;
983
984 return QwtSplineC1P::slopeBoundary(
985 boundaryCondition( QwtSpline::AtBeginning ),
986 boundaryValue( QwtSpline::AtBeginning ),
987 points[0], points[1], slopeNext );
988 }
989
997 double QwtSplineC1::slopeAtEnd( const QPolygonF& points, double slopeBefore ) const
998 {
999 const int n = points.size();
1000
1001 const QPointF p1( points[n - 1].x(), -points[n - 1].y() );
1002 const QPointF p2( points[n - 2].x(), -points[n - 2].y() );
1003
1004 const int condition = boundaryCondition( QwtSpline::AtEnd );
1005
1006 double value = boundaryValue( QwtSpline::AtEnd );
1007 if ( condition != QwtSpline::LinearRunout )
1008 {
1009 // beside LinearRunout the boundaryValue is a slope or curvature
1010 // and needs to be inverted too
1011 value = -value;
1012 }
1013
1014 const double slope = QwtSplineC1P::slopeBoundary( condition, value, p1, p2, -slopeBefore );
1015 return -slope;
1016 }
1017
1043 QPainterPath QwtSplineC1::painterPath( const QPolygonF& points ) const
1044 {
1045 const int n = points.size();
1046 if ( n <= 2 )
1047 return QwtSplineInterpolating::painterPath( points );
1048
1049 using namespace QwtSplineC1P;
1050
1051 PathStore store;
1052 switch( parametrization()->type() )
1053 {
1054 case QwtSplineParametrization::ParameterX:
1055 {
1056 store = qwtSplineC1PathParamX< PathStore >( this, points );
1057 break;
1058 }
1059 case QwtSplineParametrization::ParameterY:
1060 {
1061 store = qwtSplineC1PathParamY< PathStore >( this, points );
1062 break;
1063 }
1064 case QwtSplineParametrization::ParameterUniform:
1065 {
1066 store = qwtSplineC1PathParametric< PathStore >(
1067 this, points, paramUniform() );
1068 break;
1069 }
1070 case QwtSplineParametrization::ParameterCentripetal:
1071 {
1072 store = qwtSplineC1PathParametric< PathStore >(
1073 this, points, paramCentripetal() );
1074 break;
1075 }
1076 case QwtSplineParametrization::ParameterChordal:
1077 {
1078 store = qwtSplineC1PathParametric< PathStore >(
1079 this, points, paramChordal() );
1080 break;
1081 }
1082 default:
1083 {
1084 store = qwtSplineC1PathParametric< PathStore >(
1085 this, points, param( parametrization() ) );
1086 }
1087 }
1088
1089 return store.path;
1090 }
1091
1101 QVector< QLineF > QwtSplineC1::bezierControlLines( const QPolygonF& points ) const
1102 {
1103 using namespace QwtSplineC1P;
1104
1105 const int n = points.size();
1106 if ( n <= 2 )
1107 return QVector< QLineF >();
1108
1109 ControlPointsStore store;
1110 switch( parametrization()->type() )
1111 {
1112 case QwtSplineParametrization::ParameterX:
1113 {
1114 store = qwtSplineC1PathParamX< ControlPointsStore >( this, points );
1115 break;
1116 }
1117 case QwtSplineParametrization::ParameterY:
1118 {
1119 store = qwtSplineC1PathParamY< ControlPointsStore >( this, points );
1120 break;
1121 }
1122 case QwtSplineParametrization::ParameterUniform:
1123 {
1124 store = qwtSplineC1PathParametric< ControlPointsStore >(
1125 this, points, paramUniform() );
1126 break;
1127 }
1128 case QwtSplineParametrization::ParameterCentripetal:
1129 {
1130 store = qwtSplineC1PathParametric< ControlPointsStore >(
1131 this, points, paramCentripetal() );
1132 break;
1133 }
1134 case QwtSplineParametrization::ParameterChordal:
1135 {
1136 store = qwtSplineC1PathParametric< ControlPointsStore >(
1137 this, points, paramChordal() );
1138 break;
1139 }
1140 default:
1141 {
1142 store = qwtSplineC1PathParametric< ControlPointsStore >(
1143 this, points, param( parametrization() ) );
1144 }
1145 }
1146
1147 return store.controlPoints;
1148 }
1149
1167 QPolygonF QwtSplineC1::equidistantPolygon( const QPolygonF& points,
1168 double distance, bool withNodes ) const
1169 {
1170 if ( parametrization()->type() == QwtSplineParametrization::ParameterX )
1171 {
1172 if ( points.size() > 2 )
1173 {
1174 const QVector< double > m = slopes( points );
1175 if ( m.size() != points.size() )
1176 return QPolygonF();
1177
1178 return qwtPolygonParametric< QwtSplinePolynomial::fromSlopes >(
1179 distance, points, m, withNodes );
1180 }
1181 }
1182
1183 return QwtSplineInterpolating::equidistantPolygon( points, distance, withNodes );
1184 }
1185
1201 QVector< QwtSplinePolynomial > QwtSplineC1::polynomials(
1202 const QPolygonF& points ) const
1203 {
1204 QVector< QwtSplinePolynomial > polynomials;
1205
1206 const QVector< double > m = slopes( points );
1207 if ( m.size() < 2 )
1208 return polynomials;
1209
1210 polynomials.reserve( m.size() - 1 );
1211 for ( int i = 1; i < m.size(); i++ )
1212 {
1213 polynomials += QwtSplinePolynomial::fromSlopes(
1214 points[i - 1], m[i - 1], points[i], m[i] );
1215 }
1216
1217 return polynomials;
1218 }
1219
1228 QwtSplineC2::QwtSplineC2()
1229 {
1230 }
1231
1233 QwtSplineC2::~QwtSplineC2()
1234 {
1235 }
1236
1249 QPainterPath QwtSplineC2::painterPath( const QPolygonF& points ) const
1250 {
1251 // could be implemented from curvatures without the extra
1252 // loop for calculating the slopes vector. TODO ...
1253
1254 return QwtSplineC1::painterPath( points );
1255 }
1256
1270 QVector< QLineF > QwtSplineC2::bezierControlLines( const QPolygonF& points ) const
1271 {
1272 // could be implemented from curvatures without the extra
1273 // loop for calculating the slopes vector. TODO ...
1274
1275 return QwtSplineC1::bezierControlLines( points );
1276 }
1277
1295 QPolygonF QwtSplineC2::equidistantPolygon( const QPolygonF& points,
1296 double distance, bool withNodes ) const
1297 {
1298 if ( parametrization()->type() == QwtSplineParametrization::ParameterX )
1299 {
1300 if ( points.size() > 2 )
1301 {
1302 const QVector< double > cv = curvatures( points );
1303 if ( cv.size() != points.size() )
1304 return QPolygonF();
1305
1306 return qwtPolygonParametric< QwtSplinePolynomial::fromCurvatures >(
1307 distance, points, cv, withNodes );
1308 }
1309 }
1310
1311 return QwtSplineInterpolating::equidistantPolygon( points, distance, withNodes );
1312 }
1313
1339 QVector< double > QwtSplineC2::slopes( const QPolygonF& points ) const
1340 {
1341 const QVector< double > curvatures = this->curvatures( points );
1342 if ( curvatures.size() < 2 )
1343 return QVector< double >();
1344
1345 QVector< double > slopes( curvatures.size() );
1346
1347 const double* cv = curvatures.constData();
1348 double* m = slopes.data();
1349
1350 const int n = points.size();
1351 const QPointF* p = points.constData();
1352
1353 QwtSplinePolynomial polynomial;
1354
1355 for ( int i = 0; i < n - 1; i++ )
1356 {
1357 polynomial = QwtSplinePolynomial::fromCurvatures( p[i], cv[i], p[i + 1], cv[i + 1] );
1358 m[i] = polynomial.c1;
1359 }
1360
1361 m[n - 1] = polynomial.slopeAt( p[n - 1].x() - p[n - 2].x() );
1362
1363 return slopes;
1364 }
1365
1381 QVector< QwtSplinePolynomial > QwtSplineC2::polynomials( const QPolygonF& points ) const
1382 {
1383 QVector< QwtSplinePolynomial > polynomials;
1384
1385 const QVector< double > curvatures = this->curvatures( points );
1386 if ( curvatures.size() < 2 )
1387 return polynomials;
1388
1389 const QPointF* p = points.constData();
1390 const double* cv = curvatures.constData();
1391 const int n = curvatures.size();
1392 polynomials.reserve( n - 1 );
1393
1394 for ( int i = 1; i < n; i++ )
1395 {
1396 polynomials += QwtSplinePolynomial::fromCurvatures(
1397 p[i - 1], cv[i - 1], p[i], cv[i] );
1398 }
1399
1400 return polynomials;
1401 }
QVector< QLineF >
QwtBezier
An implementation of the de Casteljau’s Algorithm for interpolating Bézier curves.
Definition: qwt_bezier.h:30
QwtBezier::appendToPolygon
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.
Definition: qwt_bezier.cpp:186
QwtBezier::pointAt
static QPointF pointAt(const QPointF &p1, const QPointF &cp1, const QPointF &cp2, const QPointF &p2, double t)
Definition: qwt_bezier.cpp:239
QwtSplineC1
Base class for spline interpolations providing a first order parametric continuity ( C1 ) between adj...
Definition: qwt_spline.h:236
QwtSplineC1::slopes
virtual QVector< double > slopes(const QPolygonF &) const =0
Find the first derivative at the control points.
QwtSplineC1::~QwtSplineC1
virtual ~QwtSplineC1()
Destructor.
Definition: qwt_spline.cpp:968
QwtSplineC1::QwtSplineC1
QwtSplineC1()
Constructor.
Definition: qwt_spline.cpp:962
QwtSplineC1::slopeAtBeginning
virtual double slopeAtBeginning(const QPolygonF &, double slopeNext) const
Definition: qwt_spline.cpp:979
QwtSplineC1::painterPath
virtual QPainterPath painterPath(const QPolygonF &) const override
Calculate an interpolated painter path.
Definition: qwt_spline.cpp:1043
QwtSplineC1::equidistantPolygon
virtual QPolygonF equidistantPolygon(const QPolygonF &, double distance, bool withNodes) const override
Find an interpolated polygon with "equidistant" points.
Definition: qwt_spline.cpp:1167
QwtSplineC1::bezierControlLines
virtual QVector< QLineF > bezierControlLines(const QPolygonF &) const override
Interpolate a curve with Bezier curves.
Definition: qwt_spline.cpp:1101
QwtSplineC1::slopeAtEnd
virtual double slopeAtEnd(const QPolygonF &, double slopeBefore) const
Definition: qwt_spline.cpp:997
QwtSplineC1::polynomials
virtual QVector< QwtSplinePolynomial > polynomials(const QPolygonF &) const
Calculate the interpolating polynomials for a non parametric spline.
Definition: qwt_spline.cpp:1201
QwtSplineC2::equidistantPolygon
virtual QPolygonF equidistantPolygon(const QPolygonF &, double distance, bool withNodes) const override
Find an interpolated polygon with "equidistant" points.
Definition: qwt_spline.cpp:1295
QwtSplineC2::slopes
virtual QVector< double > slopes(const QPolygonF &) const override
Find the first derivative at the control points.
Definition: qwt_spline.cpp:1339
QwtSplineC2::QwtSplineC2
QwtSplineC2()
Constructor.
Definition: qwt_spline.cpp:1228
QwtSplineC2::bezierControlLines
virtual QVector< QLineF > bezierControlLines(const QPolygonF &) const override
Interpolate a curve with Bezier curves.
Definition: qwt_spline.cpp:1270
QwtSplineC2::polynomials
virtual QVector< QwtSplinePolynomial > polynomials(const QPolygonF &) const override
Calculate the interpolating polynomials for a non parametric spline.
Definition: qwt_spline.cpp:1381
QwtSplineC2::~QwtSplineC2
virtual ~QwtSplineC2()
Destructor.
Definition: qwt_spline.cpp:1233
QwtSplineC2::painterPath
virtual QPainterPath painterPath(const QPolygonF &) const override
Interpolate a curve with Bezier curves.
Definition: qwt_spline.cpp:1249
QwtSplineG1::~QwtSplineG1
virtual ~QwtSplineG1()
Destructor.
Definition: qwt_spline.cpp:949
QwtSplineG1::QwtSplineG1
QwtSplineG1()
Constructor.
Definition: qwt_spline.cpp:944
QwtSpline
Base class for all splines.
Definition: qwt_spline.h:58
QwtSpline::BoundaryPosition
BoundaryPosition
Definition: qwt_spline.h:100
QwtSpline::AtBeginning
@ AtBeginning
the condition is at the beginning of the polynomial
Definition: qwt_spline.h:102
QwtSpline::AtEnd
@ AtEnd
the condition is at the end of the polynomial
Definition: qwt_spline.h:105
QwtSpline::painterPath
virtual QPainterPath painterPath(const QPolygonF &) const =0
QwtSpline::boundaryValue
double boundaryValue(BoundaryPosition) const
Definition: qwt_spline.cpp:682
QwtSpline::setBoundaryType
void setBoundaryType(BoundaryType)
Definition: qwt_spline.cpp:617
QwtSpline::QwtSpline
QwtSpline()
Constructor.
Definition: qwt_spline.cpp:540
QwtSpline::setBoundaryCondition
void setBoundaryCondition(BoundaryPosition, int condition)
Define the condition for an endpoint of the spline.
Definition: qwt_spline.cpp:639
QwtSpline::parametrization
const QwtSplineParametrization * parametrization() const
Definition: qwt_spline.cpp:605
QwtSpline::boundaryCondition
int boundaryCondition(BoundaryPosition) const
Definition: qwt_spline.cpp:651
QwtSpline::boundaryType
BoundaryType boundaryType() const
Definition: qwt_spline.cpp:626
QwtSpline::locality
virtual uint locality() const
Definition: qwt_spline.cpp:564
QwtSpline::~QwtSpline
virtual ~QwtSpline()
Destructor.
Definition: qwt_spline.cpp:546
QwtSpline::polygon
virtual QPolygonF polygon(const QPolygonF &, double tolerance) const
Interpolate a curve by a polygon.
Definition: qwt_spline.cpp:496
QwtSpline::setBoundaryConditions
void setBoundaryConditions(int condition, double valueBegin=0.0, double valueEnd=0.0)
Define the condition at the endpoints of a spline.
Definition: qwt_spline.cpp:700
QwtSpline::setBoundaryValue
void setBoundaryValue(BoundaryPosition, double value)
Define the boundary value.
Definition: qwt_spline.cpp:670
QwtSpline::BoundaryType
BoundaryType
Definition: qwt_spline.h:66
QwtSpline::ClosedPolygon
@ ClosedPolygon
Definition: qwt_spline.h:92
QwtSpline::ConditionalBoundaries
@ ConditionalBoundaries
Definition: qwt_spline.h:72
QwtSpline::Clamped2
@ Clamped2
Definition: qwt_spline.h:134
QwtSpline::LinearRunout
@ LinearRunout
Definition: qwt_spline.h:153
QwtSpline::Clamped3
@ Clamped3
Definition: qwt_spline.h:143
QwtSpline::Clamped1
@ Clamped1
Definition: qwt_spline.h:125
QwtSpline::setParametrization
void setParametrization(int type)
Definition: qwt_spline.cpp:576
QwtSplineInterpolating::~QwtSplineInterpolating
virtual ~QwtSplineInterpolating()
Destructor.
Definition: qwt_spline.cpp:716
QwtSplineInterpolating::equidistantPolygon
virtual QPolygonF equidistantPolygon(const QPolygonF &, double distance, bool withNodes) const
Find an interpolated polygon with "equidistant" points.
Definition: qwt_spline.cpp:863
QwtSplineInterpolating::bezierControlLines
virtual QVector< QLineF > bezierControlLines(const QPolygonF &) const =0
Interpolate a curve with Bezier curves.
QwtSplineInterpolating::QwtSplineInterpolating
QwtSplineInterpolating()
Constructor.
Definition: qwt_spline.cpp:711
QwtSplineInterpolating::polygon
virtual QPolygonF polygon(const QPolygonF &, double tolerance) const override
Interpolate a curve by a polygon.
Definition: qwt_spline.cpp:805
QwtSplineInterpolating::painterPath
virtual QPainterPath painterPath(const QPolygonF &) const override
Interpolate a curve with Bezier curves.
Definition: qwt_spline.cpp:748
QwtSplineParametrization
Curve parametrization used for a spline interpolation.
Definition: qwt_spline_parametrization.h:45
QwtSplineParametrization::valueIncrementChordal
static double valueIncrementChordal(const QPointF &, const QPointF &)
Calculate the ParameterChordal value increment for 2 points.
Definition: qwt_spline_parametrization.h:179
QwtSplineParametrization::valueIncrementCentripetal
static double valueIncrementCentripetal(const QPointF &, const QPointF &)
Calculate the ParameterCentripetal value increment for 2 points.
Definition: qwt_spline_parametrization.h:196
QwtSplineParametrization::valueIncrementUniform
static double valueIncrementUniform(const QPointF &, const QPointF &)
Calculate the ParameterUniform value increment.
Definition: qwt_spline_parametrization.h:162
QwtSplineParametrization::valueIncrement
virtual double valueIncrement(const QPointF &, const QPointF &) const
Calculate the parameter value increment for 2 points.
Definition: qwt_spline_parametrization.cpp:35
QwtSplineParametrization::ParameterY
@ ParameterY
Definition: qwt_spline_parametrization.h:60
QwtSplineParametrization::ParameterCentripetal
@ ParameterCentripetal
Definition: qwt_spline_parametrization.h:94
QwtSplineParametrization::ParameterX
@ ParameterX
Definition: qwt_spline_parametrization.h:54
QwtSplineParametrization::ParameterUniform
@ ParameterUniform
Definition: qwt_spline_parametrization.h:72
QwtSplineParametrization::ParameterChordal
@ ParameterChordal
Definition: qwt_spline_parametrization.h:82
QwtSplineParametrization::valueIncrementManhattan
static double valueIncrementManhattan(const QPointF &, const QPointF &)
Calculate the ParameterManhattan value increment for 2 points.
Definition: qwt_spline_parametrization.h:210
QwtSplineParametrization::valueIncrementY
static double valueIncrementY(const QPointF &, const QPointF &)
Calculate the ParameterY value increment for 2 points.
Definition: qwt_spline_parametrization.h:148
QwtSplinePolynomial
A cubic polynomial without constant term.
Definition: qwt_spline_polynomial.h:31
QwtSplinePolynomial::slopeAt
double slopeAt(double x) const
Definition: qwt_spline_polynomial.h:119
QwtSplinePolynomial::fromSlopes
static QwtSplinePolynomial fromSlopes(const QPointF &p1, double m1, const QPointF &p2, double m2)
Definition: qwt_spline_polynomial.h:147
QwtSplinePolynomial::valueAt
double valueAt(double x) const
Definition: qwt_spline_polynomial.h:108
QwtSplinePolynomial::fromCurvatures
static QwtSplinePolynomial fromCurvatures(const QPointF &p1, double cv1, const QPointF &p2, double cv2)
Definition: qwt_spline_polynomial.h:185
QwtSplinePolynomial::c1
double c1
coefficient of the linear summand
Definition: qwt_spline_polynomial.h:64