Engauge Digitizer  2
FittingCurve.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 "FittingCurveCoefficients.h"
8 #include "FittingCurve.h"
9 #include "Logger.h"
10 #include <qmath.h>
11 #include <QPainterPath>
12 #include <QPen>
13 #include "Transformation.h"
14 
15 FittingCurve::FittingCurve (const FittingCurveCoefficients &fittingCoef,
16  double xMin,
17  double xMax,
18  bool isLogXTheta,
19  bool isLogYRadius,
20  const Transformation &transformation)
21 {
22  const int NUM_POINTS = 1000; // Use so many points that spline interpolation is not needed for smoothness
23  const double Z_LINE = 500; // More than the z value for lines since this line takes priority, and user can hide it
24 
25  setZValue (Z_LINE);
26  setPen (QPen (QColor (Qt::red)));
27 
28  QPainterPath path;
29 
30  if (transformation.transformIsDefined()) {
31 
32  for (int i = 0; i < NUM_POINTS; i++) {
33 
34  // Compute (x,y) point in graph coordinates
35  double s = (double) i / (double) (NUM_POINTS - 1);
36  double x = xMin + s * (xMax - xMin);
37  double y = yFromCoefficientsAndX (fittingCoef,
38  x);
39 
40  // The coefficients were computed assuming the x and y values were transformed if they were log scale base 10, so
41  // we must compensate here in the same way
42  if (isLogXTheta) {
43  x = qPow (10.0, x);
44  }
45  if (isLogYRadius) {
46  y = qPow (10.0, y);
47  }
48 
49  // Convert to screen coordinates
50  QPointF posGraph (x, y);
51  QPointF posScreen;
52  transformation.transformRawGraphToScreen (posGraph,
53  posScreen);
54 
55  // Add point to line
56  if (i == 0) {
57  path.moveTo (posScreen);
58  } else {
59  path.lineTo (posScreen);
60  }
61  }
62  }
63 
64  setPath (path);
65 }
66 
67 FittingCurve::~FittingCurve()
68 {
69 }
70 
71 double FittingCurve::yFromCoefficientsAndX (const FittingCurveCoefficients &fittingCoef,
72  double x) const
73 {
74  double sum = 0;
75 
76  for (int order = 0; order < fittingCoef.size(); order++) {
77  sum += fittingCoef [order] * qPow (x, order);
78  }
79 
80  return sum;
81 }
void transformRawGraphToScreen(const QPointF &pointRaw, QPointF &pointScreen) const
Transform from raw graph coordinates to linear cartesian graph coordinates, then to screen coordinate...
FittingCurve(const FittingCurveCoefficients &fittingCoef, double xMin, double xMax, bool isLogXTheta, bool isLogYRadius, const Transformation &transformation)
Single constructor.
Affine transformation between screen and graph coordinates, based on digitized axis points...
bool transformIsDefined() const
Transform is defined when at least three axis points have been digitized.