comparison base/test/TestScaleTickIntervals.h @ 1420:a533662c17f4

Merge from branch "scale-ticks"
author Chris Cannam
date Mon, 10 Jul 2017 14:23:19 +0100
parents e7cb4fb2aee4
children 8b7d6c1e1ab7
comparison
equal deleted inserted replaced
1406:09751743647e 1420:a533662c17f4
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version. See the file
12 COPYING included with this distribution for more information.
13 */
14
15 #ifndef TEST_SCALE_TICK_INTERVALS_H
16 #define TEST_SCALE_TICK_INTERVALS_H
17
18 #include "../ScaleTickIntervals.h"
19
20 #include <QObject>
21 #include <QtTest>
22 #include <QDir>
23
24 #include <iostream>
25
26 using namespace std;
27
28 class TestScaleTickIntervals : public QObject
29 {
30 Q_OBJECT
31
32 void printDiff(vector<ScaleTickIntervals::Tick> ticks,
33 vector<ScaleTickIntervals::Tick> expected) {
34
35 cerr << "Have " << ticks.size() << " ticks, expected "
36 << expected.size() << endl;
37 for (int i = 0; i < int(ticks.size()); ++i) {
38 cerr << i << ": have " << ticks[i].value << " \""
39 << ticks[i].label << "\", expected ";
40 if (i < int(expected.size())) {
41 cerr << expected[i].value << " \"" << expected[i].label
42 << "\"" << endl;
43 } else {
44 cerr << "(n/a)" << endl;
45 }
46 }
47 }
48
49 void compareTicks(ScaleTickIntervals::Ticks ticks,
50 ScaleTickIntervals::Ticks expected,
51 bool fuzzier = false)
52 {
53 double eps = 1e-7;
54 for (int i = 0; i < int(expected.size()); ++i) {
55 if (i < int(ticks.size())) {
56 bool pass = true;
57 if (ticks[i].label != expected[i].label) {
58 pass = false;
59 } else if (!fuzzier) {
60 if (fabs(ticks[i].value - expected[i].value) > eps) {
61 pass = false;
62 }
63 } else {
64 if (fabs(ticks[i].value - expected[i].value) >
65 fabs(ticks[i].value) * 1e-5) {
66 pass = false;
67 }
68 }
69 if (!pass) {
70 printDiff(ticks, expected);
71 QCOMPARE(ticks[i].label, expected[i].label);
72 QCOMPARE(ticks[i].value, expected[i].value);
73 }
74 }
75 }
76 if (ticks.size() != expected.size()) {
77 printDiff(ticks, expected);
78 }
79 QCOMPARE(ticks.size(), expected.size());
80 }
81
82 private slots:
83 void linear_0_1_10()
84 {
85 auto ticks = ScaleTickIntervals::linear({ 0, 1, 10 });
86 ScaleTickIntervals::Ticks expected {
87 { 0.0, "0.0" },
88 { 0.1, "0.1" },
89 { 0.2, "0.2" },
90 { 0.3, "0.3" },
91 { 0.4, "0.4" },
92 { 0.5, "0.5" },
93 { 0.6, "0.6" },
94 { 0.7, "0.7" },
95 { 0.8, "0.8" },
96 { 0.9, "0.9" },
97 { 1.0, "1.0" }
98 };
99 compareTicks(ticks, expected);
100 }
101
102 void linear_0_5_5()
103 {
104 auto ticks = ScaleTickIntervals::linear({ 0, 5, 5 });
105 ScaleTickIntervals::Ticks expected {
106 { 0, "0" },
107 { 1, "1" },
108 { 2, "2" },
109 { 3, "3" },
110 { 4, "4" },
111 { 5, "5" },
112 };
113 compareTicks(ticks, expected);
114 }
115
116 void linear_0_10_5()
117 {
118 auto ticks = ScaleTickIntervals::linear({ 0, 10, 5 });
119 ScaleTickIntervals::Ticks expected {
120 { 0, "0" },
121 { 2, "2" },
122 { 4, "4" },
123 { 6, "6" },
124 { 8, "8" },
125 { 10, "10" }
126 };
127 compareTicks(ticks, expected);
128 }
129
130 void linear_10_0_5()
131 {
132 auto ticks = ScaleTickIntervals::linear({ 10, 0, 5 });
133 ScaleTickIntervals::Ticks expected {
134 { 0, "0" },
135 { 2, "2" },
136 { 4, "4" },
137 { 6, "6" },
138 { 8, "8" },
139 { 10, "10" }
140 };
141 compareTicks(ticks, expected);
142 }
143
144 void linear_m10_0_5()
145 {
146 auto ticks = ScaleTickIntervals::linear({ -10, 0, 5 });
147 ScaleTickIntervals::Ticks expected {
148 { -10, "-10" },
149 { -8, "-8" },
150 { -6, "-6" },
151 { -4, "-4" },
152 { -2, "-2" },
153 { 0, "0" }
154 };
155 compareTicks(ticks, expected);
156 }
157
158 void linear_0_m10_5()
159 {
160 auto ticks = ScaleTickIntervals::linear({ 0, -10, 5 });
161 ScaleTickIntervals::Ticks expected {
162 { -10, "-10" },
163 { -8, "-8" },
164 { -6, "-6" },
165 { -4, "-4" },
166 { -2, "-2" },
167 { 0, "0" }
168 };
169 compareTicks(ticks, expected);
170 }
171
172 void linear_0_0p1_5()
173 {
174 auto ticks = ScaleTickIntervals::linear({ 0, 0.1, 5 });
175 ScaleTickIntervals::Ticks expected {
176 { 0.00, "0.00" },
177 { 0.02, "0.02" },
178 { 0.04, "0.04" },
179 { 0.06, "0.06" },
180 { 0.08, "0.08" },
181 { 0.10, "0.10" }
182 };
183 compareTicks(ticks, expected);
184 }
185
186 void linear_0_0p01_5()
187 {
188 auto ticks = ScaleTickIntervals::linear({ 0, 0.01, 5 });
189 ScaleTickIntervals::Ticks expected {
190 { 0.000, "0.000" },
191 { 0.002, "0.002" },
192 { 0.004, "0.004" },
193 { 0.006, "0.006" },
194 { 0.008, "0.008" },
195 { 0.010, "0.010" }
196 };
197 compareTicks(ticks, expected);
198 }
199
200 void linear_0_0p005_5()
201 {
202 auto ticks = ScaleTickIntervals::linear({ 0, 0.005, 5 });
203 ScaleTickIntervals::Ticks expected {
204 { 0.000, "0.000" },
205 { 0.001, "0.001" },
206 { 0.002, "0.002" },
207 { 0.003, "0.003" },
208 { 0.004, "0.004" },
209 { 0.005, "0.005" }
210 };
211 compareTicks(ticks, expected);
212 }
213
214 void linear_0_0p001_5()
215 {
216 auto ticks = ScaleTickIntervals::linear({ 0, 0.001, 5 });
217 ScaleTickIntervals::Ticks expected {
218 { 0.0000, "0.0e+00" },
219 { 0.0002, "2.0e-04" },
220 { 0.0004, "4.0e-04" },
221 { 0.0006, "6.0e-04" },
222 { 0.0008, "8.0e-04" },
223 { 0.0010, "1.0e-03" }
224 };
225 compareTicks(ticks, expected);
226 }
227
228 void linear_1_1p001_5()
229 {
230 auto ticks = ScaleTickIntervals::linear({ 1, 1.001, 5 });
231 ScaleTickIntervals::Ticks expected {
232 { 1.0000, "1.0000" },
233 { 1.0002, "1.0002" },
234 { 1.0004, "1.0004" },
235 { 1.0006, "1.0006" },
236 { 1.0008, "1.0008" },
237 { 1.0010, "1.0010" }
238 };
239 compareTicks(ticks, expected);
240 }
241
242 void linear_0p001_1_5()
243 {
244 auto ticks = ScaleTickIntervals::linear({ 0.001, 1, 5 });
245 ScaleTickIntervals::Ticks expected {
246 { 0.1, "0.1" },
247 { 0.3, "0.3" },
248 { 0.5, "0.5" },
249 { 0.7, "0.7" },
250 { 0.9, "0.9" },
251 };
252 compareTicks(ticks, expected);
253 }
254
255 void linear_10000_10010_5()
256 {
257 auto ticks = ScaleTickIntervals::linear({ 10000, 10010, 5 });
258 ScaleTickIntervals::Ticks expected {
259 { 10000, "10000" },
260 { 10002, "10002" },
261 { 10004, "10004" },
262 { 10006, "10006" },
263 { 10008, "10008" },
264 { 10010, "10010" },
265 };
266 compareTicks(ticks, expected);
267 }
268
269 void linear_10000_20000_5()
270 {
271 auto ticks = ScaleTickIntervals::linear({ 10000, 20000, 5 });
272 ScaleTickIntervals::Ticks expected {
273 { 10000, "10000" },
274 { 12000, "12000" },
275 { 14000, "14000" },
276 { 16000, "16000" },
277 { 18000, "18000" },
278 { 20000, "20000" },
279 };
280 compareTicks(ticks, expected);
281 }
282
283 void linear_m1_1_10()
284 {
285 auto ticks = ScaleTickIntervals::linear({ -1, 1, 10 });
286 ScaleTickIntervals::Ticks expected {
287 { -1.0, "-1.0" },
288 { -0.8, "-0.8" },
289 { -0.6, "-0.6" },
290 { -0.4, "-0.4" },
291 { -0.2, "-0.2" },
292 { 0.0, "0.0" },
293 { 0.2, "0.2" },
294 { 0.4, "0.4" },
295 { 0.6, "0.6" },
296 { 0.8, "0.8" },
297 { 1.0, "1.0" }
298 };
299 compareTicks(ticks, expected);
300 }
301
302 void linear_221p23_623p7_57p4()
303 {
304 auto ticks = ScaleTickIntervals::linear({ 221.23, 623.7, 4 });
305 // only 4 ticks, not 5, because none of the rounded tick
306 // values lies on an end value
307 ScaleTickIntervals::Ticks expected {
308 { 300, "300" },
309 { 400, "400" },
310 { 500, "500" },
311 { 600, "600" },
312 };
313 compareTicks(ticks, expected);
314 }
315
316 void linear_sqrt2_pi_7()
317 {
318 auto ticks = ScaleTickIntervals::linear({ sqrt(2.0), M_PI, 7 });
319 // This would be better in steps of 0.25, but we only round to
320 // integral powers of ten
321 ScaleTickIntervals::Ticks expected {
322 { 1.5, "1.5" },
323 { 1.7, "1.7" },
324 { 1.9, "1.9" },
325 { 2.1, "2.1" },
326 { 2.3, "2.3" },
327 { 2.5, "2.5" },
328 { 2.7, "2.7" },
329 { 2.9, "2.9" },
330 { 3.1, "3.1" },
331 };
332 compareTicks(ticks, expected);
333 }
334
335 void linear_pi_avogadro_7()
336 {
337 auto ticks = ScaleTickIntervals::linear({ M_PI, 6.022140857e23, 7 });
338 ScaleTickIntervals::Ticks expected {
339 // not perfect, but ok-ish
340 { 1e+22, "1.00e+22" },
341 { 1e+23, "1.00e+23" },
342 { 1.9e+23, "1.90e+23" },
343 { 2.8e+23, "2.80e+23" },
344 { 3.7e+23, "3.70e+23" },
345 { 4.6e+23, "4.60e+23" },
346 { 5.5e+23, "5.50e+23" },
347 };
348 compareTicks(ticks, expected);
349 }
350
351 void linear_2_3_1()
352 {
353 auto ticks = ScaleTickIntervals::linear({ 2, 3, 1 });
354 ScaleTickIntervals::Ticks expected {
355 { 2.0, "2" },
356 { 3.0, "3" }
357 };
358 compareTicks(ticks, expected);
359 }
360
361 void linear_2_3_2()
362 {
363 auto ticks = ScaleTickIntervals::linear({ 2, 3, 2 });
364 ScaleTickIntervals::Ticks expected {
365 { 2.0, "2.0" },
366 { 2.5, "2.5" },
367 { 3.0, "3.0" }
368 };
369 compareTicks(ticks, expected);
370 }
371
372 void linear_2_3_3()
373 {
374 auto ticks = ScaleTickIntervals::linear({ 2, 3, 3 });
375 ScaleTickIntervals::Ticks expected {
376 { 2.0, "2.0" },
377 { 2.3, "2.3" },
378 { 2.6, "2.6" },
379 { 2.9, "2.9" }
380 };
381 compareTicks(ticks, expected);
382 }
383
384 void linear_2_3_4()
385 {
386 auto ticks = ScaleTickIntervals::linear({ 2, 3, 4 });
387 // This would be better in steps of 0.25, but we only round to
388 // integral powers of ten
389 ScaleTickIntervals::Ticks expected {
390 { 2.0, "2.0" },
391 { 2.3, "2.3" },
392 { 2.6, "2.6" },
393 { 2.9, "2.9" }
394 };
395 compareTicks(ticks, expected);
396 }
397
398 void linear_2_3_5()
399 {
400 auto ticks = ScaleTickIntervals::linear({ 2, 3, 5 });
401 ScaleTickIntervals::Ticks expected {
402 { 2.0, "2.0" },
403 { 2.2, "2.2" },
404 { 2.4, "2.4" },
405 { 2.6, "2.6" },
406 { 2.8, "2.8" },
407 { 3.0, "3.0" }
408 };
409 compareTicks(ticks, expected);
410 }
411
412 void linear_2_3_6()
413 {
414 auto ticks = ScaleTickIntervals::linear({ 2, 3, 6 });
415 ScaleTickIntervals::Ticks expected {
416 { 2.0, "2.0" },
417 { 2.2, "2.2" },
418 { 2.4, "2.4" },
419 { 2.6, "2.6" },
420 { 2.8, "2.8" },
421 { 3.0, "3.0" }
422 };
423 compareTicks(ticks, expected);
424 }
425
426 void linear_1_1_10()
427 {
428 // pathological range
429 auto ticks = ScaleTickIntervals::linear({ 1, 1, 10 });
430 ScaleTickIntervals::Ticks expected {
431 { 1.0, "1" }
432 };
433 compareTicks(ticks, expected);
434 }
435
436 void linear_0_0_10()
437 {
438 // pathological range
439 auto ticks = ScaleTickIntervals::linear({ 0, 0, 10 });
440 ScaleTickIntervals::Ticks expected {
441 { 0.0, "0" }
442 };
443 compareTicks(ticks, expected);
444 }
445
446 void linear_0_1_1()
447 {
448 auto ticks = ScaleTickIntervals::linear({ 0, 1, 1 });
449 ScaleTickIntervals::Ticks expected {
450 { 0.0, "0" },
451 { 1.0, "1" }
452 };
453 compareTicks(ticks, expected);
454 }
455
456 void linear_0_1_0()
457 {
458 // senseless input
459 auto ticks = ScaleTickIntervals::linear({ 0, 1, 0 });
460 ScaleTickIntervals::Ticks expected {
461 { 0.0, "0" },
462 };
463 compareTicks(ticks, expected);
464 }
465
466 void linear_0_1_m1()
467 {
468 // senseless input
469 auto ticks = ScaleTickIntervals::linear({ 0, 1, -1 });
470 ScaleTickIntervals::Ticks expected {
471 { 0.0, "0" },
472 };
473 compareTicks(ticks, expected);
474 }
475
476 void linear_0p465_778_10()
477 {
478 // a case that gave unsatisfactory results in real life
479 // (initially it had the first tick at 1)
480 auto ticks = ScaleTickIntervals::linear({ 0.465, 778.08, 10 });
481 ScaleTickIntervals::Ticks expected {
482 { 10, "10" },
483 { 90, "90" },
484 { 170, "170" },
485 { 250, "250" },
486 { 330, "330" },
487 { 410, "410" },
488 { 490, "490" },
489 { 570, "570" },
490 { 650, "650" },
491 { 730, "730" },
492 };
493 compareTicks(ticks, expected);
494 }
495
496 void log_1_10_2()
497 {
498 auto ticks = ScaleTickIntervals::logarithmic({ 1, 10, 2 });
499 ScaleTickIntervals::Ticks expected {
500 { 1.0, "1.0" },
501 { pow(10.0, 0.5), "3.2" },
502 { 10.0, "10.0" },
503 };
504 compareTicks(ticks, expected);
505 }
506
507 void log_0_10_2()
508 {
509 auto ticks = ScaleTickIntervals::logarithmic({ 0, 10, 2 });
510 ScaleTickIntervals::Ticks expected {
511 { 1e-6, "1e-06" },
512 { 1, "1" },
513 };
514 compareTicks(ticks, expected);
515 }
516
517 void log_pi_avogadro_7()
518 {
519 auto ticks = ScaleTickIntervals::logarithmic({ M_PI, 6.022140857e23, 7 });
520 ScaleTickIntervals::Ticks expected {
521 { 1000, "1e+03" },
522 { 1e+06, "1e+06" },
523 { 1e+09, "1e+09" },
524 { 1e+12, "1e+12" },
525 { 1e+15, "1e+15" },
526 { 1e+18, "1e+18" },
527 { 1e+21, "1e+21" },
528 };
529 compareTicks(ticks, expected, true);
530 }
531
532 void log_0p465_778_10()
533 {
534 auto ticks = ScaleTickIntervals::logarithmic({ 0.465, 778.08, 10 });
535 ScaleTickIntervals::Ticks expected {
536 { 0.5, "0.5" },
537 { 1, "1.0" },
538 { 2, "2.0" },
539 { 4, "4.0" },
540 { 8, "8.0" },
541 { 16, "16.0" },
542 { 32, "32.0" },
543 { 64, "64.0" },
544 { 128, "128.0" },
545 { 256, "256.0" },
546 { 512, "512.0" },
547 };
548 compareTicks(ticks, expected);
549 }
550
551 };
552
553 #endif
554
555