Engauge Digitizer  2
ExportFileRelations.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 "CurveConnectAs.h"
8 #include "Document.h"
9 #include "DocumentModelGeneral.h"
10 #include "EngaugeAssert.h"
11 #include "ExportFileRelations.h"
12 #include "ExportLayoutFunctions.h"
13 #include "ExportOrdinalsSmooth.h"
14 #include "ExportOrdinalsStraight.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 
26 using namespace std;
27 
28 const int COLUMNS_PER_CURVE = 2;
29 
31 {
32 }
33 
34 void 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 
57  if (modelExportOverride.pointsSelectionRelations() == EXPORT_POINTS_SELECTION_RELATIONS_INTERPOLATE) {
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 
88 void 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 
158 void 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 
192 void 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) const
229 {
230  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::exportToFile";
231 
232  // Log coordinates must be temporarily transformed to linear coordinates
233  bool isLogXTheta = (document.modelCoords().coordScaleXTheta() == COORD_SCALE_LOG);
234  bool isLogYRadius = (document.modelCoords().coordScaleYRadius() == COORD_SCALE_LOG);
235 
236  // Identify curves to be included
237  QStringList curvesIncluded = curvesToInclude (modelExportOverride,
238  document,
239  document.curvesGraphsNames(),
240  CONNECT_AS_RELATION_SMOOTH,
241  CONNECT_AS_RELATION_STRAIGHT);
242 
243  // Delimiter
244  const QString delimiter = exportDelimiterToText (modelExportOverride.delimiter(),
245  modelExportOverride.header() == EXPORT_HEADER_GNUPLOT);
246 
247  // Export in one of two layouts
248  if (modelExportOverride.layoutFunctions() == EXPORT_LAYOUT_ALL_PER_LINE) {
249  exportAllPerLineXThetaValuesMerged (modelExportOverride,
250  document,
251  modelMainWindow,
252  curvesIncluded,
253  delimiter,
254  transformation,
255  isLogXTheta,
256  isLogYRadius,
257  str,
258  numWritesSoFar);
259  } else {
260  exportOnePerLineXThetaValuesMerged (modelExportOverride,
261  document,
262  modelMainWindow,
263  curvesIncluded,
264  delimiter,
265  transformation,
266  isLogXTheta,
267  isLogYRadius,
268  str,
269  numWritesSoFar);
270  }
271 }
272 
273 void ExportFileRelations::initializeXThetaYRadiusValues (const QStringList &curvesIncluded,
274  QVector<QVector<QString*> > &xThetaYRadiusValues) const
275 {
276  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::initializeXThetaYRadiusValues";
277 
278  // Initialize every entry with empty string
279  int curveCount = curvesIncluded.count();
280  int xThetaCount = xThetaYRadiusValues [0].count();
281  for (int row = 0; row < xThetaCount; row++) {
282  for (int col = 0; col < COLUMNS_PER_CURVE * curveCount; col++) {
283  xThetaYRadiusValues [col] [row] = new QString;
284  }
285  }
286 }
287 
288 QPointF ExportFileRelations::linearlyInterpolate (const Points &points,
289  double ordinal,
290  const Transformation &transformation) const
291 {
292  // LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::linearlyInterpolate";
293 
294  double xTheta = 0, yRadius = 0;
295  double ordinalBefore = 0; // Not set until ip=1
296  QPointF posGraphBefore; // Not set until ip=1
297  bool foundIt = false;
298  for (int ip = 0; ip < points.count(); ip++) {
299 
300  const Point &point = points.at (ip);
301  QPointF posGraph;
302  transformation.transformScreenToRawGraph (point.posScreen(),
303  posGraph);
304 
305  if (ordinal <= point.ordinal()) {
306 
307  foundIt = true;
308  if (ip == 0) {
309 
310  // Use first point
311  xTheta = posGraph.x();
312  yRadius = posGraph.y();
313 
314  } else {
315 
316  // Between posGraphBefore and posGraph. Note that if posGraph.x()=posGraphBefore.x() then
317  // previous iteration of loop would have been used for interpolation, and then the loop was exited
318  double s = (ordinal - ordinalBefore) / (point.ordinal() - ordinalBefore);
319  xTheta = (1.0 - s) * posGraphBefore.x() + s * posGraph.x();
320  yRadius = (1.0 - s) * posGraphBefore.y() + s * posGraph.y();
321  }
322 
323  break;
324  }
325 
326  ordinalBefore = point.ordinal();
327  posGraphBefore = posGraph;
328  }
329 
330  if (!foundIt) {
331 
332  // Use last point
333  xTheta = posGraphBefore.x();
334  yRadius = posGraphBefore.y();
335 
336  }
337 
338  return QPointF (xTheta,
339  yRadius);
340 }
341 
342 void ExportFileRelations::loadXThetaYRadiusValues (const DocumentModelExportFormat &modelExportOverride,
343  const Document &document,
344  const MainWindowModel &modelMainWindow,
345  const QStringList &curvesIncluded,
346  const Transformation &transformation,
347  bool isLogXTheta,
348  bool isLogYRadius,
349  QVector<QVector<QString*> > &xThetaYRadiusValues) const
350 {
351  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::loadXThetaYRadiusValues";
352 
353  // The curve processing logic here is mirrored in maxColumnSizeAllocation so the array allocations are in sync
354  for (int ic = 0; ic < curvesIncluded.count(); ic++) {
355 
356  int colXTheta = 2 * ic;
357  int colYRadius = 2 * ic + 1;
358 
359  const QString curveName = curvesIncluded.at (ic);
360 
361  const Curve *curve = document.curveForCurveName (curveName);
362  const Points points = curve->points ();
363 
364  if (modelExportOverride.pointsSelectionRelations() == EXPORT_POINTS_SELECTION_RELATIONS_RAW) {
365 
366  // No interpolation. Raw points
367  loadXThetaYRadiusValuesForCurveRaw (document.modelCoords(),
368  document.modelGeneral(),
369  modelMainWindow,
370  points,
371  xThetaYRadiusValues [colXTheta],
372  xThetaYRadiusValues [colYRadius],
373  transformation);
374  } else {
375 
376  const LineStyle &lineStyle = document.modelCurveStyles().lineStyle(curveName);
377 
378  // Interpolation. Points are taken approximately every every modelExport.pointsIntervalRelations
379  ExportValuesOrdinal ordinals = ordinalsAtIntervals (modelExportOverride.pointsIntervalRelations(),
380  modelExportOverride.pointsIntervalUnitsRelations(),
381  lineStyle.curveConnectAs(),
382  transformation,
383  isLogXTheta,
384  isLogYRadius,
385  points);
386 
387  if (curve->curveStyle().lineStyle().curveConnectAs() == CONNECT_AS_RELATION_SMOOTH) {
388 
389  loadXThetaYRadiusValuesForCurveInterpolatedSmooth (document.modelCoords(),
390  document.modelGeneral(),
391  modelMainWindow,
392  points,
393  ordinals,
394  xThetaYRadiusValues [colXTheta],
395  xThetaYRadiusValues [colYRadius],
396  transformation,
397  isLogXTheta,
398  isLogYRadius);
399 
400  } else {
401 
402  loadXThetaYRadiusValuesForCurveInterpolatedStraight (document.modelCoords(),
403  document.modelGeneral(),
404  modelMainWindow,
405  points,
406  ordinals,
407  xThetaYRadiusValues [colXTheta],
408  xThetaYRadiusValues [colYRadius],
409  transformation);
410  }
411  }
412  }
413 }
414 
415 void ExportFileRelations::loadXThetaYRadiusValuesForCurveInterpolatedSmooth (const DocumentModelCoords &modelCoords,
416  const DocumentModelGeneral &modelGeneral,
417  const MainWindowModel &modelMainWindow,
418  const Points &points,
419  const ExportValuesOrdinal &ordinals,
420  QVector<QString*> &xThetaValues,
421  QVector<QString*> &yRadiusValues,
422  const Transformation &transformation,
423  bool isLogXTheta,
424  bool isLogYRadius) const
425 {
426  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::loadXThetaYRadiusValuesForCurveInterpolatedSmooth";
427 
428  vector<double> t;
429  vector<SplinePair> xy;
430  ExportOrdinalsSmooth ordinalsSmooth;
431 
432  ordinalsSmooth.loadSplinePairsWithTransformation (points,
433  transformation,
434  isLogXTheta,
435  isLogYRadius,
436  t,
437  xy);
438 
439  // Spline class requires at least one point
440  if (xy.size() > 0) {
441 
442  // Fit a spline
443  Spline spline (t,
444  xy);
445 
446  FormatCoordsUnits format;
447 
448  // Extract the points
449  for (int row = 0; row < ordinals.count(); row++) {
450 
451  double ordinal = ordinals.at (row);
452  SplinePair splinePairFound = spline.interpolateCoeff(ordinal);
453  double xTheta = splinePairFound.x ();
454  double yRadius = splinePairFound.y ();
455 
456  // Save values for this row into xThetaValues and yRadiusValues, after appropriate formatting
457  format.unformattedToFormatted (xTheta,
458  yRadius,
459  modelCoords,
460  modelGeneral,
461  modelMainWindow,
462  *(xThetaValues [row]),
463  *(yRadiusValues [row]),
464  transformation);
465  }
466  }
467 }
468 
469 void ExportFileRelations::loadXThetaYRadiusValuesForCurveInterpolatedStraight (const DocumentModelCoords &modelCoords,
470  const DocumentModelGeneral &modelGeneral,
471  const MainWindowModel &modelMainWindow,
472  const Points &points,
473  const ExportValuesOrdinal &ordinals,
474  QVector<QString*> &xThetaValues,
475  QVector<QString*> &yRadiusValues,
476  const Transformation &transformation) const
477 {
478  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::loadXThetaYRadiusValuesForCurveInterpolatedStraight";
479 
480  FormatCoordsUnits format;
481 
482  // Get value at desired points
483  for (int row = 0; row < ordinals.count(); row++) {
484 
485  double ordinal = ordinals.at (row);
486 
487  QPointF pointInterpolated = linearlyInterpolate (points,
488  ordinal,
489  transformation);
490 
491  // Save values for this row into xThetaValues and yRadiusValues, after appropriate formatting
492  format.unformattedToFormatted (pointInterpolated.x(),
493  pointInterpolated.y(),
494  modelCoords,
495  modelGeneral,
496  modelMainWindow,
497  *(xThetaValues [row]),
498  *(yRadiusValues [row]),
499  transformation);
500  }
501 }
502 
503 void ExportFileRelations::loadXThetaYRadiusValuesForCurveRaw (const DocumentModelCoords &modelCoords,
504  const DocumentModelGeneral &modelGeneral,
505  const MainWindowModel &modelMainWindow,
506  const Points &points,
507  QVector<QString*> &xThetaValues,
508  QVector<QString*> &yRadiusValues,
509  const Transformation &transformation) const
510 {
511  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::loadXThetaYRadiusValuesForCurveRaw";
512 
513  FormatCoordsUnits format;
514 
515  for (int pt = 0; pt < points.count(); pt++) {
516 
517  const Point &point = points.at (pt);
518 
519  QPointF posGraph;
520  transformation.transformScreenToRawGraph (point.posScreen(),
521  posGraph);
522 
523  // Save values for this row into xThetaValues and yRadiusValues, after appropriate formatting
524  format.unformattedToFormatted (posGraph.x(),
525  posGraph.y(),
526  modelCoords,
527  modelGeneral,
528  modelMainWindow,
529  *(xThetaValues [pt]),
530  *(yRadiusValues [pt]),
531  transformation);
532  }
533 }
534 
535 int ExportFileRelations::maxColumnSizeAllocation (const DocumentModelExportFormat &modelExport,
536  const Document &document,
537  const Transformation &transformation,
538  bool isLogXTheta,
539  bool isLogYRadius,
540  const QStringList &curvesIncluded) const
541 {
542  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::maxColumnSizeAllocation";
543 
544  int maxColumnSize = 0;
545 
546  // The curve processing logic here is mirrored in loadXThetaYRadiusValues so the array allocations are in sync
547  for (int ic = 0; ic < curvesIncluded.count(); ic++) {
548 
549  const QString curveName = curvesIncluded.at (ic);
550 
551  const Curve *curve = document.curveForCurveName (curveName);
552  const Points points = curve->points ();
553 
554  if (modelExport.pointsSelectionRelations() == EXPORT_POINTS_SELECTION_RELATIONS_RAW) {
555 
556  // No interpolation. Raw points
557  maxColumnSize = qMax (maxColumnSize,
558  points.count());
559 
560  } else {
561 
562  const LineStyle &lineStyle = document.modelCurveStyles().lineStyle(curveName);
563 
564 
565  // Interpolation. Points are taken approximately every every modelExport.pointsIntervalRelations
566  ExportValuesOrdinal ordinals = ordinalsAtIntervals (modelExport.pointsIntervalRelations(),
567  modelExport.pointsIntervalUnitsRelations(),
568  lineStyle.curveConnectAs(),
569  transformation,
570  isLogXTheta,
571  isLogYRadius,
572  points);
573 
574  maxColumnSize = qMax (maxColumnSize,
575  ordinals.count());
576  }
577  }
578 
579  return maxColumnSize;
580 }
581 
582 ExportValuesOrdinal ExportFileRelations::ordinalsAtIntervals (double pointsIntervalRelations,
583  ExportPointsIntervalUnits pointsIntervalUnits,
584  CurveConnectAs curveConnectAs,
585  const Transformation &transformation,
586  bool isLogXTheta,
587  bool isLogYRadius,
588  const Points &points) const
589 {
590  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::ordinalsAtIntervals";
591 
592  if (pointsIntervalUnits == EXPORT_POINTS_INTERVAL_UNITS_GRAPH) {
593  if (curveConnectAs == CONNECT_AS_RELATION_SMOOTH) {
594 
595  return ordinalsAtIntervalsSmoothGraph (pointsIntervalRelations,
596  transformation,
597  isLogXTheta,
598  isLogYRadius,
599  points);
600 
601  } else {
602 
603  return ordinalsAtIntervalsStraightGraph (pointsIntervalRelations,
604  transformation,
605  points);
606 
607  }
608  } else {
609 
610  if (curveConnectAs == CONNECT_AS_RELATION_SMOOTH) {
611 
612  return ordinalsAtIntervalsSmoothScreen (pointsIntervalRelations,
613  points);
614 
615  } else {
616 
617  return ordinalsAtIntervalsStraightScreen (pointsIntervalRelations,
618  points);
619 
620  }
621  }
622 }
623 
624 ExportValuesOrdinal ExportFileRelations::ordinalsAtIntervalsSmoothGraph (double pointsIntervalRelations,
625  const Transformation &transformation,
626  bool isLogXTheta,
627  bool isLogYRadius,
628  const Points &points) const
629 {
630  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::ordinalsAtIntervalsSmoothGraph";
631 
632  ExportValuesOrdinal ordinals;
633 
634  // Prevent infinite loop when there are no points or will be too many points
635  if ((pointsIntervalRelations > 0) &&
636  (points.count() > 0)) {
637 
638  vector<double> t;
639  vector<SplinePair> xy;
640  ExportOrdinalsSmooth ordinalsSmooth;
641 
642  ordinalsSmooth.loadSplinePairsWithTransformation (points,
643  transformation,
644  isLogXTheta,
645  isLogYRadius,
646  t,
647  xy);
648 
649  ordinals = ordinalsSmooth.ordinalsAtIntervalsGraph (t,
650  xy,
651  pointsIntervalRelations);
652  }
653 
654  return ordinals;
655 }
656 
657 ExportValuesOrdinal ExportFileRelations::ordinalsAtIntervalsSmoothScreen (double pointsIntervalRelations,
658  const Points &points) const
659 {
660  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::ordinalsAtIntervalsSmoothScreen"
661  << " pointCount=" << points.count();
662 
663  // Results
664  ExportValuesOrdinal ordinals;
665 
666  // Prevent infinite loop when there are no points or will be too many points
667  if ((pointsIntervalRelations > 0) &&
668  (points.count() > 0)) {
669 
670  vector<double> t;
671  vector<SplinePair> xy;
672  ExportOrdinalsSmooth ordinalsSmooth;
673 
674  ordinalsSmooth.loadSplinePairsWithoutTransformation (points,
675  t,
676  xy);
677 
678  ordinals = ordinalsSmooth.ordinalsAtIntervalsGraph (t,
679  xy,
680  pointsIntervalRelations);
681  }
682 
683  return ordinals;
684 }
685 
686 ExportValuesOrdinal ExportFileRelations::ordinalsAtIntervalsStraightGraph (double pointsIntervalRelations,
687  const Transformation &transformation,
688  const Points &points) const
689 {
690  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::ordinalsAtIntervalsStraightGraph";
691 
692  ExportValuesOrdinal ordinals;
693 
694  // Prevent infinite loop when there are no points or will be too many points
695  if ((pointsIntervalRelations > 0) &&
696  (points.count() > 0)) {
697 
698  ExportOrdinalsStraight ordinalsStraight;
699 
700  ordinals = ordinalsStraight.ordinalsAtIntervalsGraphWithTransformation (points,
701  transformation,
702  pointsIntervalRelations);
703  }
704 
705  return ordinals;
706 }
707 
708 ExportValuesOrdinal ExportFileRelations::ordinalsAtIntervalsStraightScreen (double pointsIntervalRelations,
709  const Points &points) const
710 {
711  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::ordinalsAtIntervalsStraightScreen"
712  << " pointCount=" << points.count();
713 
714  // Results
715  ExportValuesOrdinal ordinals;
716 
717  // Prevent infinite loop when there are no points or will be too many points
718  if ((pointsIntervalRelations > 0) &&
719  (points.count() > 0)) {
720 
721  ExportOrdinalsStraight ordinalsStraight;
722 
723  ordinals = ordinalsStraight.ordinalsAtIntervalsGraphWithoutTransformation (points,
724  pointsIntervalRelations);
725  }
726 
727  return ordinals;
728 }
729 
730 void ExportFileRelations::outputXThetaYRadiusValues (const DocumentModelExportFormat &modelExportOverride,
731  const QStringList &curvesIncluded,
732  QVector<QVector<QString*> > &xThetaYRadiusValues,
733  const QString &delimiter,
734  QTextStream &str,
735  unsigned int &numWritesSoFar) const
736 {
737  LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::outputXThetaYRadiusValues";
738 
739  // Header
740  if (modelExportOverride.header() != EXPORT_HEADER_NONE) {
741  insertLineSeparator (numWritesSoFar == 0,
742  modelExportOverride.header (),
743  str);
744  if (modelExportOverride.header() == EXPORT_HEADER_GNUPLOT) {
745  str << gnuplotComment();
746  }
747  QString delimiterForRow;
748  QStringList::const_iterator itr;
749  for (itr = curvesIncluded.begin(); itr != curvesIncluded.end(); itr++) {
750  QString curveName = *itr;
751  str << delimiterForRow << modelExportOverride.xLabel();
752  delimiterForRow = delimiter;
753  str << delimiterForRow << curveName;
754  }
755  str << "\n";
756  }
757 
758  // Table body
759  for (int row = 0; row < xThetaYRadiusValues [0].count(); row++) {
760 
761  QString delimiterForRow;
762  for (int col = 0; col < xThetaYRadiusValues.count(); col++) {
763 
764  QString xThetaString = *(xThetaYRadiusValues [col] [row]);
765  str << delimiterForRow << wrapInDoubleQuotesIfNeeded (modelExportOverride,
766  xThetaString);
767  delimiterForRow = delimiter;
768  }
769 
770  str << "\n";
771  }
772 
773  ++numWritesSoFar;
774 }
Model for DlgSettingsGeneral and CmdSettingsGeneral.
CurveConnectAs curveConnectAs() const
Get method for connect type.
Definition: LineStyle.cpp:63
Cubic interpolation given independent and dependent value vectors.
Definition: Spline.h:21
ExportValuesOrdinal ordinalsAtIntervalsGraphWithTransformation(const Points &points, const Transformation &transformation, double pointsInterval) const
Compute ordinals, converting screen coordinates to graph coordinates.
SplinePair interpolateCoeff(double t) const
Return interpolated y for specified x.
Definition: Spline.cpp:166
double y() const
Get method for y.
Definition: SplinePair.cpp:71
Model for DlgSettingsExportFormat and CmdSettingsExportFormat.
ExportPointsSelectionRelations pointsSelectionRelations() const
Get method for point selection for relations.
const Curve * curveForCurveName(const QString &curveName) const
See CurvesGraphs::curveForCurveNames, although this also works for AXIS_CURVE_NAME.
Definition: Document.cpp:332
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
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.
double ordinal(ApplyHasCheck applyHasCheck=KEEP_HAS_CHECK) const
Get method for ordinal. Skip check if copying one instance to another.
Definition: Point.cpp:374
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.
const LineStyle lineStyle(const QString &curveName) const
Get method for copying one line style in one step.
Definition: CurveStyles.cpp:97
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.
ExportPointsIntervalUnits pointsIntervalUnitsRelations() const
Get method for points interval units for relations.
ExportDelimiter delimiter() const
Get method for delimiter.
Model for DlgSettingsCoords and CmdSettingsCoords.
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.
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
Details for a specific Line.
Definition: LineStyle.h:19
Highest-level wrapper around other Formats classes.
Utility class to interpolate points spaced evenly along a piecewise defined curve with line segments ...
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.
double pointsIntervalRelations() const
Get method for relations interval for relations.
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.
CurveStyle curveStyle() const
Return the curve style.
Definition: Curve.cpp:148
ExportFileRelations()
Single constructor.
CurveStyles modelCurveStyles() const
Get method for CurveStyles.
Definition: Document.cpp:696
double x() const
Get method for x.
Definition: SplinePair.cpp:66
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
ExportValuesOrdinal ordinalsAtIntervalsGraphWithoutTransformation(const Points &points, double pointsInterval) const
Compute ordinals, without any conversion to graph coordinates.
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...