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