Canorus  0.7
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
kdtree.h
Go to the documentation of this file.
1 
8 #ifndef KDTREE_H
9 #define KDTREE_H
10 
11 #include <QList>
12 #include <QRect>
13 
14 #include "drawable/drawable.h"
17 
18 #include "core/kdtree.h"
19 #include "core/muselement.h"
20 #include "core/playable.h"
21 #include "core/voice.h"
22 
23 /*class Node {
24 public:
25  CADrawable *elt; // pointer to the element
26  CADrawable *right, *left; // pointer to the left/right son
27  int x1,y1,x2,y2; // element keys
28 };*/
29 
30 template <typename T>
31 class CAKDTree {
32 public:
33  CAKDTree();
34 
35  void addElement(T elt);
36  bool removeElement(T elt);
37  T removeElement(double x, double y, bool autoDelete=true);
38  void import(CAKDTree *tree);
39 
40  QList<T> findInRange(double x, double y, double w=0, double h=0);
41  QList<T> findInRange(QRect &area);
42  T findNearestLeft(double x, bool timeBased=false, CADrawableContext *context=0, CAVoice *voice=0);
43  T findNearestRight(double x, bool timeBased=false, CADrawableContext *context=0, CAVoice *voice=0);
44  T findNearestUp(double y);
45  T findNearestDown(double y);
46 
47  double getMaxX();
48  double getMaxY();
49 
50  void clear(bool autoDelete=true);
51  inline int size() { return _list.size(); }
52  T at(int i) { return _list[i]; }
53  QList<T>& list() { return _list; }
54 
55 private:
57  // Basic properties //
59  QList<T> _list; // List of all the drawable elements.
60  double _maxX, _maxY; // MaxX and MaxY bound of the end of the most-right and the most-bottom elements.
61 
62  void calculateMaxXY();
63 };
64 
86 template <typename T>
88  _maxX = 0;
89  _maxY = 0;
90 }
91 
95 template <typename T>
97  _list << elt;
98 
99  if (static_cast<CADrawable*>(elt)->xPos() + static_cast<CADrawable*>(elt)->width() > _maxX)
100  _maxX = static_cast<CADrawable*>(elt)->xPos() + static_cast<CADrawable*>(elt)->width();
101  if (static_cast<CADrawable*>(elt)->yPos() + static_cast<CADrawable*>(elt)->height() > _maxY)
102  _maxY = static_cast<CADrawable*>(elt)->yPos() + static_cast<CADrawable*>(elt)->height();
103 }
104 
109 template <typename T>
111  delete elt;
112 
113  return _list.removeAll(elt);
114 }
115 
121 template <typename T>
122 T CAKDTree<T>::removeElement(double x, double y, bool autoDelete) {
123  T elt;
124  for (int i=0; i<_list.size(); i++) {
125  if (static_cast<CADrawable*>(_list.at(i))->bBox().contains(x,y)) {
126  elt = _list[i];
127  _list.removeAt(i);
128  if (autoDelete) delete elt;
129 
130  calculateMaxXY();
131 
132  return elt;
133  }
134  }
135 
136  return 0;
137 }
138 
143 template <typename T>
144 void CAKDTree<T>::clear(bool autoDelete) {
145  if (autoDelete) {
146  for (int i=0; i<_list.size(); i++)
147  delete _list[i];
148  }
149 
150  _list.clear();
151 }
152 #include <iostream>
157 template <typename T>
158 QList<T> CAKDTree<T>::findInRange(double x, double y, double w, double h) {
159  QList<T> l;
160 
161  for (int i=0; i<_list.size(); i++) {
162  if ( ((static_cast<CADrawable*>(_list[i])->xPos() <= x+w) && // The object is normal and fits into the area
163  (static_cast<CADrawable*>(_list[i])->yPos() <= y+h) &&
164  (static_cast<CADrawable*>(_list[i])->xPos() + static_cast<CADrawable*>(_list[i])->width() >= x) &&
165  (static_cast<CADrawable*>(_list[i])->yPos() + static_cast<CADrawable*>(_list[i])->height() >= y)) ||
166  ((static_cast<CADrawable*>(_list[i])->width() == 0) && // The object is unlimited in width (eg. contexts)
167  (static_cast<CADrawable*>(_list[i])->yPos() <= y+h) &&
168  (static_cast<CADrawable*>(_list[i])->yPos() + static_cast<CADrawable*>(_list[i])->height() >= y)) ||
169  ((static_cast<CADrawable*>(_list[i])->height() == 0) && // The object is unlimited in height (eg. helper lines)
170  (static_cast<CADrawable*>(_list[i])->xPos() <= x+w) &&
171  (static_cast<CADrawable*>(_list[i])->xPos() + static_cast<CADrawable*>(_list[i])->width() >= x))
172  ) {
173  l << _list[i];
174  }
175  }
176 
177  return l;
178 }
179 
185 template <typename T>
186 QList<T> CAKDTree<T>::findInRange(QRect &rect) {
187  return findInRange(rect.x(), rect.y(), rect.width(), rect.height());
188 }
189 
198 template <typename T>
199 T CAKDTree<T>::findNearestLeft(double x, bool timeBased, CADrawableContext *context, CAVoice *voice) {
200  if (_list.isEmpty())
201  return 0;
202 
203  CADrawable *elt=0;
204  int i;
205  for (i=0; i < _list.size(); i++) {
206  if ( static_cast<CADrawableMusElement*>(_list[i])->musElement() && // drawable must have a music element
207  ( !elt || (timeBased?(static_cast<CADrawable*>(_list[i]))->xPos():(static_cast<CADrawable*>(_list[i]))->xPos()) > (timeBased?elt->xPos():elt->xPos()) ) && // element's X is lesser than the already found element's X
208  ( ( timeBased?(static_cast<CADrawable*>(_list[i]))->xPos():(static_cast<CADrawable*>(_list[i]))->xPos() ) < x) && // element's X is lesser than the given X
209  ( !context || static_cast<CADrawableMusElement*>(_list[i])->drawableContext() == context ) && // compare contexts
210  ( !voice || // compare voices
211  (
212  !(static_cast<CADrawableMusElement*>(_list[i]))->musElement()->isPlayable() && // if the element isn't playable, see if it has the same context as the voice
213  ((static_cast<CADrawableMusElement*>(_list[i]))->musElement()->context() == voice->staff() && voice->contains(static_cast<CADrawableMusElement*>(_list[i])->musElement()))
214  ||
215  (static_cast<CADrawableMusElement*>(_list[i]))->musElement()->isPlayable() && // if the element is playable, see if it has the exactly same voice
216  static_cast<CAPlayable*>(static_cast<CADrawableMusElement*>(_list[i])->musElement())->voice() == voice
217  )
218  )
219  ) {
220  elt = static_cast<CADrawable*>(_list[i]);
221  }
222  }
223 
224  return static_cast<T>(elt);
225 }
226 
235 template <typename T>
236 T CAKDTree<T>::findNearestRight(double x, bool timeBased, CADrawableContext *context, CAVoice *voice) {
237  if (_list.isEmpty())
238  return 0;
239 
240  CADrawable *elt=0;
241  int i;
242  for (i=0; i < _list.size(); i++) {
243  if ( static_cast<CADrawableMusElement*>(_list[i])->musElement() && // drawable must have a music element
244  ( !elt || (timeBased?(static_cast<CADrawable*>(_list[i]))->xPos():(static_cast<CADrawable*>(_list[i]))->xPos()) < (timeBased?elt->xPos():elt->xPos()) ) && // element's X is greater than the already found element's X
245  ( ( timeBased?(static_cast<CADrawable*>(_list[i]))->xPos():(static_cast<CADrawable*>(_list[i]))->xPos() ) > x) && // element's X is lesser than the given X
246  ( !context || static_cast<CADrawableMusElement*>(_list[i])->drawableContext() == context ) && // compare contexts
247  ( !voice || // compare voices
248  (
249  !(static_cast<CADrawableMusElement*>(_list[i]))->musElement()->isPlayable() && // if the element isn't playable, see if it has the same context as the voice
250  ((static_cast<CADrawableMusElement*>(_list[i]))->musElement()->context() == voice->staff() && voice->contains((static_cast<CADrawableMusElement*>(_list[i]))->musElement()))
251  ||
252  (static_cast<CADrawableMusElement*>(_list[i]))->musElement()->isPlayable() && // if the element is playable, see if it has the exactly same voice
253  static_cast<CAPlayable*>(static_cast<CADrawableMusElement*>(_list[i])->musElement())->voice() == voice
254  )
255  )
256  ) {
257  elt = static_cast<CADrawable*>(_list[i]);
258  }
259  }
260 
261  return static_cast<T>(elt);
262 }
263 
272 template <typename T>
274  if (_list.isEmpty())
275  return 0;
276 
277  CADrawable *elt=0;
278  int i;
279  for (i=0; i<_list.size(); i++) {
280  if ( ((!elt) || ((static_cast<CADrawable*>(_list[i])->yPos() + static_cast<CADrawable*>(_list[i])->height()) > (elt->yPos() + elt->height())))
281  && ((static_cast<CADrawable*>(_list[i])->yPos()+ static_cast<CADrawable*>(_list[i])->height()) < y) ) {
282  elt = static_cast<CADrawable*>(_list[i]);
283  }
284  }
285  return static_cast<T>(elt);
286 
287 }
288 
297 template <typename T>
299  if (_list.isEmpty())
300  return 0;
301 
302  CADrawable *elt=0;
303  int i;
304  for (i=0; i<_list.size(); i++) {
305  if ( ((!elt) || (static_cast<CADrawable*>(_list[i])->yPos() < elt->yPos())) && (static_cast<CADrawable*>(_list[i])->yPos() > y) ) {
306  elt = static_cast<CADrawable*>(_list[i]);
307  }
308  }
309 
310  return static_cast<T>(elt);
311 }
312 
317 template <typename T>
319  return _maxX;
320 }
321 
326 template <typename T>
328  return _maxY;
329 }
330 
336 template <typename T>
338  _maxX = 0;
339  _maxY = 0;
340  for (int i=0; i<_list.size(); i++) {
341  if (static_cast<CADrawable*>(_list[i])->xPos() + static_cast<CADrawable*>(_list[i])->width() > _maxX)
342  _maxX = static_cast<CADrawable*>(_list[i])->xPos() + static_cast<CADrawable*>(_list[i])->width();
343  if (static_cast<CADrawable*>(_list[i])->yPos() + static_cast<CADrawable*>(_list[i])->height() > _maxY)
344  _maxY = static_cast<CADrawable*>(_list[i])->yPos() + static_cast<CADrawable*>(_list[i])->height();
345  }
346 }
347 
352 template <typename T>
354  for (int i=0; i<tree->list().size(); i++)
355  _list += tree->list().at(i)->clone();
356 
357  calculateMaxXY();
358 }
359 #endif
360