comparison layer/LogNumericalScale.cpp @ 696:e77b1673e17e tonioni

Pull out log and linear vertical scales into their own classes, make some improvements to log numbering
author Chris Cannam
date Wed, 04 Dec 2013 11:35:08 +0000
parents
children 1a1448f7beb2
comparison
equal deleted inserted replaced
695:6d9624e0ac55 696:e77b1673e17e
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 This file copyright 2006-2013 Chris Cannam and QMUL.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information.
14 */
15
16 #include "LogNumericalScale.h"
17 #include "VerticalScaleLayer.h"
18
19 #include "base/LogRange.h"
20
21 #include <QPainter>
22
23 #include <cmath>
24
25 #include "view/View.h"
26
27 //#define DEBUG_TIME_VALUE_LAYER 1
28
29 int
30 LogNumericalScale::getWidth(View *,
31 QPainter &paint)
32 {
33 return paint.fontMetrics().width("-000.00");
34 }
35
36 void
37 LogNumericalScale::paintVertical(View *v,
38 const VerticalScaleLayer *layer,
39 QPainter &paint,
40 int x0,
41 float minlog,
42 float maxlog)
43 {
44 int w = getWidth(v, paint) + x0;
45
46 int n = 10;
47
48 float val = minlog;
49 float inc = (maxlog - val) / n; // even increments of log scale
50
51 // smallest increment as displayed
52 float minDispInc = LogRange::unmap(minlog + inc) - LogRange::unmap(minlog);
53
54 #ifdef DEBUG_TIME_VALUE_LAYER
55 cerr << "min = " << minlog << ", max = " << maxlog << ", inc = " << inc << ", minDispInc = " << minDispInc << endl;
56 #endif
57
58 char buffer[40];
59
60 float round = 1.f;
61 int dp = 0;
62
63 if (minDispInc > 0) {
64 int prec = trunc(log10f(minDispInc));
65 if (prec < 0) dp = -prec;
66 round = powf(10.f, prec);
67 #ifdef DEBUG_TIME_VALUE_LAYER
68 cerr << "round = " << round << ", prec = " << prec << ", dp = " << dp << endl;
69 #endif
70 }
71
72 int prevy = -1;
73
74 for (int i = 0; i < n; ++i) {
75
76 int y, ty;
77 bool drawText = true;
78
79 if (i == n-1 &&
80 v->height() < paint.fontMetrics().height() * (n*2)) {
81 if (layer->getScaleUnits() != "") drawText = false;
82 }
83
84 float dispval = LogRange::unmap(val);
85 dispval = floor(dispval / round) * round;
86
87 #ifdef DEBUG_TIME_VALUE_LAYER
88 cerr << "val = " << val << ", dispval = " << dispval << endl;
89 #endif
90
91 y = layer->getYForValue(v, dispval);
92
93 ty = y - paint.fontMetrics().height() + paint.fontMetrics().ascent() + 2;
94
95 if (prevy >= 0 && (prevy - y) < paint.fontMetrics().height()) {
96 val += inc;
97 continue;
98 }
99
100 double dv = dispval;
101 int digits = trunc(log10f(dv));
102 int sf = dp + (digits > 0 ? digits : 0);
103 if (sf < 4) sf = 4;
104 sprintf(buffer, "%.*g", sf, dv);
105
106 QString label = QString(buffer);
107
108 paint.drawLine(w - 5, y, w, y);
109
110 if (drawText) {
111 paint.drawText(w - paint.fontMetrics().width(label) - 6,
112 ty, label);
113 }
114
115 prevy = y;
116 val += inc;
117 }
118 }