void ExportFileRelations::loadXThetaYRadiusValuesForCurveInterpolatedStraight (const DocumentModelCoords &modelCoords, const DocumentModelGeneral &modelGeneral, const MainWindowModel &modelMainWindow, const Points &points, const ExportValuesOrdinal &ordinals, QVector<QString*> &xThetaValues, QVector<QString*> &yRadiusValues, const Transformation &transformation) const { LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::loadXThetaYRadiusValuesForCurveInterpolatedStraight"; FormatCoordsUnits format; // Get value at desired points for (int row = 0; row < ordinals.count(); row++) { double ordinal = ordinals.at (row); QPointF pointInterpolated = linearlyInterpolate (points, ordinal, transformation); // Save values for this row into xThetaValues and yRadiusValues, after appropriate formatting format.unformattedToFormatted (pointInterpolated.x(), pointInterpolated.y(), modelCoords, modelGeneral, modelMainWindow, *(xThetaValues [row]), *(yRadiusValues [row]), transformation); } }
void ExportFileRelations::loadXThetaYRadiusValuesForCurveRaw (const DocumentModelCoords &modelCoords, const DocumentModelGeneral &modelGeneral, const MainWindowModel &modelMainWindow, const Points &points, QVector<QString*> &xThetaValues, QVector<QString*> &yRadiusValues, const Transformation &transformation) const { LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::loadXThetaYRadiusValuesForCurveRaw"; FormatCoordsUnits format; for (int pt = 0; pt < points.count(); pt++) { const Point &point = points.at (pt); QPointF posGraph; transformation.transformScreenToRawGraph (point.posScreen(), posGraph); // Save values for this row into xThetaValues and yRadiusValues, after appropriate formatting format.unformattedToFormatted (posGraph.x(), posGraph.y(), modelCoords, modelGeneral, modelMainWindow, *(xThetaValues [pt]), *(yRadiusValues [pt]), transformation); } }
void ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedStraight (const DocumentModelCoords &modelCoords, const MainWindowModel &modelMainWindow, const Points &points, const ExportValuesXOrY &xThetaValues, const Transformation &transformation, QVector<QString*> &yRadiusValues) const { LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedStraight"; FormatCoordsUnits format; // Get value at desired points for (int row = 0; row < xThetaValues.count(); row++) { double xThetaValue = xThetaValues.at (row); double yRadius = linearlyInterpolate (points, xThetaValue, transformation); // Save y/radius value for this row into yRadiusValues, after appropriate formatting QString dummyXThetaOut; format.unformattedToFormatted (xThetaValue, yRadius, modelCoords, modelMainWindow, dummyXThetaOut, *(yRadiusValues [row]), transformation); } }
void ExportFileFunctions::outputXThetaYRadiusValues (const DocumentModelExportFormat &modelExportOverride, const DocumentModelCoords &modelCoords, const MainWindowModel &modelMainWindow, const QStringList &curvesIncluded, const ExportValuesXOrY &xThetaValuesMerged, const Transformation &transformation, QVector<QVector<QString*> > &yRadiusValues, const QString &delimiter, QTextStream &str) const { LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::outputXThetaYRadiusValues"; // Header if (modelExportOverride.header() != EXPORT_HEADER_NONE) { if (modelExportOverride.header() == EXPORT_HEADER_GNUPLOT) { str << curveSeparator (str.string()); str << gnuplotComment(); } str << modelExportOverride.xLabel(); QStringList::const_iterator itrHeader; for (itrHeader = curvesIncluded.begin(); itrHeader != curvesIncluded.end(); itrHeader++) { QString curveName = *itrHeader; str << delimiter << curveName; } str << "\n"; } FormatCoordsUnits format; const double DUMMY_Y_RADIUS = 1.0; for (int row = 0; row < xThetaValuesMerged.count(); row++) { if (rowHasAtLeastOneYRadiusEntry (yRadiusValues, row)) { double xTheta = xThetaValuesMerged.at (row); // Output x/theta value for this row QString xThetaString, yRadiusString; format.unformattedToFormatted (xTheta, DUMMY_Y_RADIUS, modelCoords, modelMainWindow, xThetaString, yRadiusString, transformation); str << xThetaString; for (int col = 0; col < yRadiusValues.count(); col++) { str << delimiter << *(yRadiusValues [col] [row]); } str << "\n"; } } }
void ExportFileFunctions::loadYRadiusValuesForCurveRaw (const DocumentModelCoords &modelCoords, const MainWindowModel &modelMainWindow, const Points &points, const ExportValuesXOrY &xThetaValues, const Transformation &transformation, QVector<QString*> &yRadiusValues) const { LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValuesForCurveRaw"; FormatCoordsUnits format; // Since the curve points may be a subset of xThetaValues (in which case the non-applicable xThetaValues will have // blanks for the yRadiusValues), we iterate over the smaller set for (int pt = 0; pt < points.count(); pt++) { const Point &point = points.at (pt); QPointF posGraph; transformation.transformScreenToRawGraph (point.posScreen(), posGraph); // Find the closest point in xThetaValues. This is probably an N-squared algorithm, which is less than optimial, // but the delay should be insignificant with normal-sized export files double closestSeparation = 0.0; int rowClosest = 0; for (int row = 0; row < xThetaValues.count(); row++) { double xThetaValue = xThetaValues.at (row); double separation = qAbs (posGraph.x() - xThetaValue); if ((row == 0) || (separation < closestSeparation)) { closestSeparation = separation; rowClosest = row; } } // Save y/radius value for this row into yRadiusValues, after appropriate formatting QString dummyXThetaOut; format.unformattedToFormatted (posGraph.x(), posGraph.y(), modelCoords, modelMainWindow, dummyXThetaOut, *(yRadiusValues [rowClosest]), transformation); } }
void ExportFileRelations::loadXThetaYRadiusValuesForCurveInterpolatedSmooth (const DocumentModelCoords &modelCoords, const DocumentModelGeneral &modelGeneral, const MainWindowModel &modelMainWindow, const Points &points, const ExportValuesOrdinal &ordinals, QVector<QString*> &xThetaValues, QVector<QString*> &yRadiusValues, const Transformation &transformation) const { LOG4CPP_INFO_S ((*mainCat)) << "ExportFileRelations::loadXThetaYRadiusValuesForCurveInterpolatedSmooth"; vector<double> t; vector<SplinePair> xy; ExportOrdinalsSmooth ordinalsSmooth; ordinalsSmooth.loadSplinePairsWithTransformation (points, transformation, t, xy); // Spline class requires at least one point if (xy.size() > 0) { // Fit a spline Spline spline (t, xy); FormatCoordsUnits format; // Extract the points for (int row = 0; row < ordinals.count(); row++) { double ordinal = ordinals.at (row); SplinePair splinePairFound = spline.interpolateCoeff(ordinal); double xTheta = splinePairFound.x (); double yRadius = splinePairFound.y (); // Save values for this row into xThetaValues and yRadiusValues, after appropriate formatting format.unformattedToFormatted (xTheta, yRadius, modelCoords, modelGeneral, modelMainWindow, *(xThetaValues [row]), *(yRadiusValues [row]), transformation); } } }
double DlgEditScale::scaleLength () const { double xTheta, yRadius; const QString DUMMY_Y ("0"); FormatCoordsUnits format; // Format conversion is done using x coordinate. Y coordinate is given a dummy value and the result is ignored format.formattedToUnformatted (m_editScaleLength->text(), DUMMY_Y, m_modelCoords, m_modelMainWindow, xTheta, yRadius); return xTheta; }
void DlgEditPointGraph::posGraph (bool &isX, double &x, bool &isY, double &y) const { FormatCoordsUnits format; // Use zero for any empty coordinate QString xTextNotEmpty = QString ("%1").arg (m_editGraphX->text().isEmpty () ? "0" : m_editGraphX->text()); QString yTextNotEmpty = QString ("%1").arg (m_editGraphY->text().isEmpty () ? "0" : m_editGraphY->text()); format.formattedToUnformatted (xTextNotEmpty, yTextNotEmpty, m_modelCoords, m_modelMainWindow, x, y); isX = !m_editGraphX->text().isEmpty(); isY = !m_editGraphY->text().isEmpty(); }
void DlgEditPointGraph::initializeGraphCoordinates (const double *xInitialValue, const double *yInitialValue, const Transformation &transformation) { LOG4CPP_INFO_S ((*mainCat)) << "DlgEditPointGraph::initializeGraphCoordinates"; QString xTheta, yRadius; if ((xInitialValue != 0) && (yInitialValue != 0)) { FormatCoordsUnits format; format.unformattedToFormatted (*xInitialValue, *yInitialValue, m_modelCoords, m_modelGeneral, m_modelMainWindow, xTheta, yRadius, transformation); } m_editGraphX->setText (xTheta); m_editGraphY->setText (yRadius); }
void ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedSmooth (const DocumentModelCoords &modelCoords, const MainWindowModel &modelMainWindow, const Points &points, const ExportValuesXOrY &xThetaValues, const Transformation &transformation, QVector<QString*> &yRadiusValues) const { LOG4CPP_INFO_S ((*mainCat)) << "ExportFileFunctions::loadYRadiusValuesForCurveInterpolatedSmooth"; // Convert screen coordinates to graph coordinates, in vectors suitable for spline fitting vector<double> t; vector<SplinePair> xy; ExportOrdinalsSmooth ordinalsSmooth; ordinalsSmooth.loadSplinePairsWithTransformation (points, transformation, t, xy); // Formatting FormatCoordsUnits format; QString dummyXThetaOut; if (points.count() == 0) { // Since there are no values, leave the field empty for (int row = 0; row < xThetaValues.count(); row++) { *(yRadiusValues [row]) = ""; } } else if (points.count() == 1 || points.count() == 2) { // Apply the single value everywhere (N=1) or do linear interpolation (N=2) for (int row = 0; row < xThetaValues.count(); row++) { double xTheta = xThetaValues.at (row); double yRadius; if (points.count() == 1) { yRadius = xy.at (0).y (); } else { double x0 = xy.at (0).x (); double x1 = xy.at (1).x (); double y0 = xy.at (0).y (); double y1 = xy.at (1).y (); if (x0 == x1) { // Cannot do linear interpolation using two points at the same x value yRadius = xy.at (0).y (); } else { double s = (xTheta - x0) / (x1 - x0); yRadius = (1.0 - s) * y0 + s * y1; } } format.unformattedToFormatted (xTheta, yRadius, modelCoords, modelMainWindow, dummyXThetaOut, *(yRadiusValues [row]), transformation); } } else { // Iteration accuracy versus number of iterations 8->256, 10->1024, 12->4096. Single pixel accuracy out of // typical image size of 1024x1024 means around 10 iterations gives decent accuracy for numbers much bigger // than 1. A value of 12 gave some differences in the least significant figures of numbers like 10^-3 in // the regression tests. Toggling between 30 and 32 made no difference in the regression tests. const int MAX_ITERATIONS = 32; // Spline class requires at least one point if (xy.size() > 0) { // Fit a spline Spline spline (t, xy); // Get value at desired points for (int row = 0; row < xThetaValues.count(); row++) { double xTheta = xThetaValues.at (row); SplinePair splinePairFound = spline.findSplinePairForFunctionX (xTheta, MAX_ITERATIONS); double yRadius = splinePairFound.y (); // Save y/radius value for this row into yRadiusValues, after appropriate formatting QString dummyXThetaOut; format.unformattedToFormatted (xTheta, yRadius, modelCoords, modelMainWindow, dummyXThetaOut, *(yRadiusValues [row]), transformation); } } } }
void Transformation::coordTextForStatusBar (QPointF cursorScreen, QString &coordsScreen, QString &coordsGraph, QString &resolutionsGraph) { const int UNCONSTRAINED_FIELD_WIDTH = 0; const double X_DELTA_PIXELS = 1.0, Y_DELTA_PIXELS = 1.0; const char FORMAT = 'g'; if (cursorScreen.x() < 0 || cursorScreen.y() < 0) { // Out of bounds, so return empty text coordsScreen = ""; coordsGraph = ""; resolutionsGraph = ""; } else { coordsScreen = QString("(%1, %2)") .arg (cursorScreen.x ()) .arg (cursorScreen.y ()); if (m_transformIsDefined) { // For resolution we compute graph coords for cursorScreen, and then for cursorScreen plus a delta QPointF cursorScreenDelta (cursorScreen.x () + X_DELTA_PIXELS, cursorScreen.y () + Y_DELTA_PIXELS); // Convert to graph coordinates QPointF pointGraph, pointGraphDelta; transformScreenToRawGraph (cursorScreen, pointGraph); transformScreenToRawGraph (cursorScreenDelta, pointGraphDelta); // Compute graph resolutions at cursor double resolutionXGraph = qAbs ((pointGraphDelta.x () - pointGraph.x ()) / X_DELTA_PIXELS); double resolutionYGraph = qAbs ((pointGraphDelta.y () - pointGraph.y ()) / Y_DELTA_PIXELS); // Formatting for date/time and degrees/minutes/seconds is only done on coordinates, and not on resolution FormatCoordsUnits format; QString xThetaFormatted, yRadiusFormatted; format.unformattedToFormatted (pointGraph.x(), pointGraph.y(), m_modelCoords, m_modelMainWindow, xThetaFormatted, yRadiusFormatted, *this); coordsGraph = QString ("(%1, %2)") .arg (xThetaFormatted) .arg (yRadiusFormatted); resolutionsGraph = QString ("(%1, %2)") .arg (resolutionXGraph, UNCONSTRAINED_FIELD_WIDTH, FORMAT, PRECISION_DIGITS) .arg (resolutionYGraph, UNCONSTRAINED_FIELD_WIDTH, FORMAT, PRECISION_DIGITS); } else { coordsGraph = "<font color=\"red\">Need more axis points</font>"; resolutionsGraph = coordsGraph; } } }