comparison base/ScaleTickIntervals.h @ 1411:1f0d071e7ce6 scale-ticks

More tests & fixes
author Chris Cannam
date Wed, 03 May 2017 18:26:26 +0100
parents c4af57d59434
children b7a9edee85e0
comparison
equal deleted inserted replaced
1410:c4af57d59434 1411:1f0d071e7ce6
18 18
19 #include <string> 19 #include <string>
20 #include <vector> 20 #include <vector>
21 #include <cmath> 21 #include <cmath>
22 22
23 //#define DEBUG_SCALE_TICK_INTERVALS 1
24
25 #ifdef DEBUG_SCALE_TICK_INTERVALS
23 #include <iostream> 26 #include <iostream>
24 27 #endif
25 28
26 class ScaleTickIntervals 29 class ScaleTickIntervals
27 { 30 {
28 public: 31 public:
29 struct Range { 32 struct Range {
30 double min; // start of value range 33 double min; // start of value range
31 double max; // end of value range 34 double max; // end of value range
32 int n; // number of divisions requested (will be n+1 ticks) 35 int n; // number of divisions (will be at most n+1 ticks)
33 }; 36 };
34 37
35 struct Tick { 38 struct Tick {
36 double value; // value this tick represents 39 double value; // value this tick represents
37 std::string label; // value as written 40 std::string label; // value as written
55 return linear({ r.max, r.min, r.n }); 58 return linear({ r.max, r.min, r.n });
56 } 59 }
57 60
58 double inc = (r.max - r.min) / r.n; 61 double inc = (r.max - r.min) / r.n;
59 if (inc == 0) { 62 if (inc == 0) {
60 Ticks t { r.min, 1.0, r.min, false, 1, {} }; 63 #ifdef DEBUG_SCALE_TICK_INTERVALS
64 std::cerr << "inc == 0, using trivial range" << std::endl;
65 #endif
66 double roundTo = r.min;
67 if (roundTo <= 0.0) {
68 roundTo = 1.0;
69 }
70 Ticks t { r.min, 1.0, roundTo, true, 1, {} };
61 explode(r, t); 71 explode(r, t);
62 return t; 72 return t;
63 } 73 }
64 74
65 double digInc = log10(inc); 75 double digInc = log10(inc);
91 } 101 }
92 } else { 102 } else {
93 prec = precRange; 103 prec = precRange;
94 } 104 }
95 105
106 double roundTo = pow(10.0, precInc);
107
108 #ifdef DEBUG_SCALE_TICK_INTERVALS
96 std::cerr << "\nmin = " << r.min << ", max = " << r.max << ", n = " << r.n 109 std::cerr << "\nmin = " << r.min << ", max = " << r.max << ", n = " << r.n
97 << ", inc = " << inc << std::endl; 110 << ", inc = " << inc << std::endl;
98 std::cerr << "digMax = " << digMax << ", digInc = " << digInc 111 std::cerr << "digMax = " << digMax << ", digInc = " << digInc
99 << std::endl; 112 << std::endl;
100 std::cerr << "fixed = " << fixed << ", inc = " << inc 113 std::cerr << "fixed = " << fixed << ", inc = " << inc
101 << ", precInc = " << precInc << ", precRange = " << precRange 114 << ", precInc = " << precInc << ", precRange = " << precRange
102 << ", prec = " << prec << std::endl; 115 << ", prec = " << prec << std::endl;
103
104 double roundTo = pow(10.0, precInc);
105
106 std::cerr << "roundTo = " << roundTo << std::endl; 116 std::cerr << "roundTo = " << roundTo << std::endl;
117 #endif
107 118
108 inc = round(inc / roundTo) * roundTo; 119 inc = round(inc / roundTo) * roundTo;
109 if (inc < roundTo) inc = roundTo; 120 if (inc < roundTo) inc = roundTo;
110 121
111 double min = ceil(r.min / roundTo) * roundTo; 122 double min = ceil(r.min / roundTo) * roundTo;
116 return t; 127 return t;
117 } 128 }
118 129
119 private: 130 private:
120 static void explode(const Range &r, Ticks &t) { 131 static void explode(const Range &r, Ticks &t) {
132 #ifdef DEBUG_SCALE_TICK_INTERVALS
121 std::cerr << "initial = " << t.initial << ", spacing = " << t.spacing 133 std::cerr << "initial = " << t.initial << ", spacing = " << t.spacing
122 << ", roundTo = " << t.roundTo << ", fixed = " << t.fixed 134 << ", roundTo = " << t.roundTo << ", fixed = " << t.fixed
123 << ", precision = " << t.precision << std::endl; 135 << ", precision = " << t.precision << std::endl;
136 #endif
124 auto makeTick = [&](double value) { 137 auto makeTick = [&](double value) {
125 const int buflen = 40; 138 const int buflen = 40;
126 char buffer[buflen]; 139 char buffer[buflen];
127 snprintf(buffer, buflen, 140 snprintf(buffer, buflen,
128 t.fixed ? "%.*f" : "%.*e", 141 t.fixed ? "%.*f" : "%.*e",
129 t.precision, value); 142 t.precision, value);
130 return Tick({ value, std::string(buffer) }); 143 return Tick({ value, std::string(buffer) });
131 }; 144 };
132 for (double value = t.initial; 145 double eps = 1e-7;
133 value < r.max + t.spacing/2; 146 if (t.spacing < eps * 10.0) {
134 value += t.spacing) { 147 eps = t.spacing / 10.0;
148 }
149 for (double value = t.initial; value < r.max + eps; value += t.spacing) {
135 value = t.roundTo * round(value / t.roundTo); 150 value = t.roundTo * round(value / t.roundTo);
136 t.ticks.push_back(makeTick(value)); 151 t.ticks.push_back(makeTick(value));
137 } 152 }
138 } 153 }
139 }; 154 };