Engauge Digitizer 2
Loading...
Searching...
No Matches
ExportFileRelations.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
7#include "CurveConnectAs.h"
8#include "Document.h"
10#include "EngaugeAssert.h"
11#include "ExportFileRelations.h"
15#include "FormatCoordsUnits.h"
16#include "Logger.h"
17#include <qdebug.h>
18#include <qmath.h>
19#include <QTextStream>
20#include <QVector>
21#include "Spline.h"
22#include "SplinePair.h"
23#include "Transformation.h"
24#include <vector>
25
26using namespace std;
27
28const int COLUMNS_PER_CURVE = 2;
29
33
34void ExportFileRelations::exportAllPerLineXThetaValuesMerged (const DocumentModelExportFormat &modelExportOverride,
35 const Document &document,
36 const MainWindowModel &modelMainWindow,
37 const QStringList &curvesIncluded,
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)) << "ExportFileRelations::exportAllPerLineXThetaValuesMerged";
46
47 int maxColumnSize = maxColumnSizeAllocation (modelExportOverride,
48 document,
49 transformation,
50 isLogXTheta,
51 isLogYRadius,
52 curvesIncluded);
53
54 // Skip if every curve was a function
55 if (maxColumnSize > 0) {
56
58
59 exportAllPerLineXThetaValuesMergedMultiplePass (maxColumnSize,
60 modelExportOverride,
61 document,
62 modelMainWindow,
63 curvesIncluded,
64 delimiter,
65 transformation,
66 isLogXTheta,
67 isLogYRadius,
68 str,
69 numWritesSoFar);
70
71 } else {
72
73 exportAllPerLineXThetaValuesMergedOnePass (maxColumnSize,
74 modelExportOverride,
75 document,
76 modelMainWindow,
77 curvesIncluded,
78 delimiter,
79 transformation,
80 isLogXTheta,
81 isLogYRadius,
82 str,
83 numWritesSoFar);
84 }
85 }
86}
87
88void ExportFileRelations::exportAllPerLineXThetaValuesMergedMultiplePass (int maxColumnSize,
89 const DocumentModelExportFormat &modelExportOverride,
90 const Document &document,
91 const MainWindowModel &modelMainWindow,
92 const QStringList &curvesIncluded,
93 const QString &delimiter,
94 const Transformation &transformation,
95 bool isLogXTheta,
96 bool isLogYRadius,
97 QTextStream &str,
98 unsigned int &numWritesSoFar) const
99{
100 // For interpolation of relations in general a single set of x/theta values cannot be created that work for every
101 // relation curve, since one curve may have M y/radius values for a specific x/radius while another curve has
102 // N y/radius values for that same x/radius value. So we export each curve into memory separately and then merge
103 // the results. Why? Since the methods called from this method all assume a single set of x/theta values can be
104 // used for all curves
105
106 const int CURVE_COUNT_PER_PASS = 1;
107
108 int curveCount = curvesIncluded.count ();
109
110 QVector<QVector<QString*> > xThetaYRadiusValuesAll (COLUMNS_PER_CURVE * curveCount, QVector<QString*> (maxColumnSize));
111
112 initializeXThetaYRadiusValues (curvesIncluded,
113 xThetaYRadiusValuesAll);
114
115 // One pass per curve
116 int colX = 0, colY = colX + 1;
117 for (int c = 0; c < curvesIncluded.count (); c++) {
118 QString curve = curvesIncluded [c];
119
120 QStringList curvesIncludedInPass;
121 curvesIncludedInPass << curve;
122 ENGAUGE_ASSERT (curvesIncludedInPass.count () == CURVE_COUNT_PER_PASS);
123
124 QVector<QVector<QString*> > xThetaYRadiusValuesOne (COLUMNS_PER_CURVE * CURVE_COUNT_PER_PASS, QVector<QString*> (maxColumnSize));
125
126 initializeXThetaYRadiusValues (curvesIncludedInPass,
127 xThetaYRadiusValuesOne);
128 loadXThetaYRadiusValues (modelExportOverride,
129 document,
130 modelMainWindow,
131 curvesIncludedInPass,
132 transformation,
133 isLogXTheta,
134 isLogYRadius,
135 xThetaYRadiusValuesOne);
136
137 // Merge one curve array into all curves array
138 for (int row = 0; row < maxColumnSize; row++) {
139 *(xThetaYRadiusValuesAll [colX] [row]) = *(xThetaYRadiusValuesOne [0] [row]);
140 *(xThetaYRadiusValuesAll [colY] [row]) = *(xThetaYRadiusValuesOne [1] [row]);
141 }
142
143 destroy2DArray (xThetaYRadiusValuesOne);
144
145 colX += 2;
146 colY += 2;
147 }
148
149 outputXThetaYRadiusValues (modelExportOverride,
150 curvesIncluded,
151 xThetaYRadiusValuesAll,
152 delimiter,
153 str,
154 numWritesSoFar);
155 destroy2DArray (xThetaYRadiusValuesAll);
156}
157
158void ExportFileRelations::exportAllPerLineXThetaValuesMergedOnePass (int maxColumnSize,
159 const DocumentModelExportFormat &modelExportOverride,
160 const Document &document,
161 const MainWindowModel &modelMainWindow,
162 const QStringList &curvesIncluded,
163 const QString &delimiter,
164 const Transformation &transformation,
165 bool isLogXTheta,
166 bool isLogYRadius,
167 QTextStream &str,
168 unsigned int &numWritesSoFar) const
169{
170 int curveCount = curvesIncluded.count ();
171
172 QVector<QVector<QString*> > xThetaYRadiusValues (COLUMNS_PER_CURVE * curveCount, QVector<QString*> (maxColumnSize));
173 initializeXThetaYRadiusValues (curvesIncluded,
174 xThetaYRadiusValues);
175 loadXThetaYRadiusValues (modelExportOverride,
176 document,
177 modelMainWindow,
178 curvesIncluded,
179 transformation,
180 isLogXTheta,
181 isLogYRadius,
182 xThetaYRadiusValues);
183 outputXThetaYRadiusValues (modelExportOverride,
184 curvesIncluded,
185 xThetaYRadiusValues,
186 delimiter,
187 str,
188 numWritesSoFar);
189 destroy2DArray (xThetaYRadiusValues);
190}
191
192void ExportFileRelations::exportOnePerLineXThetaValuesMerged (const DocumentModelExportFormat &modelExportOverride,
193 const Document &document,
194 const MainWindowModel &modelMainWindow,
195 const QStringList &curvesIncluded,
196 const QString &delimiter,
197 const Transformation &transformation,
198 bool isLogXTheta,
199 bool isLogYRadius,
200 QTextStream &str,
201 unsigned int &numWritesSoFar) const
202{
203 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::exportOnePerLineXThetaValuesMerged";
204
205 QStringList::const_iterator itr;
206 for (itr = curvesIncluded.begin(); itr != curvesIncluded.end(); itr++) {
207
208 QString curveIncluded = *itr;
209
210 exportAllPerLineXThetaValuesMerged (modelExportOverride,
211 document,
212 modelMainWindow,
213 QStringList (curveIncluded),
214 delimiter,
215 transformation,
216 isLogXTheta,
217 isLogYRadius,
218 str,
219 numWritesSoFar);
220 }
221}
222
224 const Document &document,
225 const MainWindowModel &modelMainWindow,
226 const Transformation &transformation,
227 QTextStream &str,
228 unsigned int &numWritesSoFar,
229 bool &isOverrun) const
230{
231 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::exportToFile";
232
233 // There are no known ways for relations to overflow the maximum points limit so
234 // this initialization value will not be overwritten
235 isOverrun = false;
236
237 // Log coordinates must be temporarily transformed to linear coordinates
238 bool isLogXTheta = (document.modelCoords().coordScaleXTheta() == COORD_SCALE_LOG);
239 bool isLogYRadius = (document.modelCoords().coordScaleYRadius() == COORD_SCALE_LOG);
240
241 // Identify curves to be included
242 QStringList curvesIncluded = curvesToInclude (modelExportOverride,
243 document,
244 document.curvesGraphsNames(),
247
248 // Delimiter
249 const QString delimiter = exportDelimiterToText (modelExportOverride.delimiter(),
250 modelExportOverride.header() == EXPORT_HEADER_GNUPLOT);
251
252 // Export in one of two layouts
253 if (modelExportOverride.layoutFunctions() == EXPORT_LAYOUT_ALL_PER_LINE) {
254 exportAllPerLineXThetaValuesMerged (modelExportOverride,
255 document,
256 modelMainWindow,
257 curvesIncluded,
258 delimiter,
259 transformation,
260 isLogXTheta,
261 isLogYRadius,
262 str,
263 numWritesSoFar);
264 } else {
265 exportOnePerLineXThetaValuesMerged (modelExportOverride,
266 document,
267 modelMainWindow,
268 curvesIncluded,
269 delimiter,
270 transformation,
271 isLogXTheta,
272 isLogYRadius,
273 str,
274 numWritesSoFar);
275 }
276}
277
278void ExportFileRelations::initializeXThetaYRadiusValues (const QStringList &curvesIncluded,
279 QVector<QVector<QString*> > &xThetaYRadiusValues) const
280{
281 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::initializeXThetaYRadiusValues";
282
283 // Initialize every entry with empty string
284 int curveCount = curvesIncluded.count();
285 int xThetaCount = xThetaYRadiusValues [0].count();
286 for (int row = 0; row < xThetaCount; row++) {
287 for (int col = 0; col < COLUMNS_PER_CURVE * curveCount; col++) {
288 xThetaYRadiusValues [col] [row] = new QString;
289 }
290 }
291}
292
293QPointF ExportFileRelations::linearlyInterpolate (const Points &points,
294 double ordinal,
295 const Transformation &transformation) const
296{
297 // LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::linearlyInterpolate";
298
299 double xTheta = 0, yRadius = 0;
300 double ordinalBefore = 0; // Not set until ip=1
301 QPointF posGraphBefore; // Not set until ip=1
302 bool foundIt = false;
303 for (int ip = 0; ip < points.count(); ip++) {
304
305 const Point &point = points.at (ip);
306 QPointF posGraph;
307 transformation.transformScreenToRawGraph (point.posScreen(),
308 posGraph);
309
310 if (ordinal <= point.ordinal()) {
311
312 foundIt = true;
313 if (ip == 0) {
314
315 // Use first point
316 xTheta = posGraph.x();
317 yRadius = posGraph.y();
318
319 } else {
320
321 // Between posGraphBefore and posGraph. Note that if posGraph.x()=posGraphBefore.x() then
322 // previous iteration of loop would have been used for interpolation, and then the loop was exited
323 double s = (ordinal - ordinalBefore) / (point.ordinal() - ordinalBefore);
324 xTheta = (1.0 - s) * posGraphBefore.x() + s * posGraph.x();
325 yRadius = (1.0 - s) * posGraphBefore.y() + s * posGraph.y();
326 }
327
328 break;
329 }
330
331 ordinalBefore = point.ordinal();
332 posGraphBefore = posGraph;
333 }
334
335 if (!foundIt) {
336
337 // Use last point
338 xTheta = posGraphBefore.x();
339 yRadius = posGraphBefore.y();
340
341 }
342
343 return QPointF (xTheta,
344 yRadius);
345}
346
347void ExportFileRelations::loadXThetaYRadiusValues (const DocumentModelExportFormat &modelExportOverride,
348 const Document &document,
349 const MainWindowModel &modelMainWindow,
350 const QStringList &curvesIncluded,
351 const Transformation &transformation,
352 bool isLogXTheta,
353 bool isLogYRadius,
354 QVector<QVector<QString*> > &xThetaYRadiusValues) const
355{
356 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::loadXThetaYRadiusValues";
357
358 // The curve processing logic here is mirrored in maxColumnSizeAllocation so the array allocations are in sync
359 for (int ic = 0; ic < curvesIncluded.count(); ic++) {
360
361 int colXTheta = 2 * ic;
362 int colYRadius = 2 * ic + 1;
363
364 const QString curveName = curvesIncluded.at (ic);
365
366 const Curve *curve = document.curveForCurveName (curveName);
367 const Points points = curve->points ();
368
370
371 // No interpolation. Raw points
372 loadXThetaYRadiusValuesForCurveRaw (document.modelCoords(),
373 document.modelGeneral(),
374 modelMainWindow,
375 points,
376 xThetaYRadiusValues [colXTheta],
377 xThetaYRadiusValues [colYRadius],
378 transformation);
379 } else {
380
381 const LineStyle &lineStyle = document.modelCurveStyles().lineStyle(curveName);
382
383 // Interpolation. Points are taken approximately every every modelExport.pointsIntervalRelations
384 ExportValuesOrdinal ordinals = ordinalsAtIntervals (modelExportOverride.pointsIntervalRelations(),
385 modelExportOverride.pointsIntervalUnitsRelations(),
386 lineStyle.curveConnectAs(),
387 transformation,
388 isLogXTheta,
389 isLogYRadius,
390 points);
391
393
394 loadXThetaYRadiusValuesForCurveInterpolatedSmooth (document.modelCoords(),
395 document.modelGeneral(),
396 modelMainWindow,
397 points,
398 ordinals,
399 xThetaYRadiusValues [colXTheta],
400 xThetaYRadiusValues [colYRadius],
401 transformation,
402 isLogXTheta,
403 isLogYRadius);
404
405 } else {
406
407 loadXThetaYRadiusValuesForCurveInterpolatedStraight (document.modelCoords(),
408 document.modelGeneral(),
409 modelMainWindow,
410 points,
411 ordinals,
412 xThetaYRadiusValues [colXTheta],
413 xThetaYRadiusValues [colYRadius],
414 transformation);
415 }
416 }
417 }
418}
419
420void ExportFileRelations::loadXThetaYRadiusValuesForCurveInterpolatedSmooth (const DocumentModelCoords &modelCoords,
421 const DocumentModelGeneral &modelGeneral,
422 const MainWindowModel &modelMainWindow,
423 const Points &points,
424 const ExportValuesOrdinal &ordinals,
425 QVector<QString*> &xThetaValues,
426 QVector<QString*> &yRadiusValues,
427 const Transformation &transformation,
428 bool isLogXTheta,
429 bool isLogYRadius) const
430{
431 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::loadXThetaYRadiusValuesForCurveInterpolatedSmooth";
432
433 vector<double> t;
434 vector<SplinePair> xy;
435 ExportOrdinalsSmooth ordinalsSmooth;
436
437 ordinalsSmooth.loadSplinePairsWithTransformation (points,
438 transformation,
439 isLogXTheta,
440 isLogYRadius,
441 t,
442 xy);
443
444 // Spline class requires at least one point
445 if (xy.size() > 0) {
446
447 // Fit a spline
448 Spline spline (t,
449 xy);
450
451 FormatCoordsUnits format;
452
453 // Extract the points
454 for (int row = 0; row < ordinals.count(); row++) {
455
456 double ordinal = ordinals.at (row);
457 SplinePair splinePairFound = spline.interpolateCoeff(ordinal);
458 double xTheta = splinePairFound.x ();
459 double yRadius = splinePairFound.y ();
460
461 // Save values for this row into xThetaValues and yRadiusValues, after appropriate formatting
462 format.unformattedToFormatted (xTheta,
463 yRadius,
464 modelCoords,
465 modelGeneral,
466 modelMainWindow,
467 *(xThetaValues [row]),
468 *(yRadiusValues [row]),
469 transformation);
470 }
471 }
472}
473
474void ExportFileRelations::loadXThetaYRadiusValuesForCurveInterpolatedStraight (const DocumentModelCoords &modelCoords,
475 const DocumentModelGeneral &modelGeneral,
476 const MainWindowModel &modelMainWindow,
477 const Points &points,
478 const ExportValuesOrdinal &ordinals,
479 QVector<QString*> &xThetaValues,
480 QVector<QString*> &yRadiusValues,
481 const Transformation &transformation) const
482{
483 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::loadXThetaYRadiusValuesForCurveInterpolatedStraight";
484
485 FormatCoordsUnits format;
486
487 // Get value at desired points
488 for (int row = 0; row < ordinals.count(); row++) {
489
490 double ordinal = ordinals.at (row);
491
492 QPointF pointInterpolated = linearlyInterpolate (points,
493 ordinal,
494 transformation);
495
496 // Save values for this row into xThetaValues and yRadiusValues, after appropriate formatting
497 format.unformattedToFormatted (pointInterpolated.x(),
498 pointInterpolated.y(),
499 modelCoords,
500 modelGeneral,
501 modelMainWindow,
502 *(xThetaValues [row]),
503 *(yRadiusValues [row]),
504 transformation);
505 }
506}
507
508void ExportFileRelations::loadXThetaYRadiusValuesForCurveRaw (const DocumentModelCoords &modelCoords,
509 const DocumentModelGeneral &modelGeneral,
510 const MainWindowModel &modelMainWindow,
511 const Points &points,
512 QVector<QString*> &xThetaValues,
513 QVector<QString*> &yRadiusValues,
514 const Transformation &transformation) const
515{
516 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::loadXThetaYRadiusValuesForCurveRaw";
517
518 FormatCoordsUnits format;
519
520 for (int pt = 0; pt < points.count(); pt++) {
521
522 const Point &point = points.at (pt);
523
524 QPointF posGraph;
525 transformation.transformScreenToRawGraph (point.posScreen(),
526 posGraph);
527
528 // Save values for this row into xThetaValues and yRadiusValues, after appropriate formatting
529 format.unformattedToFormatted (posGraph.x(),
530 posGraph.y(),
531 modelCoords,
532 modelGeneral,
533 modelMainWindow,
534 *(xThetaValues [pt]),
535 *(yRadiusValues [pt]),
536 transformation);
537 }
538}
539
540int ExportFileRelations::maxColumnSizeAllocation (const DocumentModelExportFormat &modelExport,
541 const Document &document,
542 const Transformation &transformation,
543 bool isLogXTheta,
544 bool isLogYRadius,
545 const QStringList &curvesIncluded) const
546{
547 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::maxColumnSizeAllocation";
548
549 int maxColumnSize = 0;
550
551 // The curve processing logic here is mirrored in loadXThetaYRadiusValues so the array allocations are in sync
552 for (int ic = 0; ic < curvesIncluded.count(); ic++) {
553
554 const QString curveName = curvesIncluded.at (ic);
555
556 const Curve *curve = document.curveForCurveName (curveName);
557 const Points points = curve->points ();
558
560
561 // No interpolation. Raw points
562 maxColumnSize = qMax (maxColumnSize,
563 points.count());
564
565 } else {
566
567 const LineStyle &lineStyle = document.modelCurveStyles().lineStyle(curveName);
568
569
570 // Interpolation. Points are taken approximately every every modelExport.pointsIntervalRelations
571 ExportValuesOrdinal ordinals = ordinalsAtIntervals (modelExport.pointsIntervalRelations(),
572 modelExport.pointsIntervalUnitsRelations(),
573 lineStyle.curveConnectAs(),
574 transformation,
575 isLogXTheta,
576 isLogYRadius,
577 points);
578
579 maxColumnSize = qMax (maxColumnSize,
580 ordinals.count());
581 }
582 }
583
584 return maxColumnSize;
585}
586
587ExportValuesOrdinal ExportFileRelations::ordinalsAtIntervals (double pointsIntervalRelations,
588 ExportPointsIntervalUnits pointsIntervalUnits,
589 CurveConnectAs curveConnectAs,
590 const Transformation &transformation,
591 bool isLogXTheta,
592 bool isLogYRadius,
593 const Points &points) const
594{
595 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::ordinalsAtIntervals";
596
597 if (pointsIntervalUnits == EXPORT_POINTS_INTERVAL_UNITS_GRAPH) {
598 if (curveConnectAs == CONNECT_AS_RELATION_SMOOTH) {
599
600 return ordinalsAtIntervalsSmoothGraph (pointsIntervalRelations,
601 transformation,
602 isLogXTheta,
603 isLogYRadius,
604 points);
605
606 } else {
607
608 return ordinalsAtIntervalsStraightGraph (pointsIntervalRelations,
609 transformation,
610 points);
611
612 }
613 } else {
614
615 if (curveConnectAs == CONNECT_AS_RELATION_SMOOTH) {
616
617 return ordinalsAtIntervalsSmoothScreen (pointsIntervalRelations,
618 points);
619
620 } else {
621
622 return ordinalsAtIntervalsStraightScreen (pointsIntervalRelations,
623 points);
624
625 }
626 }
627}
628
629ExportValuesOrdinal ExportFileRelations::ordinalsAtIntervalsSmoothGraph (double pointsIntervalRelations,
630 const Transformation &transformation,
631 bool isLogXTheta,
632 bool isLogYRadius,
633 const Points &points) const
634{
635 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::ordinalsAtIntervalsSmoothGraph";
636
637 ExportValuesOrdinal ordinals;
638
639 // Prevent infinite loop when there are no points or will be too many points
640 if ((pointsIntervalRelations > 0) &&
641 (points.count() > 0)) {
642
643 vector<double> t;
644 vector<SplinePair> xy;
645 ExportOrdinalsSmooth ordinalsSmooth;
646
647 ordinalsSmooth.loadSplinePairsWithTransformation (points,
648 transformation,
649 isLogXTheta,
650 isLogYRadius,
651 t,
652 xy);
653
654 ordinals = ordinalsSmooth.ordinalsAtIntervalsGraph (t,
655 xy,
656 pointsIntervalRelations);
657 }
658
659 return ordinals;
660}
661
662ExportValuesOrdinal ExportFileRelations::ordinalsAtIntervalsSmoothScreen (double pointsIntervalRelations,
663 const Points &points) const
664{
665 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::ordinalsAtIntervalsSmoothScreen"
666 << " pointCount=" << points.count();
667
668 // Results
669 ExportValuesOrdinal ordinals;
670
671 // Prevent infinite loop when there are no points or will be too many points
672 if ((pointsIntervalRelations > 0) &&
673 (points.count() > 0)) {
674
675 vector<double> t;
676 vector<SplinePair> xy;
677 ExportOrdinalsSmooth ordinalsSmooth;
678
679 ordinalsSmooth.loadSplinePairsWithoutTransformation (points,
680 t,
681 xy);
682
683 ordinals = ordinalsSmooth.ordinalsAtIntervalsGraph (t,
684 xy,
685 pointsIntervalRelations);
686 }
687
688 return ordinals;
689}
690
691ExportValuesOrdinal ExportFileRelations::ordinalsAtIntervalsStraightGraph (double pointsIntervalRelations,
692 const Transformation &transformation,
693 const Points &points) const
694{
695 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::ordinalsAtIntervalsStraightGraph";
696
697 ExportValuesOrdinal ordinals;
698
699 // Prevent infinite loop when there are no points or will be too many points
700 if ((pointsIntervalRelations > 0) &&
701 (points.count() > 0)) {
702
703 ExportOrdinalsStraight ordinalsStraight;
704
705 ordinals = ordinalsStraight.ordinalsAtIntervalsGraphWithTransformation (points,
706 transformation,
707 pointsIntervalRelations);
708 }
709
710 return ordinals;
711}
712
713ExportValuesOrdinal ExportFileRelations::ordinalsAtIntervalsStraightScreen (double pointsIntervalRelations,
714 const Points &points) const
715{
716 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::ordinalsAtIntervalsStraightScreen"
717 << " pointCount=" << points.count();
718
719 // Results
720 ExportValuesOrdinal ordinals;
721
722 // Prevent infinite loop when there are no points or will be too many points
723 if ((pointsIntervalRelations > 0) &&
724 (points.count() > 0)) {
725
726 ExportOrdinalsStraight ordinalsStraight;
727
728 ordinals = ordinalsStraight.ordinalsAtIntervalsGraphWithoutTransformation (points,
729 pointsIntervalRelations);
730 }
731
732 return ordinals;
733}
734
735void ExportFileRelations::outputXThetaYRadiusValues (const DocumentModelExportFormat &modelExportOverride,
736 const QStringList &curvesIncluded,
737 QVector<QVector<QString*> > &xThetaYRadiusValues,
738 const QString &delimiter,
739 QTextStream &str,
740 unsigned int &numWritesSoFar) const
741{
742 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::outputXThetaYRadiusValues";
743
744 // Header
745 if (modelExportOverride.header() != EXPORT_HEADER_NONE) {
746 insertLineSeparator (numWritesSoFar == 0,
747 modelExportOverride.header (),
748 str);
749 if (modelExportOverride.header() == EXPORT_HEADER_GNUPLOT) {
750 str << gnuplotComment();
751 }
752 QString delimiterForRow;
753 QStringList::const_iterator itr;
754 for (itr = curvesIncluded.begin(); itr != curvesIncluded.end(); itr++) {
755 QString curveName = *itr;
756 str << delimiterForRow << modelExportOverride.xLabel();
757 delimiterForRow = delimiter;
758 str << delimiterForRow << curveName;
759 }
760 str << "\n";
761 }
762
763 // Table body
764 for (int row = 0; row < xThetaYRadiusValues [0].count(); row++) {
765
766 QString delimiterForRow;
767 for (int col = 0; col < xThetaYRadiusValues.count(); col++) {
768
769 QString xThetaString = *(xThetaYRadiusValues [col] [row]);
770 str << delimiterForRow << wrapInDoubleQuotesIfNeeded (modelExportOverride,
771 xThetaString);
772 delimiterForRow = delimiter;
773 }
774
775 str << "\n";
776 }
777
778 ++numWritesSoFar;
779}
@ COORD_SCALE_LOG
Definition CoordScale.h:14
CurveConnectAs
@ CONNECT_AS_RELATION_STRAIGHT
@ CONNECT_AS_RELATION_SMOOTH
#define ENGAUGE_ASSERT(cond)
Drop in replacement for Q_ASSERT.
QString exportDelimiterToText(ExportDelimiter exportDelimiter, bool isGnuplotDelimiter)
const int COLUMNS_PER_CURVE
@ EXPORT_HEADER_NONE
@ EXPORT_HEADER_GNUPLOT
@ EXPORT_LAYOUT_ALL_PER_LINE
@ EXPORT_POINTS_INTERVAL_UNITS_GRAPH
@ EXPORT_POINTS_SELECTION_RELATIONS_INTERPOLATE
@ EXPORT_POINTS_SELECTION_RELATIONS_RAW
QList< double > ExportValuesOrdinal
log4cpp::Category * mainCat
Definition Logger.cpp:14
QList< Point > Points
Definition Points.h:13
LineStyle lineStyle() const
Get method for LineStyle.
const LineStyle lineStyle(const QString &curveName) const
Get method for copying one line style in one step.
CurveStyle curveStyle() const
Return the curve style.
Definition Curve.cpp:149
const Points points() const
Return a shallow copy of the Points.
Definition Curve.cpp:455
Model for DlgSettingsCoords and CmdSettingsCoords.
Model for DlgSettingsExportFormat and CmdSettingsExportFormat.
ExportHeader header() const
Get method for header.
ExportPointsSelectionRelations pointsSelectionRelations() const
Get method for point selection for relations.
double pointsIntervalRelations() const
Get method for relations interval for relations.
QString xLabel() const
Get method for x label.
ExportPointsIntervalUnits pointsIntervalUnitsRelations() const
Get method for points interval units for relations.
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:44
DocumentModelGeneral modelGeneral() const
Get method for DocumentModelGeneral.
Definition Document.cpp:735
QStringList curvesGraphsNames() const
See CurvesGraphs::curvesGraphsNames.
Definition Document.cpp:355
DocumentModelCoords modelCoords() const
Get method for DocumentModelCoords.
Definition Document.cpp:707
CurveStyles modelCurveStyles() const
Get method for CurveStyles.
Definition Document.cpp:714
const Curve * curveForCurveName(const QString &curveName) const
See CurvesGraphs::curveForCurveNames, although this also works for AXIS_CURVE_NAME.
Definition Document.cpp:341
void destroy2DArray(QVector< QVector< QString * > > &array) const
Deallocate memory for array.
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.
ExportFileRelations()
Single constructor.
void exportToFile(const DocumentModelExportFormat &modelExportOverride, const Document &document, const MainWindowModel &modelMainWindow, const Transformation &transformation, QTextStream &str, unsigned int &numWritesSoFar, bool &isOverrun) const
Export Document points according to the settings.
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...
ExportValuesOrdinal ordinalsAtIntervalsGraph(const std::vector< double > &t, const std::vector< SplinePair > &xy, double pointsInterval) const
Perform the interpolation on the arrays loaded by the other methods.
void loadSplinePairsWithoutTransformation(const Points &points, std::vector< double > &t, std::vector< SplinePair > &xy) const
Load t (=ordinal) and xy (=screen position) spline pairs, without any conversion to graph coordinates...
ExportValuesOrdinal ordinalsAtIntervalsGraphWithoutTransformation(const Points &points, double pointsInterval) const
Compute ordinals, without any conversion to graph coordinates.
ExportValuesOrdinal ordinalsAtIntervalsGraphWithTransformation(const Points &points, const Transformation &transformation, double pointsInterval) const
Compute ordinals, converting screen coordinates to graph coordinates.
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...
CurveConnectAs curveConnectAs() const
Get method for connect type.
Definition LineStyle.cpp:63
Model for DlgSettingsMainWindow.
QPointF posScreen() const
Accessor for screen position.
Definition Point.cpp:404
double ordinal(ApplyHasCheck applyHasCheck=KEEP_HAS_CHECK) const
Get method for ordinal. Skip check if copying one instance to another.
Definition Point.cpp:386
double y() const
Get method for y.
double x() const
Get method for x.
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.
#define LOG4CPP_INFO_S(logger)
Definition convenience.h:18