Engauge Digitizer  2
GeometryStrategyAbstractBase.cpp
1 /******************************************************************************************************
2  * (C) 2016 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
3  * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
4  * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
5  ******************************************************************************************************/
6 
7 #include "EngaugeAssert.h"
8 #include "FormatCoordsUnits.h"
9 #include "GeometryStrategyAbstractBase.h"
10 #include <qmath.h>
11 #include <QPointF>
12 #include "Spline.h"
13 #include "SplinePair.h"
14 #include "Transformation.h"
15 #include <vector>
16 
17 using namespace std;
18 
20 {
21 }
22 
23 GeometryStrategyAbstractBase::~GeometryStrategyAbstractBase()
24 {
25 }
26 
28  const Transformation &transformation,
29  QVector<QPointF> &positionsGraph) const
30 {
31  positionsGraph.clear();
32 
33  for (int i = 0; i < points.size(); i++) {
34  const Point &pointScreen = points [i];
35  QPointF posScreen = pointScreen.posScreen ();
36  QPointF posGraph;
37 
38  transformation.transformScreenToRawGraph (posScreen,
39  posGraph);
40 
41  positionsGraph.push_back (posGraph);
42  }
43 }
44 
45 double GeometryStrategyAbstractBase::functionArea (const QVector<QPointF> &positionsGraph) const
46 {
47  // Integrate using trapezoidal approximation to get the area under the function
48  double sum = 0, xLast = 0, yLast = 0;
49  for (int i = 1; i < positionsGraph.size (); i++) {
50  double x = positionsGraph [i].x();
51  double y = positionsGraph [i].y();
52  double area = 0.5 * (y + yLast) * (x - xLast);
53  sum += area;
54  xLast = x;
55  yLast = y;
56  }
57 
58  return sum;
59 }
60 
62  const QVector<QPointF> &positionsGraph,
63  QVector<QPointF> &positionsGraphWithSubintervals,
64  QVector<QString> &distanceGraphForward,
65  QVector<QString> &distancePercentForward,
66  QVector<QString> &distanceGraphBackward,
67  QVector<QString> &distancePercentBackward) const
68 {
69  if (positionsGraph.size () > 0) {
70 
71  int i;
72 
73  // Fit splines to the points
74  vector<double> t;
75  vector<SplinePair> xy;
76  for (int i = 0; i < positionsGraph.size (); i++) {
77  t.push_back ((double) i);
78  xy.push_back (SplinePair (positionsGraph [i].x(),
79  positionsGraph [i].y()));
80  }
81 
82  Spline spline (t,
83  xy);
84 
85  // Loop over the original points, with one original point per original interval
86  QVector<double> distanceGraphDouble;
87  double xLast = 0, yLast = 0, distance = 0;
88  for (i = 0; i < positionsGraph.size(); i++) {
89 
90  // In the interval i-1 to i we insert points to create smaller subintervals
91  for (int subinterval = 0; subinterval < subintervalsPerInterval; subinterval++) {
92 
93  // Go from i-1 (exclusive) to i (inclusive)
94  double t = (double) (i - 1.0) + (double) (subinterval + 1) / (double) (subintervalsPerInterval);
95 
96  SplinePair splinePair = spline.interpolateCoeff (t);
97 
98  double x = splinePair.x ();
99  double y = splinePair.y ();
100 
101  // All points from intervals where i>0, and last point from interval i=0
102  if (i > 0 || subinterval == subintervalsPerInterval - 1) {
103 
104  // Insert one of several new points for each original point
105  positionsGraphWithSubintervals.push_back (QPointF (x, y));
106 
107  }
108 
109  if (i > 0) {
110 
111  // Add to cumulative distance
112  distance += qSqrt ((x - xLast) * (x - xLast) + (y - yLast) * (y - yLast));
113 
114  }
115 
116  xLast = x;
117  yLast = y;
118  }
119 
120  // Insert one distance entry for each original point
121  distanceGraphDouble.push_back (distance);
122  }
123 
124  // Compute distance columns
125  double dTotal = qMax (1.0, distanceGraphDouble [distanceGraphDouble.size() - 1]); // qMax prevents divide by zero
126  for (i = 0; i < distanceGraphDouble.size (); i++) {
127  double d = distanceGraphDouble [i];
128  distanceGraphForward.push_back (QString::number (d));
129  distancePercentForward.push_back (QString::number (100.0 * d / dTotal));
130  distanceGraphBackward.push_back (QString::number (dTotal - d));
131  distancePercentBackward.push_back (QString::number (100.0 * (dTotal - d) / dTotal));
132  }
133  }
134 }
135 
136 void GeometryStrategyAbstractBase::loadXY (const QVector<QPointF> &positionsGraph,
137  const DocumentModelCoords &modelCoords,
138  const MainWindowModel &modelMainWindow,
139  const Transformation &transformation,
140  QVector<QString> &x,
141  QVector<QString> &y) const
142 {
143  FormatCoordsUnits formatCoordsUnits;
144 
145  for (int i = 0; i < positionsGraph.size(); i++) {
146 
147  double xI = positionsGraph [i].x();
148  double yI = positionsGraph [i].y();
149 
150  QString xFormatted, yFormatted;
151  formatCoordsUnits.unformattedToFormatted (xI,
152  yI,
153  modelCoords,
154  modelMainWindow,
155  xFormatted,
156  yFormatted,
157  transformation);
158  x.push_back (xFormatted);
159  y.push_back (yFormatted);
160 
161  }
162 }
163 
164 double GeometryStrategyAbstractBase::polygonAreaForSimplyConnected (const QVector<QPointF> &points) const
165 {
166  // Shoelace formula
167  int N = points.size ();
168 
169  double sum = 0.0;
170  if (N > 0) {
171 
172 
173  for (int i = 0; i < N - 1; i++) {
174  sum += points [i].x() * points [i + 1].y() - points [i + 1].x() * points [i].y();
175  }
176 
177  sum += points [N - 1].x() * points [0].y() - points [0].x() * points [N - 1].y ();
178  }
179 
180  return qAbs (sum) / 2.0;
181 }
void transformScreenToRawGraph(const QPointF &coordScreen, QPointF &coordGraph) const
Transform from cartesian pixel screen coordinates to cartesian/polar graph coordinates.
void calculatePositionsGraph(const Points &points, const Transformation &transformation, QVector< QPointF > &positionsGraph) const
Convert screen positions to graph positions.
SplinePair interpolateCoeff(double t) const
Return interpolated y for specified x.
Definition: Spline.cpp:166
Cubic interpolation given independent and dependent value vectors.
Definition: Spline.h:21
double functionArea(const QVector< QPointF > &positionsGraph) const
Use trapezoidal approximation to compute area under the function. Does not apply to relation...
double y() const
Get method for y.
Definition: SplinePair.cpp:71
Class that represents one digitized point. The screen-to-graph coordinate transformation is always ex...
Definition: Point.h:23
QPointF posScreen() const
Accessor for screen position.
Definition: Point.cpp:392
void unformattedToFormatted(double xThetaUnformatted, double yRadiusUnformatted, const DocumentModelCoords &modelCoords, const MainWindowModel &mainWindowModel, QString &xThetaFormatted, QString &yRadiusFormatted, const Transformation &transformation) const
Convert unformatted numeric value to formatted string. Transformation is used to determine best resol...
Affine transformation between screen and graph coordinates, based on digitized axis points...
Model for DlgSettingsMainWindow.
Model for DlgSettingsCoords and CmdSettingsCoords.
Highest-level wrapper around other Formats classes.
double x() const
Get method for x.
Definition: SplinePair.cpp:66
GeometryStrategyAbstractBase()
Single constructor.
void insertSubintervalsAndLoadDistances(int subintervalsPerInterval, const QVector< QPointF > &positionsGraph, QVector< QPointF > &positionsGraphWithSubintervals, QVector< QString > &distanceGraphForward, QVector< QString > &distancePercentForward, QVector< QString > &distanceGraphBackward, QVector< QString > &distancePercentBackward) const
Insert the specified number of subintervals into each interval.
double polygonAreaForSimplyConnected(const QVector< QPointF > &points) const
Area in polygon using Shoelace formula, which only works if polygon is simply connected.
void loadXY(const QVector< QPointF > &positionsGraph, const DocumentModelCoords &modelCoords, const MainWindowModel &modelMainWindow, const Transformation &transformation, QVector< QString > &x, QVector< QString > &y) const
Load x and y coordinate vectors.
Single X/Y pair for cubic spline interpolation initialization and calculations.
Definition: SplinePair.h:11