Canorus  0.0
kdtree.h
Go to the documentation of this file.
1 
8 #ifndef KDTREE_H
9 #define KDTREE_H
10 
11 #include <QMultiMap>
12 #include <QRect>
13 #include <limits> // max double for managing staffs with unlimited width
14 #include <iostream> // debugging
15 
16 #include "layout/drawable.h"
17 #include "layout/drawablecontext.h"
20 
21 #include "score/muselement.h"
22 #include "score/playable.h"
23 #include "score/voice.h"
24 
38 template <typename T>
39 class CAKDTree {
40 public:
42 
43  void addElement(T elt);
44  T removeElement(double x, double y);
45 
46  QList<T> findInRange(double x, double y, double w=0, double h=0);
47  QList<T> findInRange(QRect &area);
48  T findNearestLeft(double x, bool timeBased=false, CADrawableContext *context=0, CAVoice *voice=0);
49  T findNearestRight(double x, bool timeBased=false, CADrawableContext *context=0, CAVoice *voice=0);
50  T findNearestUp(double y);
51  T findNearestDown(double y);
52 
53  double getMaxX();
54  double getMaxY();
55 
56  void clear(bool autoDelete=true);
57  inline int size() { return _mapX.size(); }
58  QList<T> list() { return _mapX.values(); }
59 
60 private:
62  // Basic properties //
64  QMultiMap<double, T> _mapX; // List of all the drawable elements sorted by xPos()
65  QMultiMap<double, T> _mapXW; // List of all the drawable elements sorted by xPos()+width()
66  double _maxY; // The largest Ypos()+height() value of any element
67 
68  void calculateMaxY();
69 };
70 
74 template <typename T>
76  _maxY = 0;
77 }
78 
82 template <typename T>
84  _mapX.insertMulti(elt->xPos(), elt);
85 
86  if (elt->width()) {
87  // regular music element
88  _mapXW.insertMulti(elt->xPos()+elt->width(), elt);
89  } else {
90  // music element with unlimited width (e.g. staffs)
91  _mapXW.insertMulti(std::numeric_limits<double>::max(), elt);
92  }
93 
94  if (elt->yPos() + elt->height() > _maxY) {
95  _maxY = elt->yPos() + elt->height();
96  }
97 }
98 
103 template <typename T>
104 void CAKDTree<T>::clear(bool autoDelete) {
105  if (autoDelete) {
106  for (typename QMultiMap<double, T>::const_iterator it=_mapX.constBegin(); it!=_mapX.constEnd(); it++) {
107  delete it.value();
108  }
109  }
110 
111  _mapX.clear();
112  _mapXW.clear();
113 
114  _maxY = 0;
115 }
116 
121 template <typename T>
122 QList<T> CAKDTree<T>::findInRange(double x, double y, double w, double h) {
123  QList<T> l;
124 
125  T rightMostElt = _mapX.lowerBound(x+w).value();
126  for (typename QMultiMap<double, T>::const_iterator it=_mapXW.upperBound(x); (it!=_mapXW.end()) && (it.value()!=rightMostElt); it++) {
127  if ( (// The object is normal and fits into the area
128  (it.value()->yPos() <= y+h) &&
129  (it.value()->yPos() + it.value()->height() >= y)) ||
130  (// The object is unlimited in width (eg. contexts)
131  (it.value()->width() == 0) &&
132  (it.value()->yPos() <= y+h) &&
133  (it.value()->yPos() + it.value()->height() >= y)) ||
134  (// The object is unlimited in height (eg. helper lines)
135  (it.value()->height() == 0))
136  ) {
137  l << it.value();
138  }
139  }
140 
141  return l;
142 }
143 
149 template <typename T>
150 QList<T> CAKDTree<T>::findInRange(QRect &rect) {
151  return findInRange(rect.x(), rect.y(), rect.width(), rect.height());
152 }
153 
162 template <typename T>
163 T CAKDTree<T>::findNearestLeft(double x, bool timeBased, CADrawableContext *context, CAVoice *voice) {
164  if (_mapX.size()==0) {
165  return 0;
166  }
167 
168  typename QMultiMap<double, T>::const_iterator it = _mapX.lowerBound(x); // returns constEnd, if not found
169  while (it!=_mapX.constBegin() && (it==_mapX.constEnd() || it.value()->xPos()>=x)) {
170  it--;
171  }
172 
173  if (it.value()->xPos()>=x) {
174  // no elements to the left at all
175  return 0;
176  }
177 
178  do {
179  if (
180  // compare contexts
181  (!context || it.value()->drawableContext() == context) &&
182  // compare voices
183  ( !voice ||
184  (
185  // if the element isn't playable, see if it has the same context as the voice
186  (!it.value()->musElement()->isPlayable() &&
187  it.value()->musElement()->context() == voice->staff())
188  ||
189  // if the element is playable, see if it has the exactly same voice
190  (it.value()->musElement()->isPlayable() &&
191  static_cast<CAPlayable*>(it.value()->musElement())->voice() == voice)
192  )
193  )
194  ) {
195  return static_cast<T>(it.value());
196  }
197  } while ((it--)!=_mapX.constBegin());
198 
199  // no regular elements to the left exists
200  return 0;
201 }
202 
211 template <typename T>
212 T CAKDTree<T>::findNearestRight(double x, bool timeBased, CADrawableContext *context, CAVoice *voice) {
213  typename QMultiMap<double, T>::const_iterator it = _mapX.upperBound(x);
214 
215  for (; it!=_mapX.constEnd(); it++) {
216  if (
217  // compare contexts
218  (!context || it.value()->drawableContext() == context) &&
219  // compare voices
220  ( !voice ||
221  (
222  // if the element isn't playable, see if it has the same context as the voice
223  (!it.value()->musElement()->isPlayable() &&
224  it.value()->musElement()->context() == voice->staff())
225  ||
226  // if the element is playable, see if it has the exactly same voice
227  (it.value()->musElement()->isPlayable() &&
228  static_cast<CAPlayable*>(it.value()->musElement())->voice() == voice)
229  )
230  )
231  ) {
232  return static_cast<T>(it.value());
233  }
234  }
235 
236  // no elements to the right exists
237  return 0;
238 }
239 
248 template <typename T>
250  if (_mapX.isEmpty())
251  return 0;
252 
253  T elt=0;
254  for (typename QMultiMap<double, T>::const_iterator it=_mapX.constBegin(); it!=_mapX.constEnd(); it++) {
255  if ( ((!elt) || ((it.value()->yPos() + it.value()->height()) > (elt->yPos() + elt->height())))
256  && ((it.value()->yPos()+ it.value()->height()) < y) ) {
257  elt = it.value();
258  }
259  }
260  return elt;
261 
262 }
263 
272 template <typename T>
274  if (_mapX.isEmpty())
275  return 0;
276 
277  T elt=0;
278  for (typename QMultiMap<double, T>::const_iterator it=_mapX.constBegin(); it!=_mapX.constEnd(); it++) {
279  if ( ((!elt) || (it.value()->yPos() < elt->yPos())) && (it.value()->yPos() > y) ) {
280  elt = it.value();
281  }
282  }
283 
284  return elt;
285 }
286 
291 template <typename T>
293  if(_mapXW.constEnd() == _mapXW.constBegin())
294  return 0.0;
295  for (typename QMultiMap<double, T>::const_iterator it=(--_mapXW.constEnd());
296  it!=_mapXW.constBegin();
297  it--) {
298  if (it.key()!=std::numeric_limits<double>::max()) {
299  // don't take contexts unlimited length into account
300  return it.key();
301  }
302  }
303  return 0;
304 }
305 
310 template <typename T>
312  return _maxY;
313 }
314 
320 template <typename T>
322  _maxY = 0;
323  for (typename QMultiMap<double, T>::iterator it=_mapX.begin(); it!=_mapX.end(); it++) {
324  if (it.value()->yPos()+it.value()->height() > _maxY) {
325  _maxY = it.value()->yPos()+it.value()->height();
326  }
327  }
328 }
329 
330 #endif
331 
drawablenotecheckererror.h
CAKDTree::_mapXW
QMultiMap< double, T > _mapXW
Definition: kdtree.h:65
CAKDTree::findNearestUp
T findNearestUp(double y)
Definition: kdtree.h:249
playable.h
CAKDTree::removeElement
T removeElement(double x, double y)
CAVoice
Class which represents a voice in the staff.
Definition: voice.h:23
CAKDTree::_maxY
double _maxY
Definition: kdtree.h:66
CAKDTree::getMaxY
double getMaxY()
Definition: kdtree.h:311
CAKDTree
Space partitioning structure for fast access to drawable elements on canvas.
Definition: kdtree.h:39
CAKDTree::findNearestRight
T findNearestRight(double x, bool timeBased=false, CADrawableContext *context=0, CAVoice *voice=0)
Definition: kdtree.h:212
CAPlayable
Playable instances of music elements.
Definition: playable.h:18
CAKDTree::findNearestLeft
T findNearestLeft(double x, bool timeBased=false, CADrawableContext *context=0, CAVoice *voice=0)
Definition: kdtree.h:163
CAKDTree::calculateMaxY
void calculateMaxY()
Definition: kdtree.h:321
CAKDTree::findInRange
QList< T > findInRange(double x, double y, double w=0, double h=0)
Definition: kdtree.h:122
drawablemuselement.h
CAKDTree::findInRange
QList< T > findInRange(QRect &area)
Definition: kdtree.h:150
CAKDTree::list
QList< T > list()
Definition: kdtree.h:58
CAKDTree::CAKDTree
CAKDTree()
Definition: kdtree.h:75
CAKDTree::addElement
void addElement(T elt)
Definition: kdtree.h:83
CAKDTree::getMaxX
double getMaxX()
Definition: kdtree.h:292
drawablecontext.h
drawable.h
CAKDTree::size
int size()
Definition: kdtree.h:57
CADrawableContext
Definition: drawablecontext.h:18
CAVoice::staff
CAStaff * staff()
Definition: voice.h:29
muselement.h
CAKDTree::findNearestDown
T findNearestDown(double y)
Definition: kdtree.h:273
voice.h
CAKDTree::clear
void clear(bool autoDelete=true)
Definition: kdtree.h:104
CAKDTree::_mapX
QMultiMap< double, T > _mapX
Definition: kdtree.h:64
CAPlayable::voice
CAVoice * voice()
Definition: playable.h:31