00001
00002
00003
00004
00005
00006
00007 #include "CallbackGatherXThetaValuesFunctions.h"
00008 #include "CurveConnectAs.h"
00009 #include "Document.h"
00010 #include "DocumentModelGeneral.h"
00011 #include "EngaugeAssert.h"
00012 #include "ExportFileFunctions.h"
00013 #include "ExportLayoutFunctions.h"
00014 #include "ExportOrdinalsSmooth.h"
00015 #include "ExportXThetaValuesMergedFunctions.h"
00016 #include "FormatCoordsUnits.h"
00017 #include "Logger.h"
00018 #include <QTextStream>
00019 #include <QVector>
00020 #include "Spline.h"
00021 #include "SplinePair.h"
00022 #include "Transformation.h"
00023 #include <vector>
00024
00025 using namespace std;
00026
00027 ExportFileFunctions::ExportFileFunctions()
00028 {
00029 }
00030
00031 void ExportFileFunctions::exportAllPerLineXThetaValuesMerged (const DocumentModelExportFormat &modelExportOverride,
00032 const Document &document,
00033 const MainWindowModel &modelMainWindow,
00034 const QStringList &curvesIncluded,
00035 const ExportValuesXOrY &xThetaValues,
00036 const QString &delimiter,
00037 const Transformation &transformation,
00038 QTextStream &str) const
00039 {
00040 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::exportAllPerLineXThetaValuesMerged";
00041
00042 int curveCount = curvesIncluded.count();
00043 int xThetaCount = xThetaValues.count();
00044 QVector<QVector<QString*> > yRadiusValues (curveCount, QVector<QString*> (xThetaCount));
00045 initializeYRadiusValues (curvesIncluded,
00046 xThetaValues,
00047 yRadiusValues);
00048 loadYRadiusValues (modelExportOverride,
00049 document,
00050 modelMainWindow,
00051 curvesIncluded,
00052 transformation,
00053 xThetaValues,
00054 yRadiusValues);
00055
00056 outputXThetaYRadiusValues (modelExportOverride,
00057 document.modelCoords(),
00058 document.modelGeneral(),
00059 modelMainWindow,
00060 curvesIncluded,
00061 xThetaValues,
00062 transformation,
00063 yRadiusValues,
00064 delimiter,
00065 str);
00066 destroy2DArray (yRadiusValues);
00067 }
00068
00069 void ExportFileFunctions::exportOnePerLineXThetaValuesMerged (const DocumentModelExportFormat &modelExportOverride,
00070 const Document &document,
00071 const MainWindowModel &modelMainWindow,
00072 const QStringList &curvesIncluded,
00073 const ExportValuesXOrY &xThetaValues,
00074 const QString &delimiter,
00075 const Transformation &transformation,
00076 QTextStream &str) const
00077 {
00078 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::exportOnePerLineXThetaValuesMerged";
00079
00080 bool isFirst = true;
00081
00082 QStringList::const_iterator itr;
00083 for (itr = curvesIncluded.begin(); itr != curvesIncluded.end(); itr++) {
00084
00085 insertLineSeparator (isFirst,
00086 modelExportOverride.header(),
00087 str);
00088
00089
00090 const int CURVE_COUNT = 1;
00091 QString curveIncluded = *itr;
00092 QStringList curvesIncluded (curveIncluded);
00093
00094 int xThetaCount = xThetaValues.count();
00095 QVector<QVector<QString*> > yRadiusValues (CURVE_COUNT, QVector<QString*> (xThetaCount));
00096 initializeYRadiusValues (curvesIncluded,
00097 xThetaValues,
00098 yRadiusValues);
00099 loadYRadiusValues (modelExportOverride,
00100 document,
00101 modelMainWindow,
00102 curvesIncluded,
00103 transformation,
00104 xThetaValues,
00105 yRadiusValues);
00106 outputXThetaYRadiusValues (modelExportOverride,
00107 document.modelCoords(),
00108 document.modelGeneral(),
00109 modelMainWindow,
00110 curvesIncluded,
00111 xThetaValues,
00112 transformation,
00113 yRadiusValues,
00114 delimiter,
00115 str);
00116 destroy2DArray (yRadiusValues);
00117 }
00118 }
00119
00120 void ExportFileFunctions::exportToFile (const DocumentModelExportFormat &modelExportOverride,
00121 const Document &document,
00122 const MainWindowModel &modelMainWindow,
00123 const Transformation &transformation,
00124 QTextStream &str) const
00125 {
00126 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::exportToFile";
00127
00128
00129 QStringList curvesIncluded = curvesToInclude (modelExportOverride,
00130 document,
00131 document.curvesGraphsNames(),
00132 CONNECT_AS_FUNCTION_SMOOTH,
00133 CONNECT_AS_FUNCTION_STRAIGHT);
00134
00135
00136 const QString delimiter = exportDelimiterToText (modelExportOverride.delimiter(),
00137 modelExportOverride.header() == EXPORT_HEADER_GNUPLOT);
00138
00139
00140 CallbackGatherXThetaValuesFunctions ftor (modelExportOverride,
00141 curvesIncluded,
00142 transformation);
00143 Functor2wRet<const QString &, const Point &, CallbackSearchReturn> ftorWithCallback = functor_ret (ftor,
00144 &CallbackGatherXThetaValuesFunctions::callback);
00145 document.iterateThroughCurvesPointsGraphs(ftorWithCallback);
00146
00147 ExportXThetaValuesMergedFunctions exportXTheta (modelExportOverride,
00148 ftor.xThetaValuesRaw(),
00149 transformation);
00150 ExportValuesXOrY xThetaValuesMerged = exportXTheta.xThetaValues ();
00151
00152
00153 if (xThetaValuesMerged.count() > 0) {
00154
00155
00156 if (modelExportOverride.layoutFunctions() == EXPORT_LAYOUT_ALL_PER_LINE) {
00157 exportAllPerLineXThetaValuesMerged (modelExportOverride,
00158 document,
00159 modelMainWindow,
00160 curvesIncluded,
00161 xThetaValuesMerged,
00162 delimiter,
00163 transformation,
00164 str);
00165 } else {
00166 exportOnePerLineXThetaValuesMerged (modelExportOverride,
00167 document,
00168 modelMainWindow,
00169 curvesIncluded,
00170 xThetaValuesMerged,
00171 delimiter,
00172 transformation,
00173 str);
00174 }
00175 }
00176 }
00177
00178 void ExportFileFunctions::initializeYRadiusValues (const QStringList &curvesIncluded,
00179 const ExportValuesXOrY &xThetaValuesMerged,
00180 QVector<QVector<QString*> > &yRadiusValues) const
00181 {
00182 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::initializeYRadiusValues";
00183
00184
00185 int curveCount = curvesIncluded.count();
00186 int xThetaCount = xThetaValuesMerged.count();
00187 for (int row = 0; row < xThetaCount; row++) {
00188 for (int col = 0; col < curveCount; col++) {
00189 yRadiusValues [col] [row] = new QString;
00190 }
00191 }
00192 }
00193
00194 double ExportFileFunctions::linearlyInterpolate (const Points &points,
00195 double xThetaValue,
00196 const Transformation &transformation) const
00197 {
00198
00199
00200
00201
00202 double yRadius = 0;
00203 QPointF posGraphBefore;
00204 bool foundIt = false;
00205 for (int ip = 0; !foundIt && (ip < points.count()); ip++) {
00206
00207 const Point &point = points.at (ip);
00208 QPointF posGraph;
00209 transformation.transformScreenToRawGraph (point.posScreen(),
00210 posGraph);
00211
00212
00213
00214
00215
00216 if (xThetaValue <= posGraph.x() && (ip > 0)) {
00217
00218 foundIt = true;
00219
00220
00221
00222
00223 double s = (xThetaValue - posGraphBefore.x()) / (posGraph.x() - posGraphBefore.x());
00224 yRadius = (1.0 -s) * posGraphBefore.y() + s * posGraph.y();
00225
00226 break;
00227 }
00228
00229 posGraphBefore = posGraph;
00230 }
00231
00232 if (!foundIt) {
00233
00234 if (points.count() > 1) {
00235
00236
00237
00238 int N = points.count();
00239 const Point &pointLast = points.at (N - 1);
00240 const Point &pointBefore = points.at (N - 2);
00241 QPointF posGraphLast;
00242 transformation.transformScreenToRawGraph (pointLast.posScreen(),
00243 posGraphLast);
00244 transformation.transformScreenToRawGraph (pointBefore.posScreen(),
00245 posGraphBefore);
00246 double s = (xThetaValue - posGraphBefore.x()) / (posGraphLast.x() - posGraphBefore.x());
00247 yRadius = (1.0 - s) * posGraphBefore.y() + s * posGraphLast.y();
00248
00249 } else if (points.count() == 1) {
00250
00251
00252 yRadius = posGraphBefore.y();
00253
00254 } else {
00255
00256 ENGAUGE_ASSERT (false);
00257
00258 }
00259 }
00260
00261 return yRadius;
00262 }
00263
00264 void ExportFileFunctions::loadYRadiusValues (const DocumentModelExportFormat &modelExportOverride,
00265 const Document &document,
00266 const MainWindowModel &modelMainWindow,
00267 const QStringList &curvesIncluded,
00268 const Transformation &transformation,
00269 const ExportValuesXOrY &xThetaValues,
00270 QVector<QVector<QString*> > &yRadiusValues) const
00271 {
00272 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValues";
00273
00274
00275 int curveCount = curvesIncluded.count();
00276 for (int col = 0; col < curveCount; col++) {
00277
00278 const QString curveName = curvesIncluded.at (col);
00279
00280 const Curve *curve = document.curveForCurveName (curveName);
00281 const Points points = curve->points ();
00282
00283 if (modelExportOverride.pointsSelectionFunctions() == EXPORT_POINTS_SELECTION_FUNCTIONS_RAW) {
00284
00285
00286 loadYRadiusValuesForCurveRaw (document.modelCoords(),
00287 document.modelGeneral(),
00288 modelMainWindow,
00289 points,
00290 xThetaValues,
00291 transformation,
00292 yRadiusValues [col]);
00293 } else {
00294
00295
00296 if (curve->curveStyle().lineStyle().curveConnectAs() == CONNECT_AS_FUNCTION_SMOOTH) {
00297
00298 loadYRadiusValuesForCurveInterpolatedSmooth (document.modelCoords(),
00299 document.modelGeneral(),
00300 modelMainWindow,
00301 points,
00302 xThetaValues,
00303 transformation,
00304 yRadiusValues [col]);
00305
00306 } else {
00307
00308 loadYRadiusValuesForCurveInterpolatedStraight (document.modelCoords(),
00309 document.modelGeneral(),
00310 modelMainWindow,
00311 points,
00312 xThetaValues,
00313 transformation,
00314 yRadiusValues [col]);
00315 }
00316 }
00317 }
00318 }
00319
00320 void ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedSmooth (const DocumentModelCoords &modelCoords,
00321 const DocumentModelGeneral &modelGeneral,
00322 const MainWindowModel &modelMainWindow,
00323 const Points &points,
00324 const ExportValuesXOrY &xThetaValues,
00325 const Transformation &transformation,
00326 QVector<QString*> &yRadiusValues) const
00327 {
00328 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedSmooth";
00329
00330
00331 vector<double> t;
00332 vector<SplinePair> xy;
00333 ExportOrdinalsSmooth ordinalsSmooth;
00334
00335 ordinalsSmooth.loadSplinePairsWithTransformation (points,
00336 transformation,
00337 t,
00338 xy);
00339
00340
00341 FormatCoordsUnits format;
00342 QString dummyXThetaOut;
00343
00344 if (points.count() == 0) {
00345
00346
00347 for (int row = 0; row < xThetaValues.count(); row++) {
00348 *(yRadiusValues [row]) = "";
00349 }
00350
00351 } else if (points.count() == 1 ||
00352 points.count() == 2) {
00353
00354
00355 for (int row = 0; row < xThetaValues.count(); row++) {
00356
00357 double xTheta = xThetaValues.at (row);
00358 double yRadius;
00359 if (points.count() == 1) {
00360 yRadius = xy.at (0).y ();
00361 } else {
00362 double x0 = xy.at (0).x ();
00363 double x1 = xy.at (1).x ();
00364 double y0 = xy.at (0).y ();
00365 double y1 = xy.at (1).y ();
00366 if (x0 == x1) {
00367
00368 yRadius = xy.at (0).y ();
00369 } else {
00370 double s = (xTheta - x0) / (x1 - x0);
00371 yRadius = (1.0 - s) * y0 + s * y1;
00372 }
00373 }
00374 format.unformattedToFormatted (xTheta,
00375 yRadius,
00376 modelCoords,
00377 modelGeneral,
00378 modelMainWindow,
00379 dummyXThetaOut,
00380 *(yRadiusValues [row]),
00381 transformation);
00382 }
00383
00384 } else {
00385
00386
00387
00388
00389
00390 const int MAX_ITERATIONS = 32;
00391
00392
00393 if (xy.size() > 0) {
00394
00395
00396 Spline spline (t,
00397 xy);
00398
00399
00400 for (int row = 0; row < xThetaValues.count(); row++) {
00401
00402 double xTheta = xThetaValues.at (row);
00403 SplinePair splinePairFound = spline.findSplinePairForFunctionX (xTheta,
00404 MAX_ITERATIONS);
00405 double yRadius = splinePairFound.y ();
00406
00407
00408 QString dummyXThetaOut;
00409 format.unformattedToFormatted (xTheta,
00410 yRadius,
00411 modelCoords,
00412 modelGeneral,
00413 modelMainWindow,
00414 dummyXThetaOut,
00415 *(yRadiusValues [row]),
00416 transformation);
00417 }
00418 }
00419 }
00420 }
00421
00422 void ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedStraight (const DocumentModelCoords &modelCoords,
00423 const DocumentModelGeneral &modelGeneral,
00424 const MainWindowModel &modelMainWindow,
00425 const Points &points,
00426 const ExportValuesXOrY &xThetaValues,
00427 const Transformation &transformation,
00428 QVector<QString*> &yRadiusValues) const
00429 {
00430 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedStraight";
00431
00432 FormatCoordsUnits format;
00433
00434
00435 for (int row = 0; row < xThetaValues.count(); row++) {
00436
00437 double xThetaValue = xThetaValues.at (row);
00438
00439 double yRadius = linearlyInterpolate (points,
00440 xThetaValue,
00441 transformation);
00442
00443
00444 QString dummyXThetaOut;
00445 format.unformattedToFormatted (xThetaValue,
00446 yRadius,
00447 modelCoords,
00448 modelGeneral,
00449 modelMainWindow,
00450 dummyXThetaOut,
00451 *(yRadiusValues [row]),
00452 transformation);
00453 }
00454 }
00455
00456 void ExportFileFunctions::loadYRadiusValuesForCurveRaw (const DocumentModelCoords &modelCoords,
00457 const DocumentModelGeneral &modelGeneral,
00458 const MainWindowModel &modelMainWindow,
00459 const Points &points,
00460 const ExportValuesXOrY &xThetaValues,
00461 const Transformation &transformation,
00462 QVector<QString*> &yRadiusValues) const
00463 {
00464 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValuesForCurveRaw";
00465
00466 FormatCoordsUnits format;
00467
00468
00469
00470 for (int pt = 0; pt < points.count(); pt++) {
00471
00472 const Point &point = points.at (pt);
00473
00474 QPointF posGraph;
00475 transformation.transformScreenToRawGraph (point.posScreen(),
00476 posGraph);
00477
00478
00479
00480 double closestSeparation = 0.0;
00481 int rowClosest = 0;
00482 for (int row = 0; row < xThetaValues.count(); row++) {
00483
00484 double xThetaValue = xThetaValues.at (row);
00485
00486 double separation = qAbs (posGraph.x() - xThetaValue);
00487
00488 if ((row == 0) ||
00489 (separation < closestSeparation)) {
00490
00491 closestSeparation = separation;
00492 rowClosest = row;
00493
00494 }
00495 }
00496
00497
00498 QString dummyXThetaOut;
00499 format.unformattedToFormatted (posGraph.x(),
00500 posGraph.y(),
00501 modelCoords,
00502 modelGeneral,
00503 modelMainWindow,
00504 dummyXThetaOut,
00505 *(yRadiusValues [rowClosest]),
00506 transformation);
00507 }
00508 }
00509
00510 void ExportFileFunctions::outputXThetaYRadiusValues (const DocumentModelExportFormat &modelExportOverride,
00511 const DocumentModelCoords &modelCoords,
00512 const DocumentModelGeneral &modelGeneral,
00513 const MainWindowModel &modelMainWindow,
00514 const QStringList &curvesIncluded,
00515 const ExportValuesXOrY &xThetaValuesMerged,
00516 const Transformation &transformation,
00517 QVector<QVector<QString*> > &yRadiusValues,
00518 const QString &delimiter,
00519 QTextStream &str) const
00520 {
00521 LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::outputXThetaYRadiusValues";
00522
00523
00524 if (modelExportOverride.header() != EXPORT_HEADER_NONE) {
00525 if (modelExportOverride.header() == EXPORT_HEADER_GNUPLOT) {
00526 str << curveSeparator (str.string());
00527 str << gnuplotComment();
00528 }
00529 str << modelExportOverride.xLabel();
00530 QStringList::const_iterator itrHeader;
00531 for (itrHeader = curvesIncluded.begin(); itrHeader != curvesIncluded.end(); itrHeader++) {
00532 QString curveName = *itrHeader;
00533 str << delimiter << curveName;
00534 }
00535 str << "\n";
00536 }
00537
00538 FormatCoordsUnits format;
00539 const double DUMMY_Y_RADIUS = 1.0;
00540
00541 for (int row = 0; row < xThetaValuesMerged.count(); row++) {
00542
00543 if (rowHasAtLeastOneYRadiusEntry (yRadiusValues,
00544 row)) {
00545
00546 double xTheta = xThetaValuesMerged.at (row);
00547
00548
00549 QString xThetaString, yRadiusString;
00550 format.unformattedToFormatted (xTheta,
00551 DUMMY_Y_RADIUS,
00552 modelCoords,
00553 modelGeneral,
00554 modelMainWindow,
00555 xThetaString,
00556 yRadiusString,
00557 transformation);
00558 str << xThetaString;
00559
00560 for (int col = 0; col < yRadiusValues.count(); col++) {
00561
00562 str << delimiter << *(yRadiusValues [col] [row]);
00563 }
00564
00565 str << "\n";
00566 }
00567 }
00568 }
00569
00570 bool ExportFileFunctions::rowHasAtLeastOneYRadiusEntry (const QVector<QVector<QString*> > &yRadiusValues,
00571 int row) const
00572 {
00573 bool hasEntry = false;
00574
00575 for (int col = 0; col < yRadiusValues.count(); col++) {
00576
00577 QString entry = *(yRadiusValues [col] [row]);
00578 if (!entry.isEmpty()) {
00579
00580 hasEntry = true;
00581 break;
00582
00583 }
00584 }
00585
00586 return hasEntry;
00587 }