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