Engauge Digitizer  2
ExportOrdinalsSmooth.cpp
1 #include "ExportOrdinalsSmooth.h"
2 #include "Logger.h"
3 #include <qdebug.h>
4 #include <qmath.h>
5 #include <QPointF>
6 #include "Spline.h"
7 #include "Transformation.h"
8 
9 using namespace std;
10 
12 {
13 }
14 
16  vector<double> &t,
17  vector<SplinePair> &xy) const
18 {
19  LOG4CPP_INFO_S ((*mainCat)) << "ExportOrdinalsSmooth::loadSplinePairsWithoutTransformation";
20 
21  Points::const_iterator itrP;
22  for (itrP = points.begin(); itrP != points.end(); itrP++) {
23  const Point &point = *itrP;
24  QPointF posScreen = point.posScreen();
25 
26  t.push_back (point.ordinal ());
27  xy.push_back (SplinePair (posScreen.x(),
28  posScreen.y()));
29  }
30 }
31 
33  const Transformation &transformation,
34  vector<double> &t,
35  vector<SplinePair> &xy) const
36 {
37  LOG4CPP_INFO_S ((*mainCat)) << "ExportOrdinalsSmooth::loadSplinePairsWithTransformation";
38 
39  Points::const_iterator itrP;
40  for (itrP = points.begin(); itrP != points.end(); itrP++) {
41  const Point &point = *itrP;
42  QPointF posScreen = point.posScreen();
43  QPointF posGraph;
44  transformation.transformScreenToRawGraph (posScreen,
45  posGraph);
46 
47  t.push_back (point.ordinal ());
48  xy.push_back (SplinePair (posGraph.x(),
49  posGraph.y()));
50  }
51 }
52 
53 ExportValuesOrdinal ExportOrdinalsSmooth::ordinalsAtIntervalsGraph (const vector<double> &t,
54  const vector<SplinePair> &xy,
55  double pointsInterval) const
56 {
57  LOG4CPP_INFO_S ((*mainCat)) << "ExportOrdinalsSmooth::ordinalsAtIntervalsGraph";
58 
59  const double NUM_SMALLER_INTERVALS = 1000;
60 
61  // Results. Initially empty, but at the end it will have tMin, ..., tMax
62  ExportValuesOrdinal ordinals;
63 
64  // Fit a spline
65  Spline spline (t,
66  xy);
67 
68  // Integrate the distances for the subintervals
69  double integratedSeparation = 0;
70  QPointF posLast (xy [0].x(),
71  xy [0].y());
72 
73  // Simplest method to find the intervals is to break up the curve into many smaller intervals, and then aggregate them
74  // into intervals that, as much as possible, have the desired length. Simplicity wins out over accuracy in this
75  // approach - accuracy is sacrificed to achieve simplicity
76  double tMin = t.front();
77  double tMax = t.back();
78 
79  double tLast = 0.0;
80  int iTLastInterval = 0;
81  for (int iT = 0; iT < NUM_SMALLER_INTERVALS; iT++) {
82 
83  double t = tMin + ((tMax - tMin) * iT) / (NUM_SMALLER_INTERVALS - 1.0);
84 
85  SplinePair pairNew = spline.interpolateCoeff(t);
86 
87  QPointF posNew = QPointF (pairNew.x(),
88  pairNew.y());
89 
90  QPointF posDelta = posNew - posLast;
91  double integratedSeparationDelta = qSqrt (posDelta.x() * posDelta.x() + posDelta.y() * posDelta.y());
92  integratedSeparation += integratedSeparationDelta;
93 
94  while (integratedSeparation >= pointsInterval) {
95 
96  // End of current interval, and start of next interval. For better accuracy without having to crank up
97  // the number of points by orders of magnitude, we use linear interpolation
98  double sInterp;
99  if (iT == 0) {
100  sInterp = 0.0;
101  } else {
102  sInterp = (double) pointsInterval / (double) integratedSeparation;
103  }
104  double tInterp = (1.0 - sInterp) * tLast + sInterp * t;
105 
106  integratedSeparation -= pointsInterval; // Part of delta that was not used gets applied to next interval
107 
108  tLast = tInterp;
109  ordinals.push_back (tInterp);
110  iTLastInterval = iT;
111  }
112 
113  tLast = t;
114  posLast = posNew;
115  }
116 
117  if (iTLastInterval < NUM_SMALLER_INTERVALS - 1) {
118 
119  // Add last point so we end up at tMax
120  ordinals.push_back (tMax);
121 
122  }
123 
124  return ordinals;
125 }
void transformScreenToRawGraph(const QPointF &coordScreen, QPointF &coordGraph) const
Transform from cartesian pixel screen coordinates to cartesian/polar graph coordinates.
SplinePair interpolateCoeff(double t) const
Return interpolated y for specified x.
Definition: Spline.cpp:127
Cubic interpolation given independent and dependent value vectors.
Definition: Spline.h:15
double y() const
Get method for y.
Definition: SplinePair.cpp:65
Class that represents one digitized point. The screen-to-graph coordinate transformation is always ex...
Definition: Point.h:17
QPointF posScreen() const
Accessor for screen position.
Definition: Point.cpp:344
Affine transformation between screen and graph coordinates, based on digitized axis points...
void loadSplinePairsWithTransformation(const Points &points, const Transformation &transformation, std::vector< double > &t, std::vector< SplinePair > &xy) const
Load t (=ordinal) and xy (=screen position) spline pairs, converting screen coordinates to graph coor...
void loadSplinePairsWithoutTransformation(const Points &points, std::vector< double > &t, std::vector< SplinePair > &xy) const
Load t (=ordinal) and xy (=screen position) spline pairs, without any conversion to graph coordinates...
ExportValuesOrdinal ordinalsAtIntervalsGraph(const std::vector< double > &t, const std::vector< SplinePair > &xy, double pointsInterval) const
Perform the interpolation on the arrays loaded by the other methods.
double x() const
Get method for x.
Definition: SplinePair.cpp:60
double ordinal(ApplyHasCheck applyHasCheck=KEEP_HAS_CHECK) const
Get method for ordinal. Skip check if copying one instance to another.
Definition: Point.cpp:326
ExportOrdinalsSmooth()
Single constructor.
Single X/Y pair for cubic spline interpolation initialization and calculations.
Definition: SplinePair.h:5