Mercurial > hg > svcore
changeset 1411:1f0d071e7ce6 scale-ticks
More tests & fixes
author | Chris Cannam |
---|---|
date | Wed, 03 May 2017 18:26:26 +0100 |
parents | c4af57d59434 |
children | b7a9edee85e0 |
files | base/ScaleTickIntervals.h base/test/TestScaleTickIntervals.h |
diffstat | 2 files changed, 131 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/base/ScaleTickIntervals.h Wed May 03 18:06:48 2017 +0100 +++ b/base/ScaleTickIntervals.h Wed May 03 18:26:26 2017 +0100 @@ -20,8 +20,11 @@ #include <vector> #include <cmath> +//#define DEBUG_SCALE_TICK_INTERVALS 1 + +#ifdef DEBUG_SCALE_TICK_INTERVALS #include <iostream> - +#endif class ScaleTickIntervals { @@ -29,7 +32,7 @@ struct Range { double min; // start of value range double max; // end of value range - int n; // number of divisions requested (will be n+1 ticks) + int n; // number of divisions (will be at most n+1 ticks) }; struct Tick { @@ -57,7 +60,14 @@ double inc = (r.max - r.min) / r.n; if (inc == 0) { - Ticks t { r.min, 1.0, r.min, false, 1, {} }; +#ifdef DEBUG_SCALE_TICK_INTERVALS + std::cerr << "inc == 0, using trivial range" << std::endl; +#endif + double roundTo = r.min; + if (roundTo <= 0.0) { + roundTo = 1.0; + } + Ticks t { r.min, 1.0, roundTo, true, 1, {} }; explode(r, t); return t; } @@ -93,6 +103,9 @@ prec = precRange; } + double roundTo = pow(10.0, precInc); + +#ifdef DEBUG_SCALE_TICK_INTERVALS std::cerr << "\nmin = " << r.min << ", max = " << r.max << ", n = " << r.n << ", inc = " << inc << std::endl; std::cerr << "digMax = " << digMax << ", digInc = " << digInc @@ -100,10 +113,8 @@ std::cerr << "fixed = " << fixed << ", inc = " << inc << ", precInc = " << precInc << ", precRange = " << precRange << ", prec = " << prec << std::endl; - - double roundTo = pow(10.0, precInc); - std::cerr << "roundTo = " << roundTo << std::endl; +#endif inc = round(inc / roundTo) * roundTo; if (inc < roundTo) inc = roundTo; @@ -118,9 +129,11 @@ private: static void explode(const Range &r, Ticks &t) { +#ifdef DEBUG_SCALE_TICK_INTERVALS std::cerr << "initial = " << t.initial << ", spacing = " << t.spacing << ", roundTo = " << t.roundTo << ", fixed = " << t.fixed << ", precision = " << t.precision << std::endl; +#endif auto makeTick = [&](double value) { const int buflen = 40; char buffer[buflen]; @@ -129,9 +142,11 @@ t.precision, value); return Tick({ value, std::string(buffer) }); }; - for (double value = t.initial; - value < r.max + t.spacing/2; - value += t.spacing) { + double eps = 1e-7; + if (t.spacing < eps * 10.0) { + eps = t.spacing / 10.0; + } + for (double value = t.initial; value < r.max + eps; value += t.spacing) { value = t.roundTo * round(value / t.roundTo); t.ticks.push_back(makeTick(value)); }
--- a/base/test/TestScaleTickIntervals.h Wed May 03 18:06:48 2017 +0100 +++ b/base/test/TestScaleTickIntervals.h Wed May 03 18:26:26 2017 +0100 @@ -34,12 +34,14 @@ cerr << "Have " << ticks.size() << " ticks, expected " << expected.size() << endl; - for (int i = 0; i < int(expected.size()); ++i) { - if (i < int(ticks.size())) { - cerr << i << ": have " << ticks[i].value << " \"" - << ticks[i].label << "\", expected " - << expected[i].value << " \"" << expected[i].label + for (int i = 0; i < int(ticks.size()); ++i) { + cerr << i << ": have " << ticks[i].value << " \"" + << ticks[i].label << "\", expected "; + if (i < int(expected.size())) { + cerr << expected[i].value << " \"" << expected[i].label << "\"" << endl; + } else { + cerr << "(n/a)" << endl; } } } @@ -115,6 +117,48 @@ compareTicks(ticks.ticks, expected); } + void linear_10_0_5() + { + auto ticks = ScaleTickIntervals::linear({ 10, 0, 5 }); + vector<ScaleTickIntervals::Tick> expected { + { 0, "0.0" }, + { 2, "2.0" }, + { 4, "4.0" }, + { 6, "6.0" }, + { 8, "8.0" }, + { 10, "10.0" } + }; + compareTicks(ticks.ticks, expected); + } + + void linear_m10_0_5() + { + auto ticks = ScaleTickIntervals::linear({ -10, 0, 5 }); + vector<ScaleTickIntervals::Tick> expected { + { -10, "-10.0" }, + { -8, "-8.0" }, + { -6, "-6.0" }, + { -4, "-4.0" }, + { -2, "-2.0" }, + { 0, "0.0" } + }; + compareTicks(ticks.ticks, expected); + } + + void linear_0_m10_5() + { + auto ticks = ScaleTickIntervals::linear({ 0, -10, 5 }); + vector<ScaleTickIntervals::Tick> expected { + { -10, "-10.0" }, + { -8, "-8.0" }, + { -6, "-6.0" }, + { -4, "-4.0" }, + { -2, "-2.0" }, + { 0, "0.0" } + }; + compareTicks(ticks.ticks, expected); + } + void linear_0_0p1_5() { auto ticks = ScaleTickIntervals::linear({ 0, 0.1, 5 }); @@ -231,6 +275,64 @@ }; compareTicks(ticks.ticks, expected); } + + void linear_221p23_623p7_57p4() + { + auto ticks = ScaleTickIntervals::linear({ 221.23, 623.7, 4 }); + // only 4 ticks, not 5, because none of the rounded tick + // values lies on an end value + vector<ScaleTickIntervals::Tick> expected { + { 230, "230" }, + { 330, "330" }, + { 430, "430" }, + { 530, "530" }, + }; + compareTicks(ticks.ticks, expected); + } + + void linear_1_1_10() + { + auto ticks = ScaleTickIntervals::linear({ 1, 1, 10 }); + vector<ScaleTickIntervals::Tick> expected { + { 1.0, "1.0" } + }; + compareTicks(ticks.ticks, expected); + } + + void linear_0_0_10() + { + auto ticks = ScaleTickIntervals::linear({ 0, 0, 10 }); + vector<ScaleTickIntervals::Tick> expected { + { 0.0, "0.0" } + }; + compareTicks(ticks.ticks, expected); + } + + void linear_0_1_1() + { + auto ticks = ScaleTickIntervals::linear({ 0, 1, 1 }); + vector<ScaleTickIntervals::Tick> expected { + { 0.0, "0.0" }, + { 1.0, "1.0" } + }; + compareTicks(ticks.ticks, expected); + } + + void linear_0_1_0() + { + auto ticks = ScaleTickIntervals::linear({ 0, 1, 0 }); + vector<ScaleTickIntervals::Tick> expected { + }; + compareTicks(ticks.ticks, expected); + } + + void linear_0_1_m1() + { + auto ticks = ScaleTickIntervals::linear({ 0, 1, -1 }); + vector<ScaleTickIntervals::Tick> expected { + }; + compareTicks(ticks.ticks, expected); + } }; #endif