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