RelativelyFineZoomConstraint.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 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2 of the
11  License, or (at your option) any later version. See the file
12  COPYING included with this distribution for more information.
13 */
14 
16 
17 #include <vector>
18 #include <algorithm>
19 #include <iostream>
20 
21 using namespace std;
22 
25  RoundingDirection dir) const
26 {
27  static vector<int> levels;
28 
29  int maxLevel = getMaxZoomLevel().level;
30 
31  if (levels.empty()) {
32  int level = 1;
33  while (level <= maxLevel) {
34 // cerr << level << " ";
35  levels.push_back(level);
36  int step = level / 10;
37  int pwr = 0;
38  while (step > 0) {
39  ++pwr;
40  step /= 2;
41  }
42  step = (1 << pwr);
43  level += step;
44  }
45 // cerr << endl;
46  }
47 
48  RoundingDirection effective = dir;
49  if (requested.zone == ZoomLevel::PixelsPerFrame) {
50  if (dir == RoundUp) effective = RoundDown;
51  else if (dir == RoundDown) effective = RoundUp;
52  }
53 
54  // iterator pointing to first level that is >= requested
55  auto i = lower_bound(levels.begin(), levels.end(), requested.level);
56 
57  ZoomLevel newLevel(requested);
58 
59  if (i == levels.end()) {
60  newLevel.level = maxLevel;
61 
62  } else if (*i == requested.level) {
63  newLevel.level = requested.level;
64 
65  } else if (effective == RoundUp) {
66  newLevel.level = *i;
67 
68  } else if (effective == RoundDown) {
69  if (i != levels.begin()) {
70  --i;
71  }
72  newLevel.level = *i;
73 
74  } else { // RoundNearest
75  if (i != levels.begin()) {
76  auto j = i;
77  --j;
78  if (requested.level - *j < *i - requested.level) {
79  newLevel.level = *j;
80  } else {
81  newLevel.level = *i;
82  }
83  }
84  }
85 
86  // canonicalise
87  if (newLevel.level == 1) {
88  newLevel.zone = ZoomLevel::FramesPerPixel;
89  }
90 
91  using namespace std::rel_ops;
92  if (newLevel > getMaxZoomLevel()) {
93  newLevel = getMaxZoomLevel();
94  } else if (newLevel < getMinZoomLevel()) {
95  newLevel = getMinZoomLevel();
96  }
97 
98  return newLevel;
99 }
100 
101 
Zone zone
Definition: ZoomLevel.h:33
Display zoom level.
Definition: ZoomLevel.h:26
int level
Definition: ZoomLevel.h:34
virtual ZoomLevel getNearestZoomLevel(ZoomLevel requested, RoundingDirection dir=RoundNearest) const override
Given an "ideal" zoom level (frames per pixel or pixels per frame) for a given zoom level...