qwt_spline_pleasing.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_pleasing.h"
12 
13 #include <qpainterpath.h>
14 
15 static inline double qwtChordalLength( const QPointF &point1, const QPointF &point2 )
16 {
17  const double dx = point2.x() - point1.x();
18  const double dy = point2.y() - point1.y();
19 
20  return std::sqrt( dx * dx + dy * dy );
21 }
22 
23 template< class Param >
24 static QPointF qwtVector( Param param,
25  const QPointF &p1, const QPointF &p2 )
26 {
27  return ( p2 - p1 ) / param( p1, p2 );
28 }
29 
30 template< class Param >
31 static QPointF qwtVectorCardinal( Param param,
32  const QPointF &p1, const QPointF &p2, const QPointF &p3 )
33 {
34  const double t1 = param( p1, p2 );
35  const double t2 = param( p2, p3 );
36 
37  return t2 * ( p3 - p1 ) / ( t1 + t2 );
38 }
39 
41 {
42  struct Tension
43  {
44  double t1;
45  double t2;
46  };
47 
48  struct param
49  {
51  parameter( p )
52  {
53  }
54 
55  inline double operator()( const QPointF &p1, const QPointF &p2 ) const
56  {
57  return parameter->valueIncrement( p1, p2 );
58  }
59 
61  };
62 
63  struct paramUniform
64  {
65  inline double operator()( const QPointF &p1, const QPointF &p2 ) const
66  {
68  }
69  };
70 
71  class PathStore
72  {
73  public:
74  inline void init( int )
75  {
76  }
77 
78  inline void start( const QPointF &p0 )
79  {
80  path.moveTo( p0 );
81  }
82 
83  inline void addCubic( const QPointF &cp1,
84  const QPointF &cp2, const QPointF &p2 )
85  {
86  path.cubicTo( cp1, cp2, p2 );
87  }
88 
89  QPainterPath path;
90  };
91 
93  {
94  public:
96  d_cp( NULL )
97  {
98  }
99 
100  inline void init( int size )
101  {
102  controlPoints.resize( size );
103  d_cp = controlPoints.data();
104  }
105 
106  inline void start( const QPointF & )
107  {
108  }
109 
110  inline void addCubic( const QPointF &cp1,
111  const QPointF &cp2, const QPointF & )
112  {
113  QLineF &l = *d_cp++;
114  l.setPoints( cp1, cp2 );
115  }
116 
118 
119  private:
120  QLineF* d_cp;
121  };
122 }
123 
125  double d13, double d23, double d24,
126  const QPointF &p1, const QPointF &p2,
127  const QPointF &p3, const QPointF &p4 )
128 {
130 
131  const bool b1 = ( d13 / 3.0 ) < d23;
132  const bool b2 = ( d24 / 3.0 ) < d23;
133 
134  if ( b1 )
135  {
136  if ( b2 )
137  {
138  tension.t1 = ( p1 != p2 ) ? ( 1.0 / 3.0 ) : ( 2.0 / 3.0 );
139  tension.t2 = ( p3 != p4 ) ? ( 1.0 / 3.0 ) : ( 2.0 / 3.0 );
140  }
141  else
142  {
143  tension.t1 = tension.t2 = d23 / d24;
144  }
145  }
146  else
147  {
148  if ( b2 )
149  {
150  tension.t1 = tension.t2 = d23 / d13;
151  }
152  else
153  {
154  tension.t1 = d23 / d13;
155  tension.t2 = d23 / d24;
156  }
157  }
158 
159  return tension;
160 }
161 
162 template< class SplineStore, class Param >
163 static SplineStore qwtSplinePathPleasing( const QPolygonF &points,
164  bool isClosed, Param param )
165 {
166  using namespace QwtSplinePleasingP;
167 
168  const int size = points.size();
169 
170  const QPointF *p = points.constData();
171 
172  SplineStore store;
173  store.init( isClosed ? size : size - 1 );
174  store.start( p[0] );
175 
176  double d13;
177  QPointF vec1;
178 
179  if ( isClosed )
180  {
181  d13 = qwtChordalLength(p[0], p[2]);
182 
183  const Tension t0 = qwtTensionPleasing(
184  qwtChordalLength( p[size-1], p[1]), qwtChordalLength(p[0], p[1]),
185  d13, p[size-1], p[0], p[1], p[2] );
186 
187  const QPointF vec0 = qwtVectorCardinal<Param>( param, p[size-1], p[0], p[1] );
188  vec1 = qwtVectorCardinal<Param>( param, p[0], p[1], p[2] );
189 
190  store.addCubic( p[0] + vec0 * t0.t1, p[1] - vec1 * t0.t2, p[1] );
191  }
192  else
193  {
194  d13 = qwtChordalLength(p[0], p[2]);
195 
196  const Tension t0 = qwtTensionPleasing(
197  qwtChordalLength( p[0], p[1]), qwtChordalLength(p[0], p[1]),
198  d13, p[0], p[0], p[1], p[2] );
199 
200  const QPointF vec0 = 0.5 * qwtVector<Param>( param, p[0], p[1] );
201  vec1 = qwtVectorCardinal<Param>( param, p[0], p[1], p[2] );
202 
203  store.addCubic( p[0] + vec0 * t0.t1, p[1] - vec1 * t0.t2, p[1] );
204  }
205 
206  for ( int i = 1; i < size - 2; i++ )
207  {
208  const double d23 = qwtChordalLength( p[i], p[i+1] );
209  const double d24 = qwtChordalLength( p[i], p[i+2] );
210 
211  const QPointF vec2 = qwtVectorCardinal<Param>( param, p[i], p[i+1], p[i+2] );
212 
213  const Tension t = qwtTensionPleasing(
214  d13, d23, d24, p[i-1], p[i], p[i+1], p[i+2] );
215 
216  store.addCubic( p[i] + vec1 * t.t1, p[i+1] - vec2 * t.t2, p[i+1] );
217 
218  d13 = d24;
219  vec1 = vec2;
220  }
221 
222  if ( isClosed )
223  {
224  const double d24 = qwtChordalLength( p[size-2], p[0] );
225 
226  const Tension tn = qwtTensionPleasing(
227  d13, qwtChordalLength( p[size-2], p[size-1] ), d24,
228  p[size-3], p[size-2], p[size-1], p[0] );
229 
230  const QPointF vec2 = qwtVectorCardinal<Param>( param, p[size-2], p[size-1], p[0] );
231  store.addCubic( p[size-2] + vec1 * tn.t1, p[size-1] - vec2 * tn.t2, p[size-1] );
232 
233  const double d34 = qwtChordalLength( p[size-1], p[0] );
234  const double d35 = qwtChordalLength( p[size-1], p[1] );
235 
236  const Tension tc = qwtTensionPleasing( d24, d34, d35, p[size-2], p[size-1], p[0], p[1] );
237 
238  const QPointF vec3 = qwtVectorCardinal<Param>( param, p[size-1], p[0], p[1] );
239 
240  store.addCubic( p[size-1] + vec2 * tc.t1, p[0] - vec3 * tc.t2, p[0] );
241  }
242  else
243  {
244  const double d24 = qwtChordalLength( p[size-2], p[size-1] );
245 
246  const Tension tn = qwtTensionPleasing(
247  d13, qwtChordalLength( p[size-2], p[size-1] ), d24,
248  p[size-3], p[size-2], p[size-1], p[size-1] );
249 
250  const QPointF vec2 = 0.5 * qwtVector<Param>( param, p[size-2], p[size-1] );
251  store.addCubic( p[size-2] + vec1 * tn.t1, p[size-1] - vec2 * tn.t2, p[size-1] );
252  }
253 
254  return store;
255 }
256 
266 {
267  setParametrization( QwtSplineParametrization::ParameterUniform );
268 }
269 
272 {
273 }
274 
277 {
278  return 2;
279 }
280 
290 QPainterPath QwtSplinePleasing::painterPath( const QPolygonF &points ) const
291 {
292  const int size = points.size();
293  if ( size <= 2 )
294  return QwtSplineG1::painterPath( points );
295 
296  const bool isClosing = ( boundaryType() == QwtSpline::ClosedPolygon );
297 
298  using namespace QwtSplinePleasingP;
299 
300  PathStore store;
301  if ( parametrization()->type() == QwtSplineParametrization::ParameterUniform )
302  {
303  store = qwtSplinePathPleasing<PathStore>( points,
304  isClosing, paramUniform() );
305  }
306  else
307  {
308  store = qwtSplinePathPleasing<PathStore>( points,
309  isClosing, param( parametrization() ) );
310  }
311 
312  if ( isClosing )
313  store.path.closeSubpath();
314 
315  return store.path;
316 }
317 
328  const QPolygonF &points ) const
329 {
330  const int size = points.size();
331  if ( size <= 2 )
332  return QVector<QLineF>();
333 
334  const bool isClosing = ( boundaryType() == QwtSpline::ClosedPolygon );
335 
336  using namespace QwtSplinePleasingP;
337 
338  ControlPointsStore store;
339  if ( parametrization()->type() == QwtSplineParametrization::ParameterUniform )
340  {
341  store = qwtSplinePathPleasing<ControlPointsStore>( points,
342  isClosing, paramUniform() );
343  }
344  else
345  {
346  store = qwtSplinePathPleasing<ControlPointsStore>( points,
347  isClosing, param( parametrization() ) );
348  }
349 
350  return store.controlPoints;
351 }
Curve parametrization used for a spline interpolation.
QwtSplinePleasing()
Constructor.
virtual QPainterPath painterPath(const QPolygonF &) const QWT_OVERRIDE
Interpolate a curve with Bezier curves.
Definition: qwt_spline.cpp:748
static QPointF qwtVectorCardinal(Param param, const QPointF &p1, const QPointF &p2, const QPointF &p3)
static SplineStore qwtSplinePathPleasing(const QPolygonF &points, bool isClosed, Param param)
virtual uint locality() const QWT_OVERRIDE
double operator()(const QPointF &p1, const QPointF &p2) const
const QwtSplineParametrization * parameter
virtual QVector< QLineF > bezierControlLines(const QPolygonF &) const QWT_OVERRIDE
Interpolate a curve with Bezier curves.
static QPointF qwtVector(Param param, const QPointF &p1, const QPointF &p2)
virtual QPainterPath painterPath(const QPolygonF &) const QWT_OVERRIDE
Interpolate a curve with Bezier curves.
void addCubic(const QPointF &cp1, const QPointF &cp2, const QPointF &)
static double valueIncrementUniform(const QPointF &, const QPointF &)
Calculate the ParameterUniform value increment.
void addCubic(const QPointF &cp1, const QPointF &cp2, const QPointF &p2)
static QwtSplinePleasingP::Tension qwtTensionPleasing(double d13, double d23, double d24, const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4)
virtual ~QwtSplinePleasing()
Destructor.
param(const QwtSplineParametrization *p)
double operator()(const QPointF &p1, const QPointF &p2) const
static double qwtChordalLength(const QPointF &point1, const QPointF &point2)


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