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
|
#ifndef NUMERIC_TICK_SET_H
#define NUMERIC_TICK_SET_H
#include "tickset.h"
#include <vector>
#include <cmath>
#include <sstream>
class NumericTickSet final : public TickSet {
public:
NumericTickSet(double min, double max, unsigned sizeRequest)
: _min(min), _max(max), _sizeRequest(sizeRequest) {
set(sizeRequest);
}
std::unique_ptr<TickSet> Clone() const override {
return std::make_unique<NumericTickSet>(*this);
}
size_t Size() const override { return _ticks.size(); }
Tick GetTick(size_t i) const override {
std::stringstream tickStr;
tickStr << _ticks[i];
if (_max - _min == 0.0)
return Tick(0.5, tickStr.str());
else
return Tick((_ticks[i] - _min) / (_max - _min), tickStr.str());
}
void Reset() override {
_ticks.clear();
set(_sizeRequest);
}
void Set(size_t maxSize) override {
_ticks.clear();
set(maxSize);
}
double UnitToAxis(double unitValue) const override {
return (_min == _max) ? 0.0 : (unitValue - _min) / (_max - _min);
}
double AxisToUnit(double axisValue) const override {
return axisValue * (_max - _min) + _min;
}
private:
friend std::unique_ptr<NumericTickSet> std::make_unique<NumericTickSet>(
const NumericTickSet&);
void set(size_t sizeRequest) {
if (std::isfinite(_min) && std::isfinite(_max)) {
if (_max == _min) {
_ticks.push_back(_min);
} else {
if (sizeRequest == 0) return;
double tickWidth =
roundUpToNiceNumber(std::fabs(_max - _min) / (double)sizeRequest);
if (tickWidth == 0.0) tickWidth = 1.0;
if (_min < _max) {
double pos = roundUpToNiceNumber(_min, tickWidth);
while (pos <= _max) {
if (fabs(pos) < tickWidth / 100.0)
_ticks.push_back(0.0);
else
_ticks.push_back(pos);
pos += tickWidth;
}
} else {
double pos = -roundUpToNiceNumber(-_min, tickWidth);
while (pos >= _max) {
if (std::fabs(pos) < tickWidth / 100.0)
_ticks.push_back(0.0);
else
_ticks.push_back(pos);
pos -= tickWidth;
}
}
while (_ticks.size() > sizeRequest) _ticks.pop_back();
}
}
}
double roundUpToNiceNumber(double number) {
if (!std::isfinite(number)) return number;
double roundedNumber = 1.0;
if (number <= 0.0) {
if (number == 0.0) {
return 0.0;
} else {
roundedNumber = -1.0;
number *= -1.0;
}
}
while (number > 10) {
number /= 10;
roundedNumber *= 10;
}
while (number <= 1) {
number *= 10;
roundedNumber /= 10;
}
if (number <= 2)
return roundedNumber * 2;
else if (number <= 5)
return roundedNumber * 5;
else
return roundedNumber * 10;
}
double roundUpToNiceNumber(double number, double roundUnit) {
return roundUnit * ceil(number / roundUnit);
}
double _min, _max;
size_t _sizeRequest;
std::vector<double> _ticks;
};
#endif
|