qwt_spline.cpp
Go to the documentation of this file.
1 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
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"
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  {
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 
32  };
33 
34  struct paramY
35  {
36  inline double operator()( const QPointF &p1, const QPointF &p2 ) const
37  {
39  }
40  };
41 
42  struct paramUniform
43  {
44  inline double operator()( const QPointF &p1, const QPointF &p2 ) const
45  {
47  }
48  };
49 
51  {
52  inline double operator()( const QPointF &p1, const QPointF &p2 ) const
53  {
55  }
56  };
57 
58  struct paramChordal
59  {
60  inline double operator()( const QPointF &p1, const QPointF &p2 ) const
61  {
63  }
64  };
65 
67  {
68  inline double operator()( const QPointF &p1, const QPointF &p2 ) const
69  {
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 
102  {
103  public:
105  d_cp( NULL )
106  {
107  }
108 
109  inline void init( int size )
110  {
111  controlPoints.resize( size );
112  d_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 = *d_cp++;
128  l.setLine( cx1, cy1, cx2, cy2 );
129  }
130 
131  inline void end()
132  {
133  }
134 
136 
137  private:
138  QLineF* d_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  }
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 
435 {
436 public:
438  boundaryType( QwtSpline::ConditionalBoundaries )
439  {
440  parametrization = new QwtSplineParametrization(
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 
453  {
454  delete parametrization;
455  }
456 
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 
541 {
542  d_data = new PrivateData;
543 }
544 
547 {
548  delete d_data;
549 }
550 
565 {
566  return 0;
567 }
568 
577 {
578  if ( d_data->parametrization->type() != type )
579  {
580  delete d_data->parametrization;
581  d_data->parametrization = new QwtSplineParametrization( type );
582  }
583 }
584 
593 {
594  if ( ( parametrization != NULL ) && ( d_data->parametrization != parametrization ) )
595  {
596  delete d_data->parametrization;
597  d_data->parametrization = parametrization;
598  }
599 }
600 
606 {
607  return d_data->parametrization;
608 }
609 
618 {
619  d_data->boundaryType = boundaryType;
620 }
621 
627 {
628  return d_data->boundaryType;
629 }
630 
639 void QwtSpline::setBoundaryCondition( BoundaryPosition position, int condition )
640 {
641  if ( ( position == QwtSpline::AtBeginning ) || ( position == QwtSpline::AtEnd ) )
642  d_data->boundaryConditions[position].type = condition;
643 }
644 
652 {
653  if ( ( position == QwtSpline::AtBeginning ) || ( position == QwtSpline::AtEnd ) )
654  return d_data->boundaryConditions[position].type;
655 
656  return d_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  d_data->boundaryConditions[position].value = value;
674 }
675 
683 {
684  if ( ( position == QwtSpline::AtBeginning ) || ( position == QwtSpline::AtEnd ) )
685  return d_data->boundaryConditions[position].value;
686 
687  return d_data->boundaryConditions[0].value; // should never happen
688 }
689 
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 
712 {
713 }
714 
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 
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 
945 {
946 }
947 
950 {
951 }
952 
963 {
964  setParametrization( QwtSplineParametrization::ParameterX );
965 }
966 
969 {
970 }
971 
979 double QwtSplineC1::slopeAtBeginning( const QPolygonF &points, double slopeNext ) const
980 {
981  if ( points.size() < 2 )
982  return 0.0;
983 
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  {
1055  {
1056  store = qwtSplineC1PathParamX<PathStore>( this, points );
1057  break;
1058  }
1060  {
1061  store = qwtSplineC1PathParamY<PathStore>( this, points );
1062  break;
1063  }
1065  {
1066  store = qwtSplineC1PathParametric<PathStore>(
1067  this, points, paramUniform() );
1068  break;
1069  }
1071  {
1072  store = qwtSplineC1PathParametric<PathStore>(
1073  this, points, paramCentripetal() );
1074  break;
1075  }
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  {
1113  {
1114  store = qwtSplineC1PathParamX<ControlPointsStore>( this, points );
1115  break;
1116  }
1118  {
1119  store = qwtSplineC1PathParamY<ControlPointsStore>( this, points );
1120  break;
1121  }
1123  {
1124  store = qwtSplineC1PathParametric<ControlPointsStore>(
1125  this, points, paramUniform() );
1126  break;
1127  }
1129  {
1130  store = qwtSplineC1PathParametric<ControlPointsStore>(
1131  this, points, paramCentripetal() );
1132  break;
1133  }
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 
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 
1229 {
1230 }
1231 
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 
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 }
Curve parametrization used for a spline interpolation.
static QPointF pointAt(const QPointF &p1, const QPointF &cp1, const QPointF &cp2, const QPointF &p2, double t)
Definition: qwt_bezier.cpp:239
virtual ~QwtSplineC1()
Destructor.
Definition: qwt_spline.cpp:968
double operator()(const QPointF &p1, const QPointF &p2) const
Definition: qwt_spline.cpp:36
enum MQTTPropertyCodes value
virtual uint locality() const
Definition: qwt_spline.cpp:564
static QPolygonF qwtPolygonParametric(double distance, const QPolygonF &points, const QVector< double > &values, bool withNodes)
Definition: qwt_spline.cpp:390
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
double c1
coefficient of the linear summand
static double valueIncrementCentripetal(const QPointF &, const QPointF &)
Calculate the ParameterCentripetal value increment for 2 points.
virtual QPainterPath painterPath(const QPolygonF &) const QWT_OVERRIDE
Interpolate a curve with Bezier curves.
Definition: qwt_spline.cpp:748
double slopeAt(double x) const
virtual QPolygonF equidistantPolygon(const QPolygonF &, double distance, bool withNodes) const
Find an interpolated polygon with "equidistant" points.
Definition: qwt_spline.cpp:863
QwtSplineParametrization * parametrization
Definition: qwt_spline.cpp:457
static double valueIncrementChordal(const QPointF &, const QPointF &)
Calculate the ParameterChordal value increment for 2 points.
virtual QVector< QwtSplinePolynomial > polynomials(const QPolygonF &) const QWT_OVERRIDE
Calculate the interpolating polynomials for a non parametric spline.
param(const QwtSplineParametrization *p)
Definition: qwt_spline.cpp:21
static SplineStore qwtSplineC1PathParamX(const QwtSplineC1 *spline, const QPolygonF &points)
Definition: qwt_spline.cpp:189
double valueAt(double x) const
virtual QVector< QLineF > bezierControlLines(const QPolygonF &) const QWT_OVERRIDE
Interpolate a curve with Bezier curves.
QwtSplineG1()
Constructor.
Definition: qwt_spline.cpp:944
virtual QVector< double > slopes(const QPolygonF &) const =0
Find the first derivative at the control points.
virtual ~QwtSplineG1()
Destructor.
Definition: qwt_spline.cpp:949
Base class for all splines.
Definition: qwt_spline.h:54
double operator()(const QPointF &p1, const QPointF &p2) const
Definition: qwt_spline.cpp:52
double slopeBoundary(int boundaryCondition, double boundaryValue, const QPointF &p1, const QPointF &p2, double slope1)
Definition: qwt_spline.cpp:141
virtual QPolygonF equidistantPolygon(const QPolygonF &, double distance, bool withNodes) const QWT_OVERRIDE
Find an interpolated polygon with "equidistant" points.
const QwtSplineParametrization * parametrization() const
Definition: qwt_spline.cpp:605
the condiation is at the end of the polynomial
Definition: qwt_spline.h:102
static SplineStore qwtSplineC1PathParametric(const QwtSplineC1 *spline, const QPolygonF &points, Param param)
Definition: qwt_spline.cpp:255
virtual QVector< QLineF > bezierControlLines(const QPolygonF &) const QWT_OVERRIDE
Interpolate a curve with Bezier curves.
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
void setBoundaryCondition(BoundaryPosition, int condition)
Define the condition for an endpoint of the spline.
Definition: qwt_spline.cpp:639
virtual ~QwtSplineC2()
Destructor.
double operator()(const QPointF &p1, const QPointF &p2) const
Definition: qwt_spline.cpp:68
virtual double valueIncrement(const QPointF &, const QPointF &) const
Calculate the parameter value increment for 2 points.
QwtSplineC2()
Constructor.
virtual QPainterPath painterPath(const QPolygonF &) const QWT_OVERRIDE
Calculate an interpolated painter path.
QwtSpline::BoundaryType boundaryType
Definition: qwt_spline.cpp:458
A cubic polynomial without constant term.
Base class for spline interpolations providing a first order parametric continuity ( C1 ) between adj...
Definition: qwt_spline.h:232
const QwtSplineParametrization * parameter
Definition: qwt_spline.cpp:31
the condiation is at the beginning of the polynomial
Definition: qwt_spline.h:99
An implementation of the de Casteljau’s Algorithm for interpolating Bézier curves.
Definition: qwt_bezier.h:29
virtual QPolygonF polygon(const QPolygonF &, double tolerance) const QWT_OVERRIDE
Interpolate a curve by a polygon.
Definition: qwt_spline.cpp:805
static double valueIncrementY(const QPointF &, const QPointF &)
Calculate the ParameterY value increment for 2 points.
void setBoundaryValue(BoundaryPosition, double value)
Define the boundary value.
Definition: qwt_spline.cpp:670
QwtSpline()
Constructor.
Definition: qwt_spline.cpp:540
virtual ~QwtSplineInterpolating()
Destructor.
Definition: qwt_spline.cpp:716
double operator()(const QPointF &p1, const QPointF &p2) const
Definition: qwt_spline.cpp:60
void addCubic(double cx1, double cy1, double cx2, double cy2, double x2, double y2)
Definition: qwt_spline.cpp:121
virtual ~QwtSpline()
Destructor.
Definition: qwt_spline.cpp:546
void addCubic(double cx1, double cy1, double cx2, double cy2, double x2, double y2)
Definition: qwt_spline.cpp:87
int boundaryCondition(BoundaryPosition) const
Definition: qwt_spline.cpp:651
double operator()(const QPointF &p1, const QPointF &p2) const
Definition: qwt_spline.cpp:26
static double valueIncrementUniform(const QPointF &, const QPointF &)
Calculate the ParameterUniform value increment.
virtual QPolygonF equidistantPolygon(const QPolygonF &, double distance, bool withNodes) const QWT_OVERRIDE
Find an interpolated polygon with "equidistant" points.
static QwtSplinePolynomial fromSlopes(const QPointF &p1, double m1, const QPointF &p2, double m2)
QwtSplineC1()
Constructor.
Definition: qwt_spline.cpp:962
double operator()(const QPointF &p1, const QPointF &p2) const
Definition: qwt_spline.cpp:44
QwtSplineInterpolating()
Constructor.
Definition: qwt_spline.cpp:711
void setParametrization(int type)
Definition: qwt_spline.cpp:576
virtual QPainterPath painterPath(const QPolygonF &) const QWT_OVERRIDE
Interpolate a curve with Bezier curves.
virtual QPolygonF polygon(const QPolygonF &, double tolerance) const
Interpolate a curve by a polygon.
Definition: qwt_spline.cpp:496
static SplineStore qwtSplineC1PathParamY(const QwtSplineC1 *spline, const QPolygonF &points)
Definition: qwt_spline.cpp:218
void start(double x1, double y1)
Definition: qwt_spline.cpp:82
virtual double slopeAtBeginning(const QPolygonF &, double slopeNext) const
Definition: qwt_spline.cpp:979
static QwtSplinePolynomial fromCurvatures(const QPointF &p1, double cv1, const QPointF &p2, double cv2)
virtual QVector< QwtSplinePolynomial > polynomials(const QPolygonF &) const
Calculate the interpolating polynomials for a non parametric spline.
virtual double slopeAtEnd(const QPolygonF &, double slopeBefore) const
Definition: qwt_spline.cpp:997
BoundaryType boundaryType() const
Definition: qwt_spline.cpp:626
virtual QVector< double > slopes(const QPolygonF &) const QWT_OVERRIDE
Find the first derivative at the control points.
double boundaryValue(BoundaryPosition) const
Definition: qwt_spline.cpp:682
void init(int size)
Definition: qwt_spline.cpp:77
BoundaryPosition
Definition: qwt_spline.h:96
void start(double x1, double y1)
Definition: qwt_spline.cpp:115
void setBoundaryType(BoundaryType)
Definition: qwt_spline.cpp:617
static double valueIncrementManhattan(const QPointF &, const QPointF &)
Calculate the ParameterManhattan value increment for 2 points.


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:48:10