Engauge Digitizer 2
Loading...
Searching...
No Matches
ExportFileFunctions.cpp
Go to the documentation of this file.
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
9#include "CurveConnectAs.h"
10#include "Document.h"
12#include "EngaugeAssert.h"
13#include "ExportFileFunctions.h"
17#include "FormatCoordsUnits.h"
18#include "GridLineLimiter.h"
19#include "LinearToLog.h"
20#include "Logger.h"
21#include <qmath.h>
22#include <QTextStream>
23#include <QVector>
24#include "Spline.h"
25#include "SplinePair.h"
26#include "Transformation.h"
27#include <vector>
28
29using namespace std;
30
34
35void ExportFileFunctions::exportAllPerLineXThetaValuesMerged (const DocumentModelExportFormat &modelExportOverride,
36 const Document &document,
37 const MainWindowModel &modelMainWindow,
38 const QStringList &curvesIncluded,
39 const ExportValuesXOrY &xThetaValues,
40 const QString &delimiter,
41 const Transformation &transformation,
42 bool isLogXTheta,
43 bool isLogYRadius,
44 const CurveLimits curveLimitsMin,
45 const CurveLimits curveLimitsMax,
47 unsigned int &numWritesSoFar) const
48{
49 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::exportAllPerLineXThetaValuesMerged";
50
51 int curveCount = curvesIncluded.count();
52 int xThetaCount = xThetaValues.count();
54 initializeYRadiusValues (curvesIncluded,
55 xThetaValues,
57 loadYRadiusValues (modelExportOverride,
58 document,
59 modelMainWindow,
60 curvesIncluded,
61 transformation,
64 xThetaValues,
65 curveLimitsMin,
66 curveLimitsMax,
68
69 outputXThetaYRadiusValues (modelExportOverride,
70 document.modelCoords(),
71 document.modelGeneral(),
72 modelMainWindow,
73 curvesIncluded,
74 xThetaValues,
75 transformation,
77 delimiter,
78 str,
81}
82
83void ExportFileFunctions::exportOnePerLineXThetaValuesMerged (const DocumentModelExportFormat &modelExportOverride,
84 const Document &document,
85 const MainWindowModel &modelMainWindow,
86 const QStringList &curvesIncluded,
87 const ExportValuesXOrY &xThetaValues,
88 const QString &delimiter,
89 const Transformation &transformation,
90 bool isLogXTheta,
91 bool isLogYRadius,
92 const CurveLimits curveLimitsMin,
93 const CurveLimits curveLimitsMax,
95 unsigned int &numWritesSoFar) const
96{
97 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::exportOnePerLineXThetaValuesMerged";
98
99 QStringList::const_iterator itr;
100 for (itr = curvesIncluded.begin(); itr != curvesIncluded.end(); itr++) {
101
102 // This curve
103 const int CURVE_COUNT = 1;
106
107 int xThetaCount = xThetaValues.count();
109 initializeYRadiusValues (curvesIncludedIter,
110 xThetaValues,
112 loadYRadiusValues (modelExportOverride,
113 document,
114 modelMainWindow,
116 transformation,
119 xThetaValues,
120 curveLimitsMin,
121 curveLimitsMax,
123 outputXThetaYRadiusValues (modelExportOverride,
124 document.modelCoords(),
125 document.modelGeneral(),
126 modelMainWindow,
128 xThetaValues,
129 transformation,
131 delimiter,
132 str,
135 }
136}
137
139 const Document &document,
140 const MainWindowModel &modelMainWindow,
141 const Transformation &transformation,
143 unsigned int &numWritesSoFar) const
144{
145 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::exportToFile";
146
147 // Log coordinates must be temporarily transformed to linear coordinates
150
151 // Identify curves to be included
152 QStringList curvesIncluded = curvesToInclude (modelExportOverride,
153 document,
154 document.curvesGraphsNames(),
157
158 // Delimiter
159 const QString delimiter = exportDelimiterToText (modelExportOverride.delimiter(),
160 modelExportOverride.header() == EXPORT_HEADER_GNUPLOT);
161
162 // Get x/theta values to be used. Also get the endpoint limits, if any
163 CurveLimits curveLimitsMin, curveLimitsMax;
166 CallbackGatherXThetasInGridLines ftor (modelMainWindow,
167 modelExportOverride,
168 curvesIncluded,
169 transformation,
170 document);
174 valuesVector = ftor.xThetaValuesRaw();
175 curveLimitsMin = ftor.curveLimitsMin();
176 curveLimitsMax = ftor.curveLimitsMax();
177 } else {
178 CallbackGatherXThetasInCurves ftor (modelExportOverride,
179 curvesIncluded,
180 transformation);
184 valuesVector = ftor.xThetaValuesRaw();
185 curveLimitsMin = ftor.curveLimitsMin();
186 curveLimitsMax = ftor.curveLimitsMax();
187 }
188
191 transformation);
192
194
195 // Skip if every curve was a relation
196 if (xThetaValuesMerged.count() > 0) {
197
198 // Export in one of two layouts
199 if (modelExportOverride.layoutFunctions() == EXPORT_LAYOUT_ALL_PER_LINE) {
200 exportAllPerLineXThetaValuesMerged (modelExportOverride,
201 document,
202 modelMainWindow,
203 curvesIncluded,
205 delimiter,
206 transformation,
209 curveLimitsMin,
210 curveLimitsMax,
211 str,
213 } else {
214 exportOnePerLineXThetaValuesMerged (modelExportOverride,
215 document,
216 modelMainWindow,
217 curvesIncluded,
219 delimiter,
220 transformation,
223 curveLimitsMin,
224 curveLimitsMax,
225 str,
227 }
228 }
229}
230
231void ExportFileFunctions::initializeYRadiusValues (const QStringList &curvesIncluded,
234{
235 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::initializeYRadiusValues";
236
237 // Initialize every entry with empty string
238 int curveCount = curvesIncluded.count();
239 int xThetaCount = xThetaValuesMerged.count();
240 for (int row = 0; row < xThetaCount; row++) {
241 for (int col = 0; col < curveCount; col++) {
242 yRadiusValues [col] [row] = new QString;
243 }
244 }
245}
246
247double ExportFileFunctions::linearlyInterpolate (const Points &points,
248 double xThetaValue,
249 const Transformation &transformation) const
250{
251 // LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::linearlyInterpolate";
252
253 // If point is within the range of the function points then interpolation will be used, otherwise
254 // extrapolation will be used
255 double yRadius = 0;
256 QPointF posGraphBefore; // Not set until ip=1
257 bool foundIt = false;
258 for (int ip = 0; !foundIt && (ip < points.count()); ip++) {
259
260 const Point &point = points.at (ip);
261 QPointF posGraph;
262 transformation.transformScreenToRawGraph (point.posScreen(),
263 posGraph);
264
265 // Cases where we have found it at this point in the code
266 // (1) interpolation case where (xBefore < xThetaValue < xAfter)
267 // (2) extrapolation case where (xThetaValue < xBefore < xAfter and ip=0) for which we delay finding it until ip=1 so we have
268 // two points for extrapolating. This case is why we have the subtle test for ip>0 in the next line
269 if (xThetaValue <= posGraph.x() && (ip > 0)) {
270
271 foundIt = true;
272
273 // Case 1 comments: xThetaValue is between posGraphBefore and posGraph. Note that if posGraph.x()=posGraphBefore.x() then
274 // previous iteration of loop would have been used for interpolation, and then the loop was exited. Range of s is 0<s<1
275 // Case 2 comments: Range of s is s<0
277 transformation.modelCoords(),
279 posGraph);
280
281 break;
282 }
283
284 posGraphBefore = posGraph;
285 }
286
287 if (!foundIt) {
288
289 if (points.count() > 1) {
290
291 // Extrapolation will be used since point is out of the range of the function points. Specifically, it is greater than the
292 // last x value in the function. Range of s is 1<s
293 int N = points.count();
294 const Point &pointLast = points.at (N - 1);
295 const Point &pointBefore = points.at (N - 2);
297 transformation.transformScreenToRawGraph (pointLast.posScreen(),
299 transformation.transformScreenToRawGraph (pointBefore.posScreen(),
302 transformation.modelCoords(),
305
306 } else if (points.count() == 1) {
307
308 // Just use the single point
310
311 } else {
312
313 ENGAUGE_ASSERT (false);
314
315 }
316 }
317
318 return yRadius;
319}
320
321void ExportFileFunctions::loadYRadiusValues (const DocumentModelExportFormat &modelExportOverride,
322 const Document &document,
323 const MainWindowModel &modelMainWindow,
324 const QStringList &curvesIncluded,
325 const Transformation &transformation,
326 bool isLogXTheta,
327 bool isLogYRadius,
328 const ExportValuesXOrY &xThetaValues,
329 const CurveLimits &curveLimitsMin,
330 const CurveLimits &curveLimitsMax,
332{
333 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValues";
334
335 // Loop through curves
336 int curveCount = curvesIncluded.count();
337 for (int col = 0; col < curveCount; col++) {
338
339 const QString curveName = curvesIncluded.at (col);
340
341 const Curve *curve = document.curveForCurveName (curveName);
342 Points points = curve->points (); // These points will be linearized below if either coordinate is log
343
345
346 // No interpolation. Raw points
347 loadYRadiusValuesForCurveRaw (document.modelCoords(),
348 document.modelGeneral(),
349 modelMainWindow,
350 points,
351 xThetaValues,
352 transformation,
353 curveName,
354 curveLimitsMin,
355 curveLimitsMax,
357 } else {
358
359 // Interpolation
360 if (curve->curveStyle().lineStyle().curveConnectAs() == CONNECT_AS_FUNCTION_SMOOTH) {
361
362 loadYRadiusValuesForCurveInterpolatedSmooth (document.modelCoords(),
363 document.modelGeneral(),
364 modelMainWindow,
365 points,
366 xThetaValues,
367 transformation,
370 curveName,
371 curveLimitsMin,
372 curveLimitsMax,
374
375 } else {
376
377 loadYRadiusValuesForCurveInterpolatedStraight (document.modelCoords(),
378 document.modelGeneral(),
379 modelMainWindow,
380 points,
381 xThetaValues,
382 transformation,
383 curveName,
384 curveLimitsMin,
385 curveLimitsMax,
387 }
388 }
389 }
390}
391
392void ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedSmooth (const DocumentModelCoords &modelCoords,
393 const DocumentModelGeneral &modelGeneral,
394 const MainWindowModel &modelMainWindow,
395 const Points &points,
396 const ExportValuesXOrY &xThetaValues,
397 const Transformation &transformation,
398 bool isLogXTheta,
399 bool isLogYRadius,
400 const QString &curveName,
401 const CurveLimits &curveLimitsMin,
402 const CurveLimits &curveLimitsMax,
404{
405 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedSmooth";
406
407 // Convert screen coordinates to graph coordinates, in vectors suitable for spline fitting
411
413 transformation,
416 t,
417 xy);
418
419 // Formatting
420 FormatCoordsUnits format;
422
423 if (points.count() == 0) {
424
425 // Since there are no values, leave the field empty
426 for (int row = 0; row < xThetaValues.count(); row++) {
427 *(yRadiusValues [row]) = "";
428 }
429
430 } else if (points.count() == 1 ||
431 points.count() == 2) {
432
433 // Apply the single value everywhere (N=1) or do linear interpolation (N=2)
434 for (int row = 0; row < xThetaValues.count(); row++) {
435
436 double xTheta = xThetaValues.at (row);
437 double yRadius;
438 if (points.count() == 1) {
439 yRadius = xy.at (0).y ();
440 } else {
441 double x0 = xy.at (0).x ();
442 double x1 = xy.at (1).x ();
443 double y0 = xy.at (0).y ();
444 double y1 = xy.at (1).y ();
445 double numerator = (xTheta - x0);
446 double denominator = (x1 - x0);
447 if (qAbs (denominator) < qAbs (numerator) / 1.0e6) {
448 // Cannot do linear interpolation using two points at the same x value
449 yRadius = xy.at (0).y ();
450 } else {
451 double s = numerator / denominator;
452 yRadius = (1.0 - s) * y0 + s * y1;
453 }
454 }
455 if (xThetaIsNotOutOfBounds (xTheta,
456 curveName,
457 curveLimitsMin,
458 curveLimitsMax)) {
460 yRadius,
461 modelCoords,
462 modelGeneral,
463 modelMainWindow,
465 *(yRadiusValues [row]),
466 transformation);
467 } else {
468 *(yRadiusValues [row]) = "";
469 }
470 }
471
472 } else {
473
474 // Iteration accuracy versus number of iterations 8->256, 10->1024, 12->4096. Single pixel accuracy out of
475 // typical image size of 1024x1024 means around 10 iterations gives decent accuracy for numbers much bigger
476 // than 1. A value of 12 gave some differences in the least significant figures of numbers like 10^-3 in
477 // the regression tests. Toggling between 30 and 32 made no difference in the regression tests.
478 const int MAX_ITERATIONS = 32;
479
480 // Spline class requires at least one point
481 if (xy.size() > 0) {
482
483 // Fit a spline
484 Spline spline (t,
485 xy);
486
487 // Get value at desired points
488 for (int row = 0; row < xThetaValues.count(); row++) {
489
490 double xTheta = xThetaValues.at (row);
491
493
494 SplinePair splinePairFound = spline.findSplinePairForFunctionX (linearToLog.linearize (xTheta, isLogXTheta),
496 double yRadius = linearToLog.delinearize (splinePairFound.y (),
498
499 // Save y/radius value for this row into yRadiusValues, after appropriate formatting
500 if (xThetaIsNotOutOfBounds (xTheta,
501 curveName,
502 curveLimitsMin,
503 curveLimitsMax)) {
505 yRadius,
506 modelCoords,
507 modelGeneral,
508 modelMainWindow,
510 *(yRadiusValues [row]),
511 transformation);
512 } else {
513 *(yRadiusValues [row]) = "";
514 }
515 }
516 }
517 }
518}
519
520void ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedStraight (const DocumentModelCoords &modelCoords,
521 const DocumentModelGeneral &modelGeneral,
522 const MainWindowModel &modelMainWindow,
523 const Points &points,
524 const ExportValuesXOrY &xThetaValues,
525 const Transformation &transformation,
526 const QString &curveName,
527 const CurveLimits &curveLimitsMin,
528 const CurveLimits &curveLimitsMax,
530{
531 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedStraight";
532
533 FormatCoordsUnits format;
534
535 // Get value at desired points
537 for (int row = 0; row < xThetaValues.count(); row++) {
538
539 double xTheta = xThetaValues.at (row);
540
541 // Interpolation on curve with no points will trigger an assert so check the point count
542 *(yRadiusValues [row]) = "";
543 if (points.count () > 0) {
544
545 double yRadius = linearlyInterpolate (points,
546 xTheta,
547 transformation);
548
549 // Save y/radius value for this row into yRadiusValues, after appropriate formatting
550 if (xThetaIsNotOutOfBounds (xTheta,
551 curveName,
552 curveLimitsMin,
553 curveLimitsMax)) {
555 yRadius,
556 modelCoords,
557 modelGeneral,
558 modelMainWindow,
560 *(yRadiusValues [row]),
561 transformation);
562 }
563 }
564 }
565}
566
567void ExportFileFunctions::loadYRadiusValuesForCurveRaw (const DocumentModelCoords &modelCoords,
568 const DocumentModelGeneral &modelGeneral,
569 const MainWindowModel &modelMainWindow,
570 const Points &points,
571 const ExportValuesXOrY &xThetaValues,
572 const Transformation &transformation,
573 const QString &curveName,
574 const CurveLimits &curveLimitsMin,
575 const CurveLimits &curveLimitsMax,
577{
578 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValuesForCurveRaw";
579
580 FormatCoordsUnits format;
581
582 // Since the curve points may be a subset of xThetaValues (in which case the non-applicable xThetaValues will have
583 // blanks for the yRadiusValues), we iterate over the smaller set
584 for (int pt = 0; pt < points.count(); pt++) {
585
586 const Point &point = points.at (pt);
587
588 QPointF posGraph;
589 transformation.transformScreenToRawGraph (point.posScreen(),
590 posGraph);
591
592 // Find the closest point in xThetaValues. This is probably an N-squared algorithm, which is less than optimial,
593 // but the delay should be insignificant with normal-sized export files
594 double closestSeparation = 0.0;
595 int rowClosest = 0;
596 for (int row = 0; row < xThetaValues.count(); row++) {
597
598 double xTheta = xThetaValues.at (row);
599
600 double separation = qAbs (posGraph.x() - xTheta);
601
602 if ((row == 0) ||
604
606 rowClosest = row;
607
608 }
609 }
610
611 // Save y/radius value for this row into yRadiusValues, after appropriate formatting
612 if (xThetaIsNotOutOfBounds (posGraph.x(),
613 curveName,
614 curveLimitsMin,
615 curveLimitsMax)) {
617 format.unformattedToFormatted (posGraph.x(),
618 posGraph.y(),
619 modelCoords,
620 modelGeneral,
621 modelMainWindow,
624 transformation);
625 } else {
626 *(yRadiusValues [rowClosest]) = "";
627 }
628 }
629}
630
631void ExportFileFunctions::outputXThetaYRadiusValues (const DocumentModelExportFormat &modelExportOverride,
632 const DocumentModelCoords &modelCoords,
633 const DocumentModelGeneral &modelGeneral,
634 const MainWindowModel &modelMainWindow,
635 const QStringList &curvesIncluded,
637 const Transformation &transformation,
639 const QString &delimiter,
641 unsigned int &numWritesSoFar) const
642{
643 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::outputXThetaYRadiusValues";
644
645 // Header
646 if (modelExportOverride.header() != EXPORT_HEADER_NONE) {
648 modelExportOverride.header (),
649 str);
650 if (modelExportOverride.header() == EXPORT_HEADER_GNUPLOT) {
651 str << gnuplotComment();
652 }
653 str << modelExportOverride.xLabel();
654 QStringList::const_iterator itrHeader;
655 for (itrHeader = curvesIncluded.begin(); itrHeader != curvesIncluded.end(); itrHeader++) {
656 QString curveName = *itrHeader;
657 str << delimiter << curveName;
658 }
659 str << "\n";
660 }
661
662 // Table body
663 FormatCoordsUnits format;
664 const double DUMMY_Y_RADIUS = 1.0;
665
666 for (int row = 0; row < xThetaValuesMerged.count(); row++) {
667
668 if (rowHasAtLeastOneYRadiusEntry (yRadiusValues,
669 row)) {
670
671 double xTheta = xThetaValuesMerged.at (row);
672
673 // Output x/theta value for this row
677 modelCoords,
678 modelGeneral,
679 modelMainWindow,
682 transformation);
683 str << wrapInDoubleQuotesIfNeeded (modelExportOverride,
685
686 for (int col = 0; col < yRadiusValues.count(); col++) {
687
689 str << delimiter << wrapInDoubleQuotesIfNeeded (modelExportOverride,
691 }
692
693 str << "\n";
694 }
695 }
696
698}
699
700bool ExportFileFunctions::rowHasAtLeastOneYRadiusEntry (const QVector<QVector<QString*> > &yRadiusValues,
701 int row) const
702{
703 bool hasEntry = false;
704
705 for (int col = 0; col < yRadiusValues.count(); col++) {
706
708 if (!entry.isEmpty()) {
709
710 hasEntry = true;
711 break;
712
713 }
714 }
715
716 return hasEntry;
717}
718
719bool ExportFileFunctions::xThetaIsNotOutOfBounds (double xTheta,
720 const QString &curveName,
721 const CurveLimits &curveLimitsMin,
722 const CurveLimits &curveLimitsMax) const
723{
724 bool ok = true;
725
726 if (curveLimitsMin.contains (curveName)) {
727 ok = ok && (curveLimitsMin [curveName] <= xTheta);
728 }
729
730 if (curveLimitsMax.contains (curveName)) {
731 ok = ok && (xTheta <= curveLimitsMax [curveName]);
732 }
733
734 return ok;
735}
@ COORD_SCALE_LOG
Definition CoordScale.h:14
@ CONNECT_AS_FUNCTION_STRAIGHT
@ CONNECT_AS_FUNCTION_SMOOTH
QHash< QString, double > CurveLimits
Definition CurveLimits.h:14
const int INNER_RADIUS_MIN
#define ENGAUGE_ASSERT(cond)
Drop in replacement for Q_ASSERT if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS) define ENGAUGE...
QString exportDelimiterToText(ExportDelimiter exportDelimiter, bool isGnuplotDelimiter)
@ EXPORT_HEADER_NONE
@ EXPORT_HEADER_GNUPLOT
@ EXPORT_LAYOUT_ALL_PER_LINE
@ EXPORT_POINTS_SELECTION_FUNCTIONS_RAW
@ EXPORT_POINTS_SELECTION_FUNCTIONS_INTERPOLATE_GRID_LINES
QList< double > ExportValuesXOrY
log4cpp::Category * mainCat
Definition Logger.cpp:14
QList< Point > Points
Definition Points.h:13
QMap< double, bool > ValuesVectorXOrY
Callback for collecting X/Theta independent variables, for functions, in preparation for exporting,...
virtual CallbackSearchReturn callback(const QString &curveName, const Point &point)
Callback method.
Callback for collecting X/Theta independent variables, for functions, in preparation for exporting,...
virtual CallbackSearchReturn callback(const QString &curveName, const Point &point)
Callback method.
Container for one set of digitized Points.
Definition Curve.h:34
const Points points() const
Return a shallow copy of the Points.
Definition Curve.cpp:451
Model for DlgSettingsCoords and CmdSettingsCoords.
CoordScale coordScaleYRadius() const
Get method for linear/log scale on y/radius.
CoordScale coordScaleXTheta() const
Get method for linear/log scale on x/theta.
Model for DlgSettingsExportFormat and CmdSettingsExportFormat.
ExportHeader header() const
Get method for header.
QString xLabel() const
Get method for x label.
ExportPointsSelectionFunctions pointsSelectionFunctions() const
Get method for point selection for functions.
ExportDelimiter delimiter() const
Get method for delimiter.
ExportLayoutFunctions layoutFunctions() const
Get method for functions layout.
Model for DlgSettingsGeneral and CmdSettingsGeneral.
Storage of one imported image and the data attached to that image.
Definition Document.h:42
DocumentModelGeneral modelGeneral() const
Get method for DocumentModelGeneral.
Definition Document.cpp:723
void iterateThroughCurvesPointsGraphs(const Functor2wRet< const QString &, const Point &, CallbackSearchReturn > &ftorWithCallback)
See Curve::iterateThroughCurvePoints, for all the graphs curves.
Definition Document.cpp:472
QStringList curvesGraphsNames() const
See CurvesGraphs::curvesGraphsNames.
Definition Document.cpp:349
DocumentModelCoords modelCoords() const
Get method for DocumentModelCoords.
Definition Document.cpp:695
const Curve * curveForCurveName(const QString &curveName) const
See CurvesGraphs::curveForCurveNames, although this also works for AXIS_CURVE_NAME.
Definition Document.cpp:335
void destroy2DArray(QVector< QVector< QString * > > &array) const
Deallocate memory for array.
double linearlyInterpolateYRadiusFromTwoPoints(double xThetaValue, const DocumentModelCoords &modelCoords, const QPointF &posGraphBefore, const QPointF &posGraph) const
Interpolate (if xThetaValue is between posGraphBefore.x() and posGraph.x()) or extrapolate (if xTheta...
QString wrapInDoubleQuotesIfNeeded(const DocumentModelExportFormat &modelExportOverride, const QString &valueString) const
RFC 4180 says if values are delimited by a comma AND a value has commas in it (for locale like Englis...
QString gnuplotComment() const
Gnuplot comment delimiter.
QStringList curvesToInclude(const DocumentModelExportFormat &modelExportOverride, const Document &document, const QStringList &curvesGraphsNames, CurveConnectAs curveConnectAs1, CurveConnectAs curveConnectAs2) const
Identify curves to include in export. The specified DocumentModelExportFormat overrides same data in ...
void insertLineSeparator(bool isFirst, ExportHeader exportHeader, QTextStream &str) const
Insert line(s) between successive sets of curves.
ExportFileFunctions()
Single constructor.
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.
Utility class to interpolate points spaced evenly along a piecewise defined curve with fitted spline.
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...
Creates the set of merged x/theta values for exporting functions, using interpolation.
Highest-level wrapper around other Formats classes.
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...
Warps log coordinates to make them linear before passing them to code that accepts only linear coordi...
Definition LinearToLog.h:14
Model for DlgSettingsMainWindow.
Class that represents one digitized point. The screen-to-graph coordinate transformation is always ex...
Definition Point.h:26
QPointF posScreen() const
Accessor for screen position.
Definition Point.cpp:404
Single X/Y pair for cubic spline interpolation initialization and calculations.
Definition SplinePair.h:14
Cubic interpolation given independent and dependent value vectors.
Definition Spline.h:30
Affine transformation between screen and graph coordinates, based on digitized axis points.
void transformScreenToRawGraph(const QPointF &coordScreen, QPointF &coordGraph) const
Transform from cartesian pixel screen coordinates to cartesian/polar graph coordinates.
DocumentModelCoords modelCoords() const
Get method for DocumentModelCoords.
#define LOG4CPP_INFO_S(logger)
Definition convenience.h:18