qwt_weeding_curve_fitter.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 
11 #include "qwt_math.h"
12 #include <qstack.h>
13 #include <qvector.h>
14 
15 #if QT_VERSION < 0x040601
16 #define qFabs(x) ::fabs(x)
17 #endif
18 
20 {
21 public:
23  tolerance( 1.0 ),
24  chunkSize( 0 )
25  {
26  }
27 
28  double tolerance;
29  uint chunkSize;
30 };
31 
33 {
34 public:
35  Line( int i1 = 0, int i2 = 0 ):
36  from( i1 ),
37  to( i2 )
38  {
39  }
40 
41  int from;
42  int to;
43 };
44 
53 {
54  d_data = new PrivateData;
55  setTolerance( tolerance );
56 }
57 
60 {
61  delete d_data;
62 }
63 
78 {
79  d_data->tolerance = qMax( tolerance, 0.0 );
80 }
81 
87 {
88  return d_data->tolerance;
89 }
90 
103 {
104  if ( numPoints > 0 )
105  numPoints = qMax( numPoints, 3U );
106 
107  d_data->chunkSize = numPoints;
108 }
109 
117 {
118  return d_data->chunkSize;
119 }
120 
126 QPolygonF QwtWeedingCurveFitter::fitCurve( const QPolygonF &points ) const
127 {
128  QPolygonF fittedPoints;
129 
130  if ( d_data->chunkSize == 0 )
131  {
132  fittedPoints = simplify( points );
133  }
134  else
135  {
136  for ( int i = 0; i < points.size(); i += d_data->chunkSize )
137  {
138  const QPolygonF p = points.mid( i, d_data->chunkSize );
139  fittedPoints += simplify( p );
140  }
141  }
142 
143  return fittedPoints;
144 }
145 
151 QPainterPath QwtWeedingCurveFitter::fitCurvePath( const QPolygonF &points ) const
152 {
153  QPainterPath path;
154  path.addPolygon( fitCurve( points ) );
155  return path;
156 }
157 
158 QPolygonF QwtWeedingCurveFitter::simplify( const QPolygonF &points ) const
159 {
160  const double toleranceSqr = d_data->tolerance * d_data->tolerance;
161 
163  stack.reserve( 500 );
164 
165  const QPointF *p = points.data();
166  const int nPoints = points.size();
167 
168  QVector<bool> usePoint( nPoints, false );
169 
170  stack.push( Line( 0, nPoints - 1 ) );
171 
172  while ( !stack.isEmpty() )
173  {
174  const Line r = stack.pop();
175 
176  // initialize line segment
177  const double vecX = p[r.to].x() - p[r.from].x();
178  const double vecY = p[r.to].y() - p[r.from].y();
179 
180  const double vecLength = qSqrt( vecX * vecX + vecY * vecY );
181 
182  const double unitVecX = ( vecLength != 0.0 ) ? vecX / vecLength : 0.0;
183  const double unitVecY = ( vecLength != 0.0 ) ? vecY / vecLength : 0.0;
184 
185  double maxDistSqr = 0.0;
186  int nVertexIndexMaxDistance = r.from + 1;
187  for ( int i = r.from + 1; i < r.to; i++ )
188  {
189  //compare to anchor
190  const double fromVecX = p[i].x() - p[r.from].x();
191  const double fromVecY = p[i].y() - p[r.from].y();
192 
193  double distToSegmentSqr;
194  if ( fromVecX * unitVecX + fromVecY * unitVecY < 0.0 )
195  {
196  distToSegmentSqr = fromVecX * fromVecX + fromVecY * fromVecY;
197  }
198  else
199  {
200  const double toVecX = p[i].x() - p[r.to].x();
201  const double toVecY = p[i].y() - p[r.to].y();
202  const double toVecLength = toVecX * toVecX + toVecY * toVecY;
203 
204  const double s = toVecX * ( -unitVecX ) + toVecY * ( -unitVecY );
205  if ( s < 0.0 )
206  {
207  distToSegmentSqr = toVecLength;
208  }
209  else
210  {
211  distToSegmentSqr = qFabs( toVecLength - s * s );
212  }
213  }
214 
215  if ( maxDistSqr < distToSegmentSqr )
216  {
217  maxDistSqr = distToSegmentSqr;
218  nVertexIndexMaxDistance = i;
219  }
220  }
221  if ( maxDistSqr <= toleranceSqr )
222  {
223  usePoint[r.from] = true;
224  usePoint[r.to] = true;
225  }
226  else
227  {
228  stack.push( Line( r.from, nVertexIndexMaxDistance ) );
229  stack.push( Line( nVertexIndexMaxDistance, r.to ) );
230  }
231  }
232 
233  QPolygonF stripped;
234  for ( int i = 0; i < nPoints; i++ )
235  {
236  if ( usePoint[i] )
237  stripped += p[i];
238  }
239 
240  return stripped;
241 }
virtual QPainterPath fitCurvePath(const QPolygonF &) const
XmlRpcServer s
#define qFabs(x)
virtual ~QwtWeedingCurveFitter()
Destructor.
GraphId path[kMaxDeadlockPathLen]
size_t to
virtual QPolygonF fitCurve(const QPolygonF &) const
void * stack[40]
virtual QPolygonF simplify(const QPolygonF &) const
int i
size_t from
QwtWeedingCurveFitter(double tolerance=1.0)
Abstract base class for a curve fitter.


plotjuggler
Author(s): Davide Faconti
autogenerated on Sat Jul 6 2019 03:44:18