annotate data/model/PowerOfSqrtTwoZoomConstraint.cpp @ 383:94fc0591ea43 1.2-stable

* merge from trunk (1.2 ended up being tracked from trunk, but we may want this branch for fixes later)
author Chris Cannam
date Wed, 27 Feb 2008 10:32:45 +0000
parents 3a13b0d4934e
children d7f3dfe6f9a4
rev   line source
Chris@147 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@147 2
Chris@147 3 /*
Chris@147 4 Sonic Visualiser
Chris@147 5 An audio file viewer and annotation editor.
Chris@147 6 Centre for Digital Music, Queen Mary, University of London.
Chris@147 7 This file copyright 2006 Chris Cannam.
Chris@147 8
Chris@147 9 This program is free software; you can redistribute it and/or
Chris@147 10 modify it under the terms of the GNU General Public License as
Chris@147 11 published by the Free Software Foundation; either version 2 of the
Chris@147 12 License, or (at your option) any later version. See the file
Chris@147 13 COPYING included with this distribution for more information.
Chris@147 14 */
Chris@147 15
Chris@147 16 #include "PowerOfSqrtTwoZoomConstraint.h"
Chris@147 17
Chris@147 18 #include <iostream>
Chris@147 19 #include <cmath>
Chris@147 20
Chris@147 21
Chris@147 22 size_t
Chris@147 23 PowerOfSqrtTwoZoomConstraint::getNearestBlockSize(size_t blockSize,
Chris@147 24 RoundingDirection dir) const
Chris@147 25 {
Chris@147 26 int type, power;
Chris@147 27 size_t rv = getNearestBlockSize(blockSize, type, power, dir);
Chris@147 28 return rv;
Chris@147 29 }
Chris@147 30
Chris@147 31 size_t
Chris@147 32 PowerOfSqrtTwoZoomConstraint::getNearestBlockSize(size_t blockSize,
Chris@147 33 int &type,
Chris@147 34 int &power,
Chris@147 35 RoundingDirection dir) const
Chris@147 36 {
Chris@147 37 // std::cerr << "given " << blockSize << std::endl;
Chris@147 38
Chris@147 39 size_t minCachePower = getMinCachePower();
Chris@147 40
Chris@147 41 if (blockSize < (1U << minCachePower)) {
Chris@147 42 type = -1;
Chris@147 43 power = 0;
Chris@147 44 float val = 1.0, prevVal = 1.0;
Chris@147 45 while (val + 0.01 < blockSize) {
Chris@147 46 prevVal = val;
Chris@147 47 val *= sqrt(2);
Chris@147 48 }
Chris@147 49 size_t rval;
Chris@147 50 if (dir == RoundUp) rval = size_t(val + 0.01);
Chris@147 51 else if (dir == RoundDown) rval = size_t(prevVal + 0.01);
Chris@147 52 else if (val - blockSize < blockSize - prevVal) rval = size_t(val + 0.01);
Chris@147 53 else rval = size_t(prevVal + 0.01);
Chris@147 54 // std::cerr << "returning " << rval << std::endl;
Chris@147 55 return rval;
Chris@147 56 }
Chris@147 57
Chris@147 58 unsigned int prevBase = (1 << minCachePower);
Chris@147 59 unsigned int prevPower = minCachePower;
Chris@147 60 unsigned int prevType = 0;
Chris@147 61
Chris@147 62 size_t result = 0;
Chris@147 63
Chris@147 64 for (unsigned int i = 0; ; ++i) {
Chris@147 65
Chris@147 66 power = minCachePower + i/2;
Chris@147 67 type = i % 2;
Chris@147 68
Chris@147 69 unsigned int base;
Chris@147 70 if (type == 0) {
Chris@147 71 base = (1 << power);
Chris@147 72 } else {
Chris@147 73 base = (((unsigned int)((1 << minCachePower) * sqrt(2) + 0.01))
Chris@147 74 << (power - minCachePower));
Chris@147 75 }
Chris@147 76
Chris@147 77 // std::cerr << "Testing base " << base << std::endl;
Chris@383 78
Chris@383 79 if (base == blockSize) {
Chris@383 80 result = base;
Chris@383 81 break;
Chris@383 82 }
Chris@383 83
Chris@383 84 if (base > blockSize) {
Chris@147 85 if (dir == RoundNearest) {
Chris@147 86 if (base - blockSize < blockSize - prevBase) {
Chris@147 87 dir = RoundUp;
Chris@147 88 } else {
Chris@147 89 dir = RoundDown;
Chris@147 90 }
Chris@147 91 }
Chris@147 92 if (dir == RoundUp) {
Chris@147 93 result = base;
Chris@147 94 break;
Chris@147 95 } else {
Chris@147 96 type = prevType;
Chris@147 97 power = prevPower;
Chris@147 98 result = prevBase;
Chris@147 99 break;
Chris@147 100 }
Chris@147 101 }
Chris@147 102
Chris@147 103 prevType = type;
Chris@147 104 prevPower = power;
Chris@147 105 prevBase = base;
Chris@147 106 }
Chris@147 107
Chris@147 108 if (result > getMaxZoomLevel()) result = getMaxZoomLevel();
Chris@147 109 return result;
Chris@147 110 }