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
|
#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 size_request, bool is_integer)
: min_(min),
max_(max),
size_request_(size_request),
is_integer_(is_integer) {
set(size_request);
}
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(size_request_);
}
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 size_request) {
if (std::isfinite(min_) && std::isfinite(max_)) {
if (max_ == min_) {
ticks_.push_back(min_);
} else {
if (size_request == 0) return;
double tickWidth =
RoundUpToNiceNumber(std::fabs(max_ - min_) / (double)size_request);
if (is_integer_ && tickWidth < 1.0) tickWidth = 1.0;
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() > size_request) 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_;
double max_;
size_t size_request_;
bool is_integer_;
std::vector<double> ticks_;
};
#endif
|