svgui  1.9
LogNumericalScale.cpp
Go to the documentation of this file.
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
31  QPainter &paint)
32 {
33  return paint.fontMetrics().width("-000.00") + 10;
34 }
35 
36 void
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  if (dp > 4) dp = 4;
68 #ifdef DEBUG_TIME_VALUE_LAYER
69  cerr << "round = " << round << ", prec = " << prec << ", dp = " << dp << endl;
70 #endif
71  }
72 
73  int prevy = -1;
74 
75  for (int i = 0; i < n; ++i) {
76 
77  int y, ty;
78  bool drawText = true;
79 
80  if (i == n-1 &&
81  v->height() < paint.fontMetrics().height() * (n*2)) {
82  if (layer->getScaleUnits() != "") drawText = false;
83  }
84 
85  float dispval = LogRange::unmap(val);
86  dispval = floor(dispval / round) * round;
87 
88 #ifdef DEBUG_TIME_VALUE_LAYER
89  cerr << "val = " << val << ", dispval = " << dispval << endl;
90 #endif
91 
92  y = layer->getYForValue(v, dispval);
93 
94  ty = y - paint.fontMetrics().height() + paint.fontMetrics().ascent() + 2;
95 
96  if (prevy >= 0 && (prevy - y) < paint.fontMetrics().height()) {
97  val += inc;
98  continue;
99  }
100 
101  int digits = trunc(log10f(dispval));
102  int sf = dp + (digits > 0 ? digits : 0);
103  if (sf < 4) sf = 4;
104 #ifdef DEBUG_TIME_VALUE_LAYER
105  cerr << "sf = " << sf << endl;
106 #endif
107  sprintf(buffer, "%.*g", sf, dispval);
108 
109  QString label = QString(buffer);
110 
111  paint.drawLine(w - 5, y, w, y);
112 
113  if (drawText) {
114  paint.drawText(w - paint.fontMetrics().width(label) - 6,
115  ty, label);
116  }
117 
118  prevy = y;
119  val += inc;
120  }
121 }
void paintVertical(View *v, const VerticalScaleLayer *layer, QPainter &paint, int x0, float minlog, float maxlog)
int getWidth(View *v, QPainter &paint)
virtual int getYForValue(View *, float value) const =0
View is the base class of widgets that display one or more overlaid views of data against a horizonta...
Definition: View.h:50
virtual QString getScaleUnits() const =0