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