svgui  1.9
LogNumericalScale.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006-2013 Chris Cannam and QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "LogNumericalScale.h"
00017 #include "VerticalScaleLayer.h"
00018 
00019 #include "base/LogRange.h"
00020 
00021 #include <QPainter>
00022 
00023 #include <cmath>
00024 
00025 #include "view/View.h"
00026 
00027 //#define DEBUG_TIME_VALUE_LAYER 1
00028 
00029 int
00030 LogNumericalScale::getWidth(View *,
00031                             QPainter &paint)
00032 {
00033     return paint.fontMetrics().width("-000.00") + 10;
00034 }
00035 
00036 void
00037 LogNumericalScale::paintVertical(View *v,
00038                                  const VerticalScaleLayer *layer,
00039                                  QPainter &paint,
00040                                  int x0,
00041                                  float minlog,
00042                                  float maxlog)
00043 {
00044     int w = getWidth(v, paint) + x0;
00045 
00046     int n = 10;
00047 
00048     float val = minlog;
00049     float inc = (maxlog - val) / n; // even increments of log scale
00050 
00051     // smallest increment as displayed
00052     float minDispInc = LogRange::unmap(minlog + inc) - LogRange::unmap(minlog);
00053 
00054 #ifdef DEBUG_TIME_VALUE_LAYER
00055     cerr << "min = " << minlog << ", max = " << maxlog << ", inc = " << inc << ", minDispInc = " << minDispInc << endl;
00056 #endif
00057 
00058     char buffer[40];
00059 
00060     float round = 1.f;
00061     int dp = 0;
00062 
00063     if (minDispInc > 0) {
00064         int prec = trunc(log10f(minDispInc));
00065         if (prec < 0) dp = -prec;
00066         round = powf(10.f, prec);
00067         if (dp > 4) dp = 4;
00068 #ifdef DEBUG_TIME_VALUE_LAYER
00069         cerr << "round = " << round << ", prec = " << prec << ", dp = " << dp << endl;
00070 #endif
00071     }
00072 
00073     int prevy = -1;
00074                 
00075     for (int i = 0; i < n; ++i) {
00076 
00077         int y, ty;
00078         bool drawText = true;
00079 
00080         if (i == n-1 &&
00081             v->height() < paint.fontMetrics().height() * (n*2)) {
00082             if (layer->getScaleUnits() != "") drawText = false;
00083         }
00084 
00085         float dispval = LogRange::unmap(val);
00086         dispval = floor(dispval / round) * round;
00087 
00088 #ifdef DEBUG_TIME_VALUE_LAYER
00089         cerr << "val = " << val << ", dispval = " << dispval << endl;
00090 #endif
00091 
00092         y = layer->getYForValue(v, dispval);
00093 
00094         ty = y - paint.fontMetrics().height() + paint.fontMetrics().ascent() + 2;
00095         
00096         if (prevy >= 0 && (prevy - y) < paint.fontMetrics().height()) {
00097             val += inc;
00098             continue;
00099         }
00100 
00101         int digits = trunc(log10f(dispval));
00102         int sf = dp + (digits > 0 ? digits : 0);
00103         if (sf < 4) sf = 4;
00104 #ifdef DEBUG_TIME_VALUE_LAYER
00105         cerr << "sf = " << sf << endl;
00106 #endif
00107         sprintf(buffer, "%.*g", sf, dispval);
00108 
00109         QString label = QString(buffer);
00110 
00111         paint.drawLine(w - 5, y, w, y);
00112 
00113         if (drawText) {
00114             paint.drawText(w - paint.fontMetrics().width(label) - 6,
00115                            ty, label);
00116         }
00117 
00118         prevy = y;
00119         val += inc;
00120     }
00121 }