Engauge Digitizer  2
ExportFileFunctions.cpp
1 /******************************************************************************************************
2  * (C) 2014 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 "CallbackGatherXThetaValuesFunctions.h"
8 #include "CurveConnectAs.h"
9 #include "Document.h"
10 #include "DocumentModelGeneral.h"
11 #include "EngaugeAssert.h"
12 #include "ExportFileFunctions.h"
13 #include "ExportLayoutFunctions.h"
14 #include "ExportOrdinalsSmooth.h"
15 #include "ExportXThetaValuesMergedFunctions.h"
16 #include "FormatCoordsUnits.h"
17 #include "LinearToLog.h"
18 #include "Logger.h"
19 #include <QTextStream>
20 #include <QVector>
21 #include "Spline.h"
22 #include "SplinePair.h"
23 #include "Transformation.h"
24 #include <vector>
25 
26 using namespace std;
27 
29 {
30 }
31 
32 void ExportFileFunctions::exportAllPerLineXThetaValuesMerged (const DocumentModelExportFormat &modelExportOverride,
33  const Document &document,
34  const MainWindowModel &modelMainWindow,
35  const QStringList &curvesIncluded,
36  const ExportValuesXOrY &xThetaValues,
37  const QString &delimiter,
38  const Transformation &transformation,
39  bool isLogXTheta,
40  bool isLogYRadius,
41  QTextStream &str,
42  unsigned int &numWritesSoFar) const
43 {
44  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::exportAllPerLineXThetaValuesMerged";
45 
46  int curveCount = curvesIncluded.count();
47  int xThetaCount = xThetaValues.count();
48  QVector<QVector<QString*> > yRadiusValues (curveCount, QVector<QString*> (xThetaCount));
49  initializeYRadiusValues (curvesIncluded,
50  xThetaValues,
51  yRadiusValues);
52  loadYRadiusValues (modelExportOverride,
53  document,
54  modelMainWindow,
55  curvesIncluded,
56  transformation,
57  isLogXTheta,
58  isLogYRadius,
59  xThetaValues,
60  yRadiusValues);
61 
62  outputXThetaYRadiusValues (modelExportOverride,
63  document.modelCoords(),
64  document.modelGeneral(),
65  modelMainWindow,
66  curvesIncluded,
67  xThetaValues,
68  transformation,
69  yRadiusValues,
70  delimiter,
71  str,
72  numWritesSoFar);
73  destroy2DArray (yRadiusValues);
74 }
75 
76 void ExportFileFunctions::exportOnePerLineXThetaValuesMerged (const DocumentModelExportFormat &modelExportOverride,
77  const Document &document,
78  const MainWindowModel &modelMainWindow,
79  const QStringList &curvesIncluded,
80  const ExportValuesXOrY &xThetaValues,
81  const QString &delimiter,
82  const Transformation &transformation,
83  bool isLogXTheta,
84  bool isLogYRadius,
85  QTextStream &str,
86  unsigned int &numWritesSoFar) const
87 {
88  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::exportOnePerLineXThetaValuesMerged";
89 
90  QStringList::const_iterator itr;
91  for (itr = curvesIncluded.begin(); itr != curvesIncluded.end(); itr++) {
92 
93  // This curve
94  const int CURVE_COUNT = 1;
95  QString curveIncluded = *itr;
96  QStringList curvesIncluded (curveIncluded);
97 
98  int xThetaCount = xThetaValues.count();
99  QVector<QVector<QString*> > yRadiusValues (CURVE_COUNT, QVector<QString*> (xThetaCount));
100  initializeYRadiusValues (curvesIncluded,
101  xThetaValues,
102  yRadiusValues);
103  loadYRadiusValues (modelExportOverride,
104  document,
105  modelMainWindow,
106  curvesIncluded,
107  transformation,
108  isLogXTheta,
109  isLogYRadius,
110  xThetaValues,
111  yRadiusValues);
112  outputXThetaYRadiusValues (modelExportOverride,
113  document.modelCoords(),
114  document.modelGeneral(),
115  modelMainWindow,
116  curvesIncluded,
117  xThetaValues,
118  transformation,
119  yRadiusValues,
120  delimiter,
121  str,
122  numWritesSoFar);
123  destroy2DArray (yRadiusValues);
124  }
125 }
126 
128  const Document &document,
129  const MainWindowModel &modelMainWindow,
130  const Transformation &transformation,
131  QTextStream &str,
132  unsigned int &numWritesSoFar) const
133 {
134  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::exportToFile";
135 
136  // Log coordinates must be temporarily transformed to linear coordinates
137  bool isLogXTheta = (document.modelCoords().coordScaleXTheta() == COORD_SCALE_LOG);
138  bool isLogYRadius = (document.modelCoords().coordScaleYRadius() == COORD_SCALE_LOG);
139 
140  // Identify curves to be included
141  QStringList curvesIncluded = curvesToInclude (modelExportOverride,
142  document,
143  document.curvesGraphsNames(),
144  CONNECT_AS_FUNCTION_SMOOTH,
145  CONNECT_AS_FUNCTION_STRAIGHT);
146 
147  // Delimiter
148  const QString delimiter = exportDelimiterToText (modelExportOverride.delimiter(),
149  modelExportOverride.header() == EXPORT_HEADER_GNUPLOT);
150 
151  // Get x/theta values to be used
152  CallbackGatherXThetaValuesFunctions ftor (modelExportOverride,
153  curvesIncluded,
154  transformation);
155  Functor2wRet<const QString &, const Point &, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
157  document.iterateThroughCurvesPointsGraphs(ftorWithCallback);
158 
159  ExportXThetaValuesMergedFunctions exportXTheta (modelExportOverride,
160  ftor.xThetaValuesRaw(),
161  transformation);
162  ExportValuesXOrY xThetaValuesMerged = exportXTheta.xThetaValues ();
163 
164  // Skip if every curve was a relation
165  if (xThetaValuesMerged.count() > 0) {
166 
167  // Export in one of two layouts
168  if (modelExportOverride.layoutFunctions() == EXPORT_LAYOUT_ALL_PER_LINE) {
169  exportAllPerLineXThetaValuesMerged (modelExportOverride,
170  document,
171  modelMainWindow,
172  curvesIncluded,
173  xThetaValuesMerged,
174  delimiter,
175  transformation,
176  isLogXTheta,
177  isLogYRadius,
178  str,
179  numWritesSoFar);
180  } else {
181  exportOnePerLineXThetaValuesMerged (modelExportOverride,
182  document,
183  modelMainWindow,
184  curvesIncluded,
185  xThetaValuesMerged,
186  delimiter,
187  transformation,
188  isLogXTheta,
189  isLogYRadius,
190  str,
191  numWritesSoFar);
192  }
193  }
194 }
195 
196 void ExportFileFunctions::initializeYRadiusValues (const QStringList &curvesIncluded,
197  const ExportValuesXOrY &xThetaValuesMerged,
198  QVector<QVector<QString*> > &yRadiusValues) const
199 {
200  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::initializeYRadiusValues";
201 
202  // Initialize every entry with empty string
203  int curveCount = curvesIncluded.count();
204  int xThetaCount = xThetaValuesMerged.count();
205  for (int row = 0; row < xThetaCount; row++) {
206  for (int col = 0; col < curveCount; col++) {
207  yRadiusValues [col] [row] = new QString;
208  }
209  }
210 }
211 
212 double ExportFileFunctions::linearlyInterpolate (const Points &points,
213  double xThetaValue,
214  const Transformation &transformation) const
215 {
216  // LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::linearlyInterpolate";
217 
218  // If point is within the range of the function points then interpolation will be used, otherwise
219  // extrapolation will be used
220  double yRadius = 0;
221  QPointF posGraphBefore; // Not set until ip=1
222  bool foundIt = false;
223  for (int ip = 0; !foundIt && (ip < points.count()); ip++) {
224 
225  const Point &point = points.at (ip);
226  QPointF posGraph;
227  transformation.transformScreenToRawGraph (point.posScreen(),
228  posGraph);
229 
230  // Cases where we have found it at this point in the code
231  // (1) interpolation case where (xBefore < xThetaValue < xAfter)
232  // (2) extrapolation case where (xThetaValue < xBefore < xAfter and ip=0) for which we delay finding it until ip=1 so we have
233  // two points for extrapolating. This case is why we have the subtle test for ip>0 in the next line
234  if (xThetaValue <= posGraph.x() && (ip > 0)) {
235 
236  foundIt = true;
237 
238  // Case 1 comments: xThetaValue is between posGraphBefore and posGraph. Note that if posGraph.x()=posGraphBefore.x() then
239  // previous iteration of loop would have been used for interpolation, and then the loop was exited. Range of s is 0<s<1
240  // Case 2 comments: Range of s is s<0
241  double s = (xThetaValue - posGraphBefore.x()) / (posGraph.x() - posGraphBefore.x());
242  yRadius = (1.0 -s) * posGraphBefore.y() + s * posGraph.y();
243 
244  break;
245  }
246 
247  posGraphBefore = posGraph;
248  }
249 
250  if (!foundIt) {
251 
252  if (points.count() > 1) {
253 
254  // Extrapolation will be used since point is out of the range of the function points. Specifically, it is greater than the
255  // last x value in the function. Range of s is 1<s
256  int N = points.count();
257  const Point &pointLast = points.at (N - 1);
258  const Point &pointBefore = points.at (N - 2);
259  QPointF posGraphLast;
260  transformation.transformScreenToRawGraph (pointLast.posScreen(),
261  posGraphLast);
262  transformation.transformScreenToRawGraph (pointBefore.posScreen(),
263  posGraphBefore);
264  double s = (xThetaValue - posGraphBefore.x()) / (posGraphLast.x() - posGraphBefore.x());
265  yRadius = (1.0 - s) * posGraphBefore.y() + s * posGraphLast.y();
266 
267  } else if (points.count() == 1) {
268 
269  // Just use the single point
270  yRadius = posGraphBefore.y();
271 
272  } else {
273 
274  ENGAUGE_ASSERT (false);
275 
276  }
277  }
278 
279  return yRadius;
280 }
281 
282 void ExportFileFunctions::loadYRadiusValues (const DocumentModelExportFormat &modelExportOverride,
283  const Document &document,
284  const MainWindowModel &modelMainWindow,
285  const QStringList &curvesIncluded,
286  const Transformation &transformation,
287  bool isLogXTheta,
288  bool isLogYRadius,
289  const ExportValuesXOrY &xThetaValues,
290  QVector<QVector<QString*> > &yRadiusValues) const
291 {
292  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValues";
293 
294  // Loop through curves
295  int curveCount = curvesIncluded.count();
296  for (int col = 0; col < curveCount; col++) {
297 
298  const QString curveName = curvesIncluded.at (col);
299 
300  const Curve *curve = document.curveForCurveName (curveName);
301  Points points = curve->points (); // These points will be linearized below if either coordinate is log
302 
303  if (modelExportOverride.pointsSelectionFunctions() == EXPORT_POINTS_SELECTION_FUNCTIONS_RAW) {
304 
305  // No interpolation. Raw points
306  loadYRadiusValuesForCurveRaw (document.modelCoords(),
307  document.modelGeneral(),
308  modelMainWindow,
309  points,
310  xThetaValues,
311  transformation,
312  yRadiusValues [col]);
313  } else {
314 
315  // Interpolation
316  if (curve->curveStyle().lineStyle().curveConnectAs() == CONNECT_AS_FUNCTION_SMOOTH) {
317 
318  loadYRadiusValuesForCurveInterpolatedSmooth (document.modelCoords(),
319  document.modelGeneral(),
320  modelMainWindow,
321  points,
322  xThetaValues,
323  transformation,
324  isLogXTheta,
325  isLogYRadius,
326  yRadiusValues [col]);
327 
328  } else {
329 
330  loadYRadiusValuesForCurveInterpolatedStraight (document.modelCoords(),
331  document.modelGeneral(),
332  modelMainWindow,
333  points,
334  xThetaValues,
335  transformation,
336  yRadiusValues [col]);
337  }
338  }
339  }
340 }
341 
342 void ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedSmooth (const DocumentModelCoords &modelCoords,
343  const DocumentModelGeneral &modelGeneral,
344  const MainWindowModel &modelMainWindow,
345  const Points &points,
346  const ExportValuesXOrY &xThetaValues,
347  const Transformation &transformation,
348  bool isLogXTheta,
349  bool isLogYRadius,
350  QVector<QString*> &yRadiusValues) const
351 {
352  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedSmooth";
353 
354  // Convert screen coordinates to graph coordinates, in vectors suitable for spline fitting
355  vector<double> t;
356  vector<SplinePair> xy;
357  ExportOrdinalsSmooth ordinalsSmooth;
358 
359  ordinalsSmooth.loadSplinePairsWithTransformation (points,
360  transformation,
361  isLogXTheta,
362  isLogYRadius,
363  t,
364  xy);
365 
366  // Formatting
367  FormatCoordsUnits format;
368  QString dummyXThetaOut;
369 
370  if (points.count() == 0) {
371 
372  // Since there are no values, leave the field empty
373  for (int row = 0; row < xThetaValues.count(); row++) {
374  *(yRadiusValues [row]) = "";
375  }
376 
377  } else if (points.count() == 1 ||
378  points.count() == 2) {
379 
380  // Apply the single value everywhere (N=1) or do linear interpolation (N=2)
381  for (int row = 0; row < xThetaValues.count(); row++) {
382 
383  double xTheta = xThetaValues.at (row);
384  double yRadius;
385  if (points.count() == 1) {
386  yRadius = xy.at (0).y ();
387  } else {
388  double x0 = xy.at (0).x ();
389  double x1 = xy.at (1).x ();
390  double y0 = xy.at (0).y ();
391  double y1 = xy.at (1).y ();
392  if (x0 == x1) {
393  // Cannot do linear interpolation using two points at the same x value
394  yRadius = xy.at (0).y ();
395  } else {
396  double s = (xTheta - x0) / (x1 - x0);
397  yRadius = (1.0 - s) * y0 + s * y1;
398  }
399  }
400  format.unformattedToFormatted (xTheta,
401  yRadius,
402  modelCoords,
403  modelGeneral,
404  modelMainWindow,
405  dummyXThetaOut,
406  *(yRadiusValues [row]),
407  transformation);
408  }
409 
410  } else {
411 
412  // Iteration accuracy versus number of iterations 8->256, 10->1024, 12->4096. Single pixel accuracy out of
413  // typical image size of 1024x1024 means around 10 iterations gives decent accuracy for numbers much bigger
414  // than 1. A value of 12 gave some differences in the least significant figures of numbers like 10^-3 in
415  // the regression tests. Toggling between 30 and 32 made no difference in the regression tests.
416  const int MAX_ITERATIONS = 32;
417 
418  // Spline class requires at least one point
419  if (xy.size() > 0) {
420 
421  // Fit a spline
422  Spline spline (t,
423  xy);
424 
425  // Get value at desired points
426  for (int row = 0; row < xThetaValues.count(); row++) {
427 
428  double xTheta = xThetaValues.at (row);
429 
430  LinearToLog linearToLog;
431 
432  SplinePair splinePairFound = spline.findSplinePairForFunctionX (linearToLog.linearize (xTheta, isLogXTheta),
433  MAX_ITERATIONS);
434  double yRadius = linearToLog.delinearize (splinePairFound.y (),
435  isLogYRadius);
436 
437  // Save y/radius value for this row into yRadiusValues, after appropriate formatting
438  QString dummyXThetaOut;
439  format.unformattedToFormatted (xTheta,
440  yRadius,
441  modelCoords,
442  modelGeneral,
443  modelMainWindow,
444  dummyXThetaOut,
445  *(yRadiusValues [row]),
446  transformation);
447  }
448  }
449  }
450 }
451 
452 void ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedStraight (const DocumentModelCoords &modelCoords,
453  const DocumentModelGeneral &modelGeneral,
454  const MainWindowModel &modelMainWindow,
455  const Points &points,
456  const ExportValuesXOrY &xThetaValues,
457  const Transformation &transformation,
458  QVector<QString*> &yRadiusValues) const
459 {
460  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedStraight";
461 
462  FormatCoordsUnits format;
463 
464  // Get value at desired points
465  for (int row = 0; row < xThetaValues.count(); row++) {
466 
467  double xThetaValue = xThetaValues.at (row);
468 
469  double yRadius = linearlyInterpolate (points,
470  xThetaValue,
471  transformation);
472 
473  // Save y/radius value for this row into yRadiusValues, after appropriate formatting
474  QString dummyXThetaOut;
475  format.unformattedToFormatted (xThetaValue,
476  yRadius,
477  modelCoords,
478  modelGeneral,
479  modelMainWindow,
480  dummyXThetaOut,
481  *(yRadiusValues [row]),
482  transformation);
483  }
484 }
485 
486 void ExportFileFunctions::loadYRadiusValuesForCurveRaw (const DocumentModelCoords &modelCoords,
487  const DocumentModelGeneral &modelGeneral,
488  const MainWindowModel &modelMainWindow,
489  const Points &points,
490  const ExportValuesXOrY &xThetaValues,
491  const Transformation &transformation,
492  QVector<QString*> &yRadiusValues) const
493 {
494  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValuesForCurveRaw";
495 
496  FormatCoordsUnits format;
497 
498  // Since the curve points may be a subset of xThetaValues (in which case the non-applicable xThetaValues will have
499  // blanks for the yRadiusValues), we iterate over the smaller set
500  for (int pt = 0; pt < points.count(); pt++) {
501 
502  const Point &point = points.at (pt);
503 
504  QPointF posGraph;
505  transformation.transformScreenToRawGraph (point.posScreen(),
506  posGraph);
507 
508  // Find the closest point in xThetaValues. This is probably an N-squared algorithm, which is less than optimial,
509  // but the delay should be insignificant with normal-sized export files
510  double closestSeparation = 0.0;
511  int rowClosest = 0;
512  for (int row = 0; row < xThetaValues.count(); row++) {
513 
514  double xThetaValue = xThetaValues.at (row);
515 
516  double separation = qAbs (posGraph.x() - xThetaValue);
517 
518  if ((row == 0) ||
519  (separation < closestSeparation)) {
520 
521  closestSeparation = separation;
522  rowClosest = row;
523 
524  }
525  }
526 
527  // Save y/radius value for this row into yRadiusValues, after appropriate formatting
528  QString dummyXThetaOut;
529  format.unformattedToFormatted (posGraph.x(),
530  posGraph.y(),
531  modelCoords,
532  modelGeneral,
533  modelMainWindow,
534  dummyXThetaOut,
535  *(yRadiusValues [rowClosest]),
536  transformation);
537  }
538 }
539 
540 void ExportFileFunctions::outputXThetaYRadiusValues (const DocumentModelExportFormat &modelExportOverride,
541  const DocumentModelCoords &modelCoords,
542  const DocumentModelGeneral &modelGeneral,
543  const MainWindowModel &modelMainWindow,
544  const QStringList &curvesIncluded,
545  const ExportValuesXOrY &xThetaValuesMerged,
546  const Transformation &transformation,
547  QVector<QVector<QString*> > &yRadiusValues,
548  const QString &delimiter,
549  QTextStream &str,
550  unsigned int &numWritesSoFar) const
551 {
552  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::outputXThetaYRadiusValues";
553 
554  // Header
555  if (modelExportOverride.header() != EXPORT_HEADER_NONE) {
556  insertLineSeparator (numWritesSoFar == 0,
557  modelExportOverride.header (),
558  str);
559  if (modelExportOverride.header() == EXPORT_HEADER_GNUPLOT) {
560  str << gnuplotComment();
561  }
562  str << modelExportOverride.xLabel();
563  QStringList::const_iterator itrHeader;
564  for (itrHeader = curvesIncluded.begin(); itrHeader != curvesIncluded.end(); itrHeader++) {
565  QString curveName = *itrHeader;
566  str << delimiter << curveName;
567  }
568  str << "\n";
569  }
570 
571  // Table body
572  FormatCoordsUnits format;
573  const double DUMMY_Y_RADIUS = 1.0;
574 
575  for (int row = 0; row < xThetaValuesMerged.count(); row++) {
576 
577  if (rowHasAtLeastOneYRadiusEntry (yRadiusValues,
578  row)) {
579 
580  double xTheta = xThetaValuesMerged.at (row);
581 
582  // Output x/theta value for this row
583  QString xThetaString, yRadiusString;
584  format.unformattedToFormatted (xTheta,
585  DUMMY_Y_RADIUS,
586  modelCoords,
587  modelGeneral,
588  modelMainWindow,
589  xThetaString,
590  yRadiusString,
591  transformation);
592  str << wrapInDoubleQuotesIfNeeded (modelExportOverride,
593  xThetaString);
594 
595  for (int col = 0; col < yRadiusValues.count(); col++) {
596 
597  QString yRadiusString = *(yRadiusValues [col] [row]);
598  str << delimiter << wrapInDoubleQuotesIfNeeded (modelExportOverride,
599  yRadiusString);
600  }
601 
602  str << "\n";
603  }
604  }
605 
606  ++numWritesSoFar;
607 }
608 
609 bool ExportFileFunctions::rowHasAtLeastOneYRadiusEntry (const QVector<QVector<QString*> > &yRadiusValues,
610  int row) const
611 {
612  bool hasEntry = false;
613 
614  for (int col = 0; col < yRadiusValues.count(); col++) {
615 
616  QString entry = *(yRadiusValues [col] [row]);
617  if (!entry.isEmpty()) {
618 
619  hasEntry = true;
620  break;
621 
622  }
623  }
624 
625  return hasEntry;
626 }
Model for DlgSettingsGeneral and CmdSettingsGeneral.
CurveConnectAs curveConnectAs() const
Get method for connect type.
Definition: LineStyle.cpp:63
Creates the set of merged x/theta values for exporting functions, using interpolation.
Cubic interpolation given independent and dependent value vectors.
Definition: Spline.h:21
ExportValuesXOrY xThetaValues() const
Resulting x/theta values for all included functions.
double y() const
Get method for y.
Definition: SplinePair.cpp:71
Model for DlgSettingsExportFormat and CmdSettingsExportFormat.
double linearize(double value, bool isLog) const
Convert log coordinates to linear. This is a noop if the input is already linear. ...
Definition: LinearToLog.cpp:19
double delinearize(double value, bool isLog) const
Convert linear coordinates to log. This is a noop if the output is supposed to be linear...
Definition: LinearToLog.cpp:8
const Curve * curveForCurveName(const QString &curveName) const
See CurvesGraphs::curveForCurveNames, although this also works for AXIS_CURVE_NAME.
Definition: Document.cpp:332
ExportFileFunctions()
Single constructor.
DocumentModelGeneral modelGeneral() const
Get method for DocumentModelGeneral.
Definition: Document.cpp:717
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
CallbackSearchReturn callback(const QString &curveName, const Point &point)
Callback method.
const Points points() const
Return a shallow copy of the Points.
Definition: Curve.cpp:451
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.
LineStyle lineStyle() const
Get method for LineStyle.
Definition: CurveStyle.cpp:26
Utility class to interpolate points spaced evenly along a piecewise defined curve with fitted spline...
CoordScale coordScaleXTheta() const
Get method for linear/log scale on x/theta.
ExportDelimiter delimiter() const
Get method for delimiter.
Model for DlgSettingsCoords and CmdSettingsCoords.
Storage of one imported image and the data attached to that image.
Definition: Document.h:41
Container for one set of digitized Points.
Definition: Curve.h:33
Highest-level wrapper around other Formats classes.
void loadSplinePairsWithTransformation(const Points &points, const Transformation &transformation, bool isLogXTheta, bool isLogYRadius, std::vector< double > &t, std::vector< SplinePair > &xy) const
Load t (=ordinal) and xy (=screen position) spline pairs, converting screen coordinates to graph coor...
CoordScale coordScaleYRadius() const
Get method for linear/log scale on y/radius.
ExportHeader header() const
Get method for header.
ExportLayoutFunctions layoutFunctions() const
Get method for functions layout.
void transformScreenToRawGraph(const QPointF &coordScreen, QPointF &coordGraph) const
Transform from cartesian pixel screen coordinates to cartesian/polar graph coordinates.
QString xLabel() const
Get method for x label.
void iterateThroughCurvesPointsGraphs(const Functor2wRet< const QString &, const Point &, CallbackSearchReturn > &ftorWithCallback)
See Curve::iterateThroughCurvePoints, for all the graphs curves.
Definition: Document.cpp:466
SplinePair findSplinePairForFunctionX(double x, int numIterations) const
Use bisection algorithm to iteratively find the SplinePair interpolated to best match the specified x...
Definition: Spline.cpp:116
CurveStyle curveStyle() const
Return the curve style.
Definition: Curve.cpp:148
Callback for collecting X/Theta independent variables, for functions, in preparation for exporting...
Warps log coordinates to make them linear before passing them to code that accepts only linear coordi...
Definition: LinearToLog.h:7
ExportPointsSelectionFunctions pointsSelectionFunctions() const
Get method for point selection for functions.
DocumentModelCoords modelCoords() const
Get method for DocumentModelCoords.
Definition: Document.cpp:689
QStringList curvesGraphsNames() const
See CurvesGraphs::curvesGraphsNames.
Definition: Document.cpp:346
Single X/Y pair for cubic spline interpolation initialization and calculations.
Definition: SplinePair.h:11
void exportToFile(const DocumentModelExportFormat &modelExportOverride, const Document &document, const MainWindowModel &modelMainWindow, const Transformation &transformation, QTextStream &str, unsigned int &numWritesSoFar) const
Export Document points according to the settings.