1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
#ifndef TIME_TICK_SET_H
#define TIME_TICK_SET_H
#include "tickset.h"
#include "../../structures/date.h"
class TimeTickSet final : public TickSet {
public:
TimeTickSet(double minTime, double maxTime, unsigned sizeRequest)
: _min(minTime), _max(maxTime), _sizeRequest(sizeRequest) {
if (!std::isfinite(minTime) || !std::isfinite(maxTime))
throw std::runtime_error("Invalid (non-finite) range in TimeTickSet");
set(sizeRequest);
}
std::unique_ptr<TickSet> Clone() const override {
return std::unique_ptr<TickSet>(new TimeTickSet(*this));
}
size_t Size() const override { return _ticks.size(); }
Tick GetTick(size_t i) const override {
double val = _ticks[i];
return Tick((val - _min) / (_max - _min), Date::AipsMJDToTimeString(val));
}
void Reset() override {
_ticks.clear();
set(_sizeRequest);
}
void Set(size_t maxSize) override {
_ticks.clear();
set(maxSize);
}
double UnitToAxis(double unitValue) const override {
return (unitValue - _min) / (_max - _min);
}
double AxisToUnit(double axisValue) const override {
return axisValue * (_max - _min) + _min;
}
private:
void set(size_t sizeRequest) {
if (_max == _min) {
_ticks.push_back(_min);
} else {
if (sizeRequest == 0) return;
double tickWidth =
calculateTickWidth((_max - _min) / (double)sizeRequest);
if (tickWidth == 0.0 || !std::isfinite(tickWidth)) tickWidth = 1.0;
double pos = roundUpToNiceNumber(_min, tickWidth);
while (pos < _max) {
_ticks.push_back(pos);
pos += tickWidth;
}
while (_ticks.size() > sizeRequest) _ticks.pop_back();
}
}
double calculateTickWidth(double lowerLimit) const {
if (!std::isfinite(lowerLimit)) return lowerLimit;
// number is in units of seconds
if (lowerLimit >= 60.0 * 60.0 * 24.0) { // In days?
double width = 60.0 * 60.0 * 24.0;
while (width < lowerLimit) width *= 2.0;
return width;
} else if (lowerLimit > 60.0 * 30.0) { // in hours?
if (lowerLimit <= 60.0 * 60.0) {
return 60.0 * 60.0; // hours
} else if (lowerLimit <= 60.0 * 60.0 * 2.0) {
return 60.0 * 60.0 * 2.0; // two hours
} else if (lowerLimit <= 60.0 * 60.0 * 3.0) {
return 60.0 * 60.0 * 3.0; // three hours
} else if (lowerLimit <= 60.0 * 60.0 * 4.0) {
return 60.0 * 60.0 * 4.0; // four hours
} else if (lowerLimit <= 60.0 * 60.0 * 6.0) {
return 60.0 * 60.0 * 6.0; // six hours
} else {
return 60.0 * 60.0 * 12.0; // twelve hours
}
} else if (lowerLimit > 30.0) { // in minutes?
if (lowerLimit <= 60.0)
return 60.0; // in minutes
else if (lowerLimit <= 60.0 * 2.0)
return 60.0 * 2.0; // two minutes
else if (lowerLimit <= 60.0 * 5.0)
return 60.0 * 5.0; // five minutes
else if (lowerLimit <= 60.0 * 10.0)
return 60.0 * 10.0; // ten minutes
else if (lowerLimit <= 60.0 * 15.0)
return 60.0 * 15.0; // quarter hours
else
return 60.0 * 30.0; // half hours
} else if (lowerLimit > 0.5) { // in seconds?
if (lowerLimit <= 1.0)
return 1.0; // in seconds
else if (lowerLimit <= 2.0)
return 2.0; // two seconds
else if (lowerLimit <= 5.0)
return 5.0; // five seconds
else if (lowerLimit <= 10.0)
return 10.0; // ten seconds
else if (lowerLimit <= 15.0)
return 15.0; // quarter minute
else
return 30.0; // half a minute
} else if (lowerLimit == 0.0) {
return 0.0;
} else { // in 10th of seconds or lower?
double factor = 1.0;
while (lowerLimit <= 0.1 && std::isfinite(lowerLimit)) {
factor *= 0.1;
lowerLimit *= 10.0;
}
if (lowerLimit <= 0.2)
return 0.2 * factor;
else if (lowerLimit <= 0.5)
return 0.5 * factor;
else
return factor;
}
}
double roundUpToNiceNumber(double number, double roundUnit) {
return roundUnit * std::ceil(number / roundUnit);
}
double _min, _max;
size_t _sizeRequest;
std::vector<double> _ticks;
};
#endif
|