qwt_bezier.cpp
Go to the documentation of this file.
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_bezier.h"
11 #include "qwt_math.h"
12 
13 #include <qpolygon.h>
14 #include <qstack.h>
15 
16 namespace
17 {
18  class BezierData
19  {
20  public:
21  inline BezierData()
22  {
23  // default constructor with uninitialized points
24  }
25 
26  inline BezierData( const QPointF& p1, const QPointF& cp1,
27  const QPointF& cp2, const QPointF& p2 ):
28  m_x1( p1.x() ),
29  m_y1( p1.y() ),
30  m_cx1( cp1.x() ),
31  m_cy1( cp1.y() ),
32  m_cx2( cp2.x() ),
33  m_cy2( cp2.y() ),
34  m_x2( p2.x() ),
35  m_y2( p2.y() )
36  {
37  }
38 
39  static inline double minFlatness( double tolerance )
40  {
41  // we can simplify the tolerance criterion check in
42  // the subdivision loop, by precalculating some
43  // flatness value.
44 
45  return 16 * ( tolerance * tolerance );
46  }
47 
48  inline double flatness() const
49  {
50  // algo by Roger Willcocks ( http://www.rops.org )
51 
52  const double ux = 3.0 * m_cx1 - 2.0 * m_x1 - m_x2;
53  const double uy = 3.0 * m_cy1 - 2.0 * m_y1 - m_y2;
54  const double vx = 3.0 * m_cx2 - 2.0 * m_x2 - m_x1;
55  const double vy = 3.0 * m_cy2 - 2.0 * m_y2 - m_y1;
56 
57  const double ux2 = ux * ux;
58  const double uy2 = uy * uy;
59 
60  const double vx2 = vx * vx;
61  const double vy2 = vy * vy;
62 
63  return qwtMaxF( ux2, vx2 ) + qwtMaxF( uy2, vy2 );
64  }
65 
66  inline BezierData subdivided()
67  {
68  BezierData bz;
69 
70  const double c1 = midValue( m_cx1, m_cx2 );
71 
72  bz.m_cx1 = midValue( m_x1, m_cx1 );
73  m_cx2 = midValue( m_cx2, m_x2 );
74  bz.m_x1 = m_x1;
75  bz.m_cx2 = midValue( bz.m_cx1, c1 );
76  m_cx1 = midValue( c1, m_cx2 );
77  bz.m_x2 = m_x1 = midValue( bz.m_cx2, m_cx1 );
78 
79  const double c2 = midValue( m_cy1, m_cy2 );
80 
81  bz.m_cy1 = midValue( m_y1, m_cy1 );
82  m_cy2 = midValue( m_cy2, m_y2 );
83  bz.m_y1 = m_y1;
84  bz.m_cy2 = midValue( bz.m_cy1, c2 );
85  m_cy1 = midValue( m_cy2, c2 );
86  bz.m_y2 = m_y1 = midValue( bz.m_cy2, m_cy1 );
87 
88  return bz;
89  }
90 
91  inline QPointF p2() const
92  {
93  return QPointF( m_x2, m_y2 );
94  }
95 
96  private:
97  inline double midValue( double v1, double v2 )
98  {
99  return 0.5 * ( v1 + v2 );
100  }
101 
102  double m_x1, m_y1;
103  double m_cx1, m_cy1;
104  double m_cx2, m_cy2;
105  double m_x2, m_y2;
106  };
107 }
108 
116 QwtBezier::QwtBezier( double tolerance )
117  : m_tolerance( qwtMaxF( tolerance, 0.0 ) )
118  , m_flatness( BezierData::minFlatness( m_tolerance ) )
119 {
120 }
121 
124 {
125 }
126 
141 void QwtBezier::setTolerance( double tolerance )
142 {
143  m_tolerance = qwtMaxF( tolerance, 0.0 );
144  m_flatness = BezierData::minFlatness( m_tolerance );
145 }
146 
157 QPolygonF QwtBezier::toPolygon( const QPointF& p1,
158  const QPointF& cp1, const QPointF& cp2, const QPointF& p2 ) const
159 {
160  QPolygonF polygon;
161 
162  if ( m_flatness > 0.0 )
163  {
164  // a flatness of 0.0 is not achievable
165  appendToPolygon( p1, cp1, cp2, p2, polygon );
166  }
167 
168  return polygon;
169 }
170 
186 void QwtBezier::appendToPolygon( const QPointF& p1, const QPointF& cp1,
187  const QPointF& cp2, const QPointF& p2, QPolygonF& polygon ) const
188 {
189  if ( m_flatness <= 0.0 )
190  {
191  // a flatness of 0.0 is not achievable
192  return;
193  }
194 
195  if ( polygon.isEmpty() || polygon.last() != p1 )
196  polygon += p1;
197 
198  // to avoid deep stacks we convert the recursive algo
199  // to something iterative, where the parameters of the
200  // recursive class are pushed to a stack instead
201 
202  QStack< BezierData > stack;
203  stack.push( BezierData( p1, cp1, cp2, p2 ) );
204 
205  while( true )
206  {
207  BezierData& bz = stack.top();
208 
209  if ( bz.flatness() < m_flatness )
210  {
211  if ( stack.size() == 1 )
212  {
213  polygon += p2;
214  return;
215  }
216 
217  polygon += bz.p2();
218  stack.pop();
219  }
220  else
221  {
222  stack.push( bz.subdivided() );
223  }
224  }
225 
226 }
227 
239 QPointF QwtBezier::pointAt( const QPointF& p1,
240  const QPointF& cp1, const QPointF& cp2, const QPointF& p2, double t )
241 {
242  const double d1 = 3.0 * t;
243  const double d2 = 3.0 * t * t;
244  const double d3 = t * t * t;
245  const double s = 1.0 - t;
246 
247  const double x = ( ( s * p1.x() + d1 * cp1.x() ) * s + d2 * cp2.x() ) * s + d3 * p2.x();
248  const double y = ( ( s * p1.y() + d1 * cp1.y() ) * s + d2 * cp2.y() ) * s + d3 * p2.y();
249 
250  return QPointF( x, y );
251 }
252 
qwt_bezier.h
QwtBezier::tolerance
double tolerance() const
Definition: qwt_bezier.h:56
QwtBezier::toPolygon
QPolygonF toPolygon(const QPointF &p1, const QPointF &cp1, const QPointF &cp2, const QPointF &p2) const
Interpolate a Bézier curve by a polygon.
Definition: qwt_bezier.cpp:157
s
XmlRpcServer s
mqtt_test_proto.x
x
Definition: mqtt_test_proto.py:34
qwt_math.h
mqtt_test_proto.y
y
Definition: mqtt_test_proto.py:35
QStack
Definition: qwt_plot_zoomer.h:17
QwtBezier::setTolerance
void setTolerance(double tolerance)
Definition: qwt_bezier.cpp:141
qwtMaxF
QWT_CONSTEXPR float qwtMaxF(float a, float b)
Definition: qwt_math.h:127
QwtBezier::m_flatness
double m_flatness
Definition: qwt_bezier.h:49
QwtBezier::m_tolerance
double m_tolerance
Definition: qwt_bezier.h:48
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
QwtBezier::QwtBezier
QwtBezier(double tolerance=0.5)
Constructor.
Definition: qwt_bezier.cpp:116
QwtBezier::~QwtBezier
~QwtBezier()
Destructor.
Definition: qwt_bezier.cpp:123


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Aug 11 2024 02:24:24