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 DocumentModelGeneral &modelGeneral,
139  const MainWindowModel &modelMainWindow,
140  const Transformation &transformation,
141  QVector<QString> &x,
142  QVector<QString> &y) const
143 {
144  FormatCoordsUnits formatCoordsUnits;
145 
146  for (int i = 0; i < positionsGraph.size(); i++) {
147 
148  double xI = positionsGraph [i].x();
149  double yI = positionsGraph [i].y();
150 
151  QString xFormatted, yFormatted;
152  formatCoordsUnits.unformattedToFormatted (xI,
153  yI,
154  modelCoords,
155  modelGeneral,
156  modelMainWindow,
157  xFormatted,
158  yFormatted,
159  transformation);
160  x.push_back (xFormatted);
161  y.push_back (yFormatted);
162 
163  }
164 }
165 
166 double GeometryStrategyAbstractBase::polygonAreaForSimplyConnected (const QVector<QPointF> &points) const
167 {
168  // Shoelace formula
169  int N = points.size ();
170 
171  double sum = 0.0;
172  if (N > 0) {
173 
174 
175  for (int i = 0; i < N - 1; i++) {
176  sum += points [i].x() * points [i + 1].y() - points [i + 1].x() * points [i].y();
177  }
178 
179  sum += points [N - 1].x() * points [0].y() - points [0].x() * points [N - 1].y ();
180  }
181 
182  return qAbs (sum) / 2.0;
183 }
Model for DlgSettingsGeneral and CmdSettingsGeneral.
double functionArea(const QVector< QPointF > &positionsGraph) const
Use trapezoidal approximation to compute area under the function. Does not apply to relation...
void calculatePositionsGraph(const Points &points, const Transformation &transformation, QVector< QPointF > &positionsGraph) const
Convert screen positions to graph positions.
Cubic interpolation given independent and dependent value vectors.
Definition: Spline.h:21
SplinePair interpolateCoeff(double t) const
Return interpolated y for specified x.
Definition: Spline.cpp:166
double y() const
Get method for y.
Definition: SplinePair.cpp:71
void loadXY(const QVector< QPointF > &positionsGraph, const DocumentModelCoords &modelCoords, const DocumentModelGeneral &modelGeneral, const MainWindowModel &modelMainWindow, const Transformation &transformation, QVector< QString > &x, QVector< QString > &y) const
Load x and y coordinate vectors.
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 DocumentModelGeneral &modelGeneral, 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.
double polygonAreaForSimplyConnected(const QVector< QPointF > &points) const
Area in polygon using Shoelace formula, which only works if polygon is simply connected.
Highest-level wrapper around other Formats classes.
GeometryStrategyAbstractBase()
Single constructor.
void transformScreenToRawGraph(const QPointF &coordScreen, QPointF &coordGraph) const
Transform from cartesian pixel screen coordinates to cartesian/polar graph coordinates.
double x() const
Get method for x.
Definition: SplinePair.cpp:66
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.
Single X/Y pair for cubic spline interpolation initialization and calculations.
Definition: SplinePair.h:11