svcore  1.9
PowerOfSqrtTwoZoomConstraint.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 Chris Cannam.
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 "PowerOfSqrtTwoZoomConstraint.h"
00017 
00018 #include <iostream>
00019 #include <cmath>
00020 
00021 
00022 int
00023 PowerOfSqrtTwoZoomConstraint::getNearestBlockSize(int blockSize,
00024                                                   RoundingDirection dir) const
00025 {
00026     int type, power;
00027     int rv = getNearestBlockSize(blockSize, type, power, dir);
00028     return rv;
00029 }
00030 
00031 int
00032 PowerOfSqrtTwoZoomConstraint::getNearestBlockSize(int blockSize,
00033                                                   int &type, 
00034                                                   int &power,
00035                                                   RoundingDirection dir) const
00036 {
00037 //    cerr << "given " << blockSize << endl;
00038 
00039     int minCachePower = getMinCachePower();
00040 
00041     if (blockSize < (1 << minCachePower)) {
00042         type = -1;
00043         power = 0;
00044         float val = 1.0, prevVal = 1.0;
00045         while (val + 0.01 < blockSize) {
00046             prevVal = val;
00047             val *= sqrt(2.f);
00048         }
00049         int rval;
00050         if (dir == RoundUp) rval = int(val + 0.01);
00051         else if (dir == RoundDown) rval = int(prevVal + 0.01);
00052         else if (val - blockSize < blockSize - prevVal) rval = int(val + 0.01);
00053         else rval = int(prevVal + 0.01);
00054 //      SVDEBUG << "returning " << rval << endl;
00055         return rval;
00056     }
00057 
00058     int prevBase = (1 << minCachePower);
00059     int prevPower = minCachePower;
00060     int prevType = 0;
00061 
00062     int result = 0;
00063 
00064     for (unsigned int i = 0; ; ++i) {
00065 
00066         power = minCachePower + i/2;
00067         type = i % 2;
00068 
00069         int base;
00070         if (type == 0) {
00071             base = (1 << power);
00072         } else {
00073             base = (((unsigned int)((1 << minCachePower) * sqrt(2.) + 0.01))
00074                     << (power - minCachePower));
00075         }
00076 
00077 //      SVDEBUG << "Testing base " << base << endl;
00078 
00079         if (base == blockSize) {
00080             result = base;
00081             break;
00082         }
00083 
00084         if (base > blockSize) {
00085             if (dir == RoundNearest) {
00086                 if (base - blockSize < blockSize - prevBase) {
00087                     dir = RoundUp;
00088                 } else {
00089                     dir = RoundDown;
00090                 }
00091             }
00092             if (dir == RoundUp) {
00093                 result = base;
00094                 break;
00095             } else {
00096                 type = prevType;
00097                 power = prevPower;
00098                 result = prevBase;
00099                 break;
00100             }
00101         }
00102 
00103         prevType = type;
00104         prevPower = power;
00105         prevBase = base;
00106     }
00107 
00108     if (result > getMaxZoomLevel()) result = getMaxZoomLevel();
00109     return result;
00110 }