[Kst] branches/work/kst/portto4/kst/src
Mike Fenton
mike at staikos.net
Mon Feb 11 20:22:10 CET 2008
SVN commit 773788 by fenton:
Add interpretation of values to Date/Time.
M +337 -28 libkstapp/plotitem.cpp
M +6 -0 libkstapp/plotitem.h
M +2 -6 libkstmath/plotdefines.h
--- branches/work/kst/portto4/kst/src/libkstapp/plotitem.cpp #773787:773788
@@ -27,10 +27,17 @@
#include "dataobjectcollection.h"
#include "cartesianrenderitem.h"
+#include "settings.h"
+
#include <QDebug>
static qreal MARGIN_WIDTH = 20.0;
static qreal MARGIN_HEIGHT = 20.0;
+static int FULL_PRECISION = 15;
+static qreal JD1900 = 2415020.5;
+static qreal JD1970 = 2440587.5;
+static qreal JD_RJD = 2400000.0;
+static qreal JD_MJD = 2400000.5;
namespace Kst {
@@ -362,55 +369,73 @@
yLabels.append(QString::number(y));
}
- QString xOffsetLabel, yOffsetLabel;
- if (_xAxisBaseOffset) {
- qreal offset;
+ QString xBaseLabel, yBaseLabel;
+ if (_xAxisBaseOffset || _xAxisInterpret) {
+ qreal base;
int shortest = 1000;
for (int i = 0; i < xMajorTicks.count(); i++) {
if (xLabels[i].length() < shortest) {
shortest = xLabels[i].length();
- offset = xMajorTicks[i];
+ base = xMajorTicks[i];
}
}
xLabels.clear();
- xOffsetLabel = QString::number(offset);
+ if (_xAxisInterpret) {
+ xBaseLabel = interpretLabel(_xAxisInterpretation, _xAxisDisplay, base, xMajorTicks[xMajorTicks.count() -1]);
+ } else {
+ xBaseLabel = QString::number(base);
+ }
for (int i = 0; i < xMajorTicks.count(); i++) {
- qreal value = xMajorTicks[i] - offset;
+ qreal offset;
+ if (_xAxisInterpret) {
+ offset = interpretOffset(_xAxisInterpretation, _xAxisDisplay, base, xMajorTicks[i]);
+ } else {
+ offset = xMajorTicks[i] - base;
+ }
QString label;
- if (value < 0) {
+ if (offset < 0) {
label += "-";
- value = value * -1;
- } else if (value > 0) {
+ offset = offset * -1;
+ } else if (offset > 0) {
label += "+";
}
label += "[";
- label += QString::number(value);
+ label += QString::number(offset, 'g', FULL_PRECISION);
label += "]";
xLabels.append(label);
}
}
- if (_yAxisBaseOffset) {
- qreal offset;
+ if (_yAxisBaseOffset || _yAxisInterpret) {
+ qreal base;
int shortest = 1000;
for (int i = 0; i < yMajorTicks.count(); i++) {
if (yLabels[i].length() < shortest) {
shortest = yLabels[i].length();
- offset = yMajorTicks[i];
+ base = yMajorTicks[i];
}
}
yLabels.clear();
- yOffsetLabel = QString::number(offset);
+ if (_yAxisInterpret) {
+ yBaseLabel = interpretLabel(_yAxisInterpretation, _yAxisDisplay, base, yMajorTicks[xMajorTicks.count() -1]);
+ } else {
+ yBaseLabel = QString::number(base);
+ }
for (int i = 0; i < yMajorTicks.count(); i++) {
- qreal value = yMajorTicks[i] - offset;
+ qreal offset;
+ if (_yAxisInterpret) {
+ offset = interpretOffset(_yAxisInterpretation, _yAxisDisplay, base, yMajorTicks[i]);
+ } else {
+ offset = yMajorTicks[i] - base;
+ }
QString label;
- if (value < 0) {
+ if (offset < 0) {
label += "-";
- value = value * -1;
- } else if (value > 0) {
+ offset = offset * -1;
+ } else if (offset > 0) {
label += "+";
}
label += "[";
- label += QString::number(value);
+ label += QString::number(offset);
label += "]";
yLabels.append(label);
}
@@ -439,25 +464,25 @@
painter->drawText(bound, flags, label);
}
- if (_yAxisBaseOffset) {
+ if (!yBaseLabel.isEmpty()) {
painter->save();
QTransform t;
t.rotate(90.0);
painter->rotate(-90.0);
- QRectF bound = painter->boundingRect(QRectF(), flags, yOffsetLabel);
+ QRectF bound = painter->boundingRect(QRectF(), flags, yBaseLabel);
bound = QRectF(bound.x(), bound.bottomRight().y() - bound.width(), bound.height(), bound.width());
QPointF p = mapToPlotFromProjection(QPointF(projectionRect().left(), projectionRect().top()));
p.setX(p.x() - bound.width() * 2.0);
bound.moveBottomLeft(p);
- if (xLabelRect.isValid()) {
- xLabelRect = xLabelRect.united(bound);
+ if (yLabelRect.isValid()) {
+ yLabelRect = yLabelRect.united(bound);
} else {
- xLabelRect = bound;
+ yLabelRect = bound;
}
- painter->drawText(t.mapRect(bound), flags, yOffsetLabel);
+ painter->drawText(t.mapRect(bound), flags, yBaseLabel);
painter->restore();
}
@@ -485,8 +510,8 @@
painter->drawText(bound, flags, label);
}
- if (_xAxisBaseOffset) {
- QRectF bound = painter->boundingRect(QRectF(), flags, xOffsetLabel);
+ if (!xBaseLabel.isEmpty()) {
+ QRectF bound = painter->boundingRect(QRectF(), flags, xBaseLabel);
QPointF p = mapToPlotFromProjection(QPointF(projectionRect().left(), projectionRect().top()));
p.setY(p.y() + bound.height() * 2.0);
bound.moveBottomLeft(p);
@@ -497,7 +522,7 @@
xLabelRect = bound;
}
- painter->drawText(bound, flags, xOffsetLabel);
+ painter->drawText(bound, flags, xBaseLabel);
}
_xLabelRect = xLabelRect;
@@ -514,6 +539,290 @@
}
+QString PlotItem::interpretLabel(KstAxisInterpretation axisInterpretation, KstAxisDisplay axisDisplay, double base, double lastValue) {
+ double value = convertTimeValueToJD(axisInterpretation, base);
+ double scaleValue = convertTimeValueToJD(axisInterpretation, lastValue) - value;
+
+ switch (axisInterpretation) {
+ case AXIS_INTERP_YEAR:
+ scaleValue *= 365.25 * 24.0 * 60.0 * 60.0;
+ break;
+ case AXIS_INTERP_CTIME:
+ break;
+ case AXIS_INTERP_JD:
+ case AXIS_INTERP_MJD:
+ case AXIS_INTERP_RJD:
+ scaleValue *= 24.0 * 60.0 * 60.0;
+ break;
+ case AXIS_INTERP_AIT:
+ break;
+ }
+
+ QString label;
+
+ // print value in appropriate format
+ switch (axisDisplay) {
+ case AXIS_DISPLAY_YEAR:
+ value -= JD1900 + 0.5;
+ value /= 365.25;
+ value += 1900.0;
+ label = i18n("J");
+ label += QString::number(value, 'g', FULL_PRECISION);
+ label += " [years]";
+ break;
+ case AXIS_DISPLAY_YYMMDDHHMMSS_SS:
+ case AXIS_DISPLAY_DDMMYYHHMMSS_SS:
+ case AXIS_DISPLAY_QTTEXTDATEHHMMSS_SS:
+ case AXIS_DISPLAY_QTLOCALDATEHHMMSS_SS:
+ label = convertJDToDateString(axisInterpretation, axisDisplay, value);
+ if( scaleValue > 10.0 * 24.0 * 60.0 * 60.0 ) {
+ label += i18n(" [days]");
+ } else if( scaleValue > 10.0 * 24.0 * 60.0 ) {
+ label += i18n(" [hours]");
+ } else if( scaleValue > 10.0 * 60.0 ) {
+ label += i18n(" [minutes]");
+ } else {
+ label += i18n(" [seconds]");
+ }
+ break;
+ case AXIS_DISPLAY_JD:
+ label = i18n("JD");
+ label += QString::number(value, 'g', FULL_PRECISION);
+ label += " [days]";
+ break;
+ case AXIS_DISPLAY_MJD:
+ value -= JD_MJD;
+ label = i18n("MJD");
+ label += QString::number(value, 'g', FULL_PRECISION);
+ label += " [days]";
+ break;
+ case AXIS_DISPLAY_RJD:
+ value -= JD_RJD;
+ label = i18n("RJD");
+ label += QString::number(value, 'g', FULL_PRECISION);
+ label += " [days]";
+ break;
+ }
+
+ return label;
+}
+
+
+double PlotItem::interpretOffset(KstAxisInterpretation axisInterpretation, KstAxisDisplay axisDisplay, double base, double value) {
+ double offset;
+ offset = value - base;
+
+ offset = convertTimeDiffValueToDays(axisInterpretation, offset);
+
+ // convert difference to desired format
+ switch (axisDisplay) {
+ case AXIS_DISPLAY_YEAR:
+ offset /= 365.25;
+ break;
+ case AXIS_DISPLAY_YYMMDDHHMMSS_SS:
+ case AXIS_DISPLAY_DDMMYYHHMMSS_SS:
+ case AXIS_DISPLAY_QTTEXTDATEHHMMSS_SS:
+ case AXIS_DISPLAY_QTLOCALDATEHHMMSS_SS:
+ offset *= 24.0 * 60.0 * 60.0;
+ break;
+ case AXIS_DISPLAY_JD:
+ case AXIS_DISPLAY_MJD:
+ case AXIS_DISPLAY_RJD:
+ break;
+ }
+ return offset;
+}
+
+
+double PlotItem::convertTimeValueToJD(KstAxisInterpretation axisInterpretation, double valueIn) {
+ double value = valueIn;
+
+ switch (axisInterpretation) {
+ case AXIS_INTERP_YEAR:
+ value -= 1900.0;
+ value *= 365.25;
+ value += JD1900 + 0.5;
+ break;
+ case AXIS_INTERP_CTIME:
+ value /= 24.0 * 60.0 * 60.0;
+ value += JD1970;
+ break;
+ case AXIS_INTERP_JD:
+ break;
+ case AXIS_INTERP_MJD:
+ value += JD_MJD;
+ break;
+ case AXIS_INTERP_RJD:
+ value += JD_RJD;
+ break;
+ case AXIS_INTERP_AIT:
+ value -= 86400.0 * (365.0 * 12.0 + 3.0);
+ // current difference (seconds) between UTC and AIT
+ // refer to the following for more information:
+ // http://hpiers.obspm.fr/eop-pc/earthor/utc/TAI-UTC_tab.html
+ value -= 32.0;
+ value /= 24.0 * 60.0 * 60.0;
+ value += JD1970;
+ default:
+ break;
+ }
+
+ return value;
+}
+
+
+double PlotItem::convertTimeDiffValueToDays(KstAxisInterpretation axisInterpretation, double offsetIn) {
+ double offset = offsetIn;
+
+ switch (axisInterpretation) {
+ case AXIS_INTERP_YEAR:
+ offset *= 365.25;
+ break;
+ case AXIS_INTERP_CTIME:
+ offset /= 24.0 * 60.0 * 60.0;
+ break;
+ case AXIS_INTERP_JD:
+ case AXIS_INTERP_MJD:
+ case AXIS_INTERP_RJD:
+ break;
+ case AXIS_INTERP_AIT:
+ offset /= 24.0 * 60.0 * 60.0;
+ break;
+ default:
+ break;
+ }
+
+ return offset;
+}
+
+
+QString PlotItem::convertJDToDateString(KstAxisInterpretation axisInterpretation, KstAxisDisplay axisDisplay, double dJD) {
+ QString label;
+ QDate date;
+
+ int accuracy;
+ double xdelta = (projectionRect().right()-projectionRect().left())/double(projectionRect().width());
+ xdelta = convertTimeDiffValueToDays(axisInterpretation, xdelta);
+ xdelta *= 24.0 * 60.0 * 60.0;
+
+ if (xdelta == 0.0) {
+ accuracy = FULL_PRECISION;
+ } else {
+ accuracy = 1 - int(log10(xdelta));
+ if (accuracy < 0) {
+ accuracy = 0;
+ }
+ }
+
+ // utcOffset() is returned in seconds... as it must be since
+ // some time zones are not an integer number of hours offset
+ // from UTC...
+ dJD += double(Settings::globalSettings()->utcOffset()) / 86400.0;
+
+ // get the date from the Julian day number
+ double dJDDay = floor(dJD);
+ double dJDFraction = dJD - dJDDay;
+
+ // gregorian calendar correction
+ if (dJD >= 2299160.5) {
+ double tmp = int( ( (dJDDay - 1867216.0) - 0.25 ) / 36524.25 );
+ dJDDay += 1.0 + tmp - floor(0.25*tmp);
+ }
+
+ // correction for half day offset
+ double dDayFraction = dJDFraction + 0.5;
+ if (dDayFraction >= 1.0) {
+ dDayFraction -= 1.0;
+ dJDDay += 1.0;
+ }
+
+ // get time of day from day fraction
+ int hour = int(dDayFraction*24.0);
+ int minute = int((dDayFraction*24.0 - double(hour))*60.0);
+ double second = ((dDayFraction*24.0 - double(hour))*60.0 - double(minute))*60.0;
+
+ if (accuracy >= 0) {
+ second *= pow(10.0, accuracy);
+ second = floor(second+0.5);
+ second /= pow(10.0,accuracy);
+ if (second >= 60.0) {
+ second -= 60.0;
+ minute++;
+ if (minute == 60) {
+ minute = 0;
+ hour++;
+ if (hour == 24) {
+ hour = 0;
+ }
+ }
+ }
+ }
+
+ double j2 = dJDDay + 1524.0;
+ double j3 = floor(6680.0 + ( (j2 - 2439870.0) - 122.1 )/365.25);
+ double j4 = floor(j3 * 365.25);
+ double j5 = floor((j2 - j4)/30.6001);
+
+ int day = int(j2 - j4 - floor(j5*30.6001));
+ int month = int(j5 - 1.0);
+ if (month > 12) {
+ month -= 12;
+ }
+ int year = int(j3 - 4715.0);
+ if (month > 2) {
+ --year;
+ }
+ if (year <= 0) {
+ --year;
+ }
+ // check how many decimal places for the seconds we actually need to show
+ if (accuracy > 0) {
+ QString strSecond;
+
+ strSecond.sprintf("%02.*f", accuracy, second);
+ for (int i=strSecond.length()-1; i>0; i--) {
+ if (strSecond.at(i) == '0') {
+ accuracy--;
+ } else if (!strSecond.at(i).isDigit()) {
+ break;
+ }
+ }
+ }
+
+ if (accuracy < 0) {
+ accuracy = 0;
+ }
+
+ QString seconds;
+ QString hourminute;
+ hourminute.sprintf(" %02d:%02d:", hour, minute);
+ seconds.sprintf(" %02.*f", accuracy, second);
+ switch (axisDisplay) {
+ case AXIS_DISPLAY_YYMMDDHHMMSS_SS:
+ label.sprintf("%d/%02d/%02d", year, month, day);
+ label += hourminute + seconds;
+ break;
+ case AXIS_DISPLAY_DDMMYYHHMMSS_SS:
+ label.sprintf("%02d/%02d/%d", day, month, year);
+ label += hourminute + seconds;
+ break;
+ case AXIS_DISPLAY_QTTEXTDATEHHMMSS_SS:
+ date.setYMD(year, month, day);
+ label = date.toString(Qt::TextDate).toAscii();
+ label += hourminute + seconds;
+ break;
+ case AXIS_DISPLAY_QTLOCALDATEHHMMSS_SS:
+ date.setYMD(year, month, day);
+ label = date.toString(Qt::LocalDate).toAscii();
+ label += hourminute + seconds;
+ break;
+ default:
+ break;
+ }
+ return label;
+}
+
+
QRectF PlotItem::plotAxisRect() const {
qreal left = isLeftLabelVisible() ? labelMarginWidth() : 0.0;
qreal bottom = isBottomLabelVisible() ? labelMarginHeight() : 0.0;
--- branches/work/kst/portto4/kst/src/libkstapp/plotitem.h #773787:773788
@@ -259,6 +259,12 @@
qreal calculatedLabelMarginHeight() const;
void setCalculatedLabelMarginHeight(qreal marginHeight);
+ QString interpretLabel(KstAxisInterpretation axisInterpretation, KstAxisDisplay axisDisplay, double base, double lastValue);
+ double convertTimeValueToJD(KstAxisInterpretation axisInterpretation, double valueIn);
+ QString convertJDToDateString(KstAxisInterpretation axisInterpretation, KstAxisDisplay axisDisplay, double dJD);
+ double convertTimeDiffValueToDays(KstAxisInterpretation axisInterpretation, double offsetIn);
+ double interpretOffset(KstAxisInterpretation axisInterpretation, KstAxisDisplay axisDisplay, double base, double value);
+
QRectF horizontalLabelRect(bool calc) const;
QRectF verticalLabelRect(bool calc) const;
--- branches/work/kst/portto4/kst/src/libkstmath/plotdefines.h #773787:773788
@@ -34,9 +34,7 @@
AXIS_DISPLAY_QTLOCALDATEHHMMSS_SS,
AXIS_DISPLAY_JD,
AXIS_DISPLAY_MJD,
- AXIS_DISPLAY_RJD,
- AXIS_DISPLAY_KDE_SHORTDATE,
- AXIS_DISPLAY_KDE_LONGDATE };
+ AXIS_DISPLAY_RJD };
struct AxisInterpretation {
const char *label;
@@ -65,9 +63,7 @@
{ I18N_NOOP("<Qt Local Date> HH:MM:SS.SS"), AXIS_DISPLAY_QTLOCALDATEHHMMSS_SS },
{ I18N_NOOP2("Julian Date", "JD"), AXIS_DISPLAY_JD },
{ I18N_NOOP2("Modified Julian Date", "MJD"), AXIS_DISPLAY_MJD },
- { I18N_NOOP2("Reduced Julian Date", "RJD"), AXIS_DISPLAY_RJD },
- { I18N_NOOP("<KDE Short Date and Time>"), AXIS_DISPLAY_KDE_SHORTDATE },
- { I18N_NOOP("<KDE Long Date and Time>"), AXIS_DISPLAY_KDE_LONGDATE }
+ { I18N_NOOP2("Reduced Julian Date", "RJD"), AXIS_DISPLAY_RJD }
};
class TickParameters {
More information about the Kst
mailing list