Krita Source Code Documentation
Loading...
Searching...
No Matches
KoRTree.h
Go to the documentation of this file.
1/* This file is part of the KDE project
2 SPDX-FileCopyrightText: 2006 Thorsten Zachmann <zachmann@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5
6 Based on code from Wolfgang Baer - WBaer@gmx.de
7*/
8
9#ifndef KORTREE_H
10#define KORTREE_H
11
12#include <QPair>
13#include <QMap>
14#include <QList>
15#include <QVector>
16#include <QPointF>
17#include <QRectF>
18#include <QVarLengthArray>
19
20#include <QDebug>
21#include "kis_assert.h"
22
23// #define CALLIGRA_RTREE_DEBUG
24#ifdef CALLIGRA_RTREE_DEBUG
25#include <QPainter>
26#endif
27
37template <typename T>
39{
40public:
47 KoRTree(int capacity, int minimum);
48
52 virtual ~KoRTree();
53
63 virtual void insert(const QRectF& bb, const T& data);
64
69 bool contains(const T &data);
70
79 void remove(const T& data);
80
89 virtual QList<T> intersects(const QRectF& rect) const;
90
99 QList<T> contains(const QPointF &point) const;
100
109 QList<T> contained(const QRectF &point) const;
110
118
126
127 virtual void clear() {
128 delete m_root;
129 m_root = createLeafNode(m_capacity + 1, 0, 0);
130 m_leafMap.clear();
131 }
132
133#ifdef CALLIGRA_RTREE_DEBUG
139 void paint(QPainter & p) const;
140
144 void debug() const;
145#endif
146
147protected:
148 class NonLeafNode;
149 class LeafNode;
150
151 class Node
152 {
153 public:
154#ifdef CALLIGRA_RTREE_DEBUG
155 static int nodeIdCnt;
156#endif
157 Node(int capacity, int level, Node * parent);
158 virtual ~Node() {}
159
160 virtual void remove(int index);
161 // move node between nodes of the same type from node
162 virtual void move(Node * node, int index) = 0;
163
164 virtual LeafNode * chooseLeaf(const QRectF& bb) = 0;
165 virtual NonLeafNode * chooseNode(const QRectF& bb, int level) = 0;
166
167 virtual void intersects(const QRectF& rect, QMap<int, T> & result) const = 0;
168 virtual void contains(const QPointF & point, QMap<int, T> & result) const = 0;
169 virtual void contained(const QRectF & point, QMap<int, T> & result) const = 0;
170
171 virtual void keys(QList<QRectF> & result) const = 0;
172 virtual void values(QMap<int, T> & result) const = 0;
173
174 virtual Node * parent() const {
175 return m_parent;
176 }
177 virtual void setParent(Node * parent) {
179 }
180
181 virtual int childCount() const {
182 return m_counter;
183 }
184
185 virtual const QRectF& boundingBox() const {
186 return m_boundingBox;
187 }
188 virtual void updateBoundingBox();
189
190 virtual const QRectF& childBoundingBox(int index) const {
191 return m_childBoundingBox[index];
192 }
193 virtual void setChildBoundingBox(int index, const QRectF& rect) {
194 m_childBoundingBox[index] = rect;
195 }
196
197 virtual void clear();
198 virtual bool isRoot() const {
199 return m_parent == 0;
200 }
201 virtual bool isLeaf() const {
202 return false;
203 }
204
205 virtual int place() const {
206 return m_place;
207 }
208 virtual void setPlace(int place) {
209 m_place = place;
210 }
211
212 virtual int level() const {
213 return m_level;
214 }
215 virtual void setLevel(int level) {
216 m_level = level;
217 }
218
219#ifdef CALLIGRA_RTREE_DEBUG
220 virtual int nodeId() const {
221 return m_nodeId;
222 }
223
224 virtual void paint(QPainter & p, int level) const = 0;
225 virtual void debug(QString line) const = 0;
226
227 protected:
228#define levelColorSize 5
229 static QColor levelColor[levelColorSize];
230 virtual void paintRect(QPainter & p, int level) const;
231#endif
232 protected:
237 // the position in the parent
239#ifdef CALLIGRA_RTREE_DEBUG
240 int m_nodeId;
241#endif
243 };
244
245class NonLeafNode : virtual public Node
246 {
247 public:
248 NonLeafNode(int capacity, int level, Node * parent);
249 ~NonLeafNode() override;
250
251 virtual void insert(const QRectF& bb, Node * data);
252 void remove(int index) override;
253 void move(Node * node, int index) override;
254
255 LeafNode * chooseLeaf(const QRectF& bb) override;
256 NonLeafNode * chooseNode(const QRectF& bb, int level) override;
257
258 void intersects(const QRectF& rect, QMap<int, T> & result) const override;
259 void contains(const QPointF & point, QMap<int, T> & result) const override;
260 void contained(const QRectF & point, QMap<int, T> & result) const override;
261
262 void keys(QList<QRectF> & result) const override;
263 void values(QMap<int, T> & result) const override;
264
265 virtual Node * getNode(int index) const;
266
267#ifdef CALLIGRA_RTREE_DEBUG
268 virtual void paint(QPainter & p, int level) const;
269 virtual void debug(QString line) const;
270#endif
271 protected:
272 virtual Node * getLeastEnlargement(const QRectF& bb) const;
273
275 };
276
277class LeafNode : virtual public Node
278 {
279 public:
280 static int dataIdCounter;
281
282 LeafNode(int capacity, int level, Node * parent);
283 ~LeafNode() override;
284
285 virtual void insert(const QRectF& bb, const T& data, int id);
286 void remove(int index) override;
287 virtual void remove(const T& data);
288 void move(Node * node, int index) override;
289
290 LeafNode * chooseLeaf(const QRectF& bb) override;
291 NonLeafNode * chooseNode(const QRectF& bb, int level) override;
292
293 void intersects(const QRectF& rect, QMap<int, T> & result) const override;
294 void contains(const QPointF & point, QMap<int, T> & result) const override;
295 void contained(const QRectF & point, QMap<int, T> & result) const override;
296
297 void keys(QList<QRectF> & result) const override;
298 void values(QMap<int, T> & result) const override;
299
300 virtual const T& getData(int index) const;
301 virtual int getDataId(int index) const;
302
303 bool isLeaf() const override {
304 return true;
305 }
306
307#ifdef CALLIGRA_RTREE_DEBUG
308 virtual void debug(QString line) const;
309 virtual void paint(QPainter & p, int level) const;
310#endif
311 protected:
314 };
315
316 // factory methods
317 virtual LeafNode* createLeafNode(int capacity, int level, Node * parent) {
318 return new LeafNode(capacity, level, parent);
319 }
320 virtual NonLeafNode* createNonLeafNode(int capacity, int level, Node * parent) {
321 return new NonLeafNode(capacity, level, parent);
322 }
323
324 // methods for insert
325 QPair<Node *, Node *> splitNode(Node * node);
326 QPair<int, int> pickSeeds(Node * node);
327 QPair<int, int> pickNext(Node * node, QVector<bool> & marker, Node * group1, Node * group2);
328 virtual void adjustTree(Node * node1, Node * node2);
329 void insertHelper(const QRectF& bb, const T& data, int id);
330
331 // methods for delete
332 void insert(Node * node);
333 virtual void condenseTree(Node * node, QVector<Node *> & reinsert);
334
338 QMap<T, LeafNode *> m_leafMap;
339};
340
341template <typename T>
342KoRTree<T>::KoRTree(int capacity, int minimum)
343 : m_capacity(capacity)
344 , m_minimum(minimum)
345 , m_root(createLeafNode(m_capacity + 1, 0, 0))
346{
347 if (minimum > capacity / 2)
348 qFatal("KoRTree::KoRTree minimum can be maximal capacity/2");
349 //debugFlake << "root node " << m_root->nodeId();
350}
351
352template <typename T>
354{
355 delete m_root;
356}
357
358template <typename T>
359void KoRTree<T>::insert(const QRectF& bb, const T& data)
360{
361 // check if the shape is not already registered
362 KIS_SAFE_ASSERT_RECOVER_NOOP(!m_leafMap[data]);
363
364 insertHelper(bb, data, LeafNode::dataIdCounter++);
365}
366
367template <typename T>
368void KoRTree<T>::insertHelper(const QRectF& bb, const T& data, int id)
369{
370 QRectF nbb(bb.normalized());
371 // This has to be done as it is not possible to use QRectF::united() with a isNull()
372 if (nbb.isNull()) {
373 qWarning() << "KoRTree::insert boundingBox isNull setting size to" << nbb.size();
374
375 nbb.setWidth(0.0001);
376 nbb.setHeight(0.0001);
377 }
378 else {
379 // This has to be done as QRectF::intersects() return false if the rect does not have any area overlapping.
380 // If there is no width or height there is no area and therefore no overlapping.
381 if ( nbb.width() == 0 ) {
382 nbb.setWidth(0.0001);
383 }
384 if ( nbb.height() == 0 ) {
385 nbb.setHeight(0.0001);
386 }
387 }
388
389 LeafNode * leaf = m_root->chooseLeaf(nbb);
390 //debugFlake << " leaf" << leaf->nodeId() << nbb;
391
392 if (leaf->childCount() < m_capacity) {
393 leaf->insert(nbb, data, id);
394 m_leafMap[data] = leaf;
395 adjustTree(leaf, 0);
396 } else {
397 leaf->insert(nbb, data, id);
398 m_leafMap[data] = leaf;
399 QPair<Node *, Node *> newNodes = splitNode(leaf);
400 LeafNode * l = dynamic_cast<LeafNode *>(newNodes.first);
401 if (l)
402 for (int i = 0; i < l->childCount(); ++i)
403 m_leafMap[l->getData(i)] = l;
404 l = dynamic_cast<LeafNode *>(newNodes.second);
405 if (l)
406 for (int i = 0; i < l->childCount(); ++i)
407 m_leafMap[l->getData(i)] = l;
408
409 adjustTree(newNodes.first, newNodes.second);
410 }
411}
412
413template <typename T>
415{
416 if (node->level() == m_root->level()) {
417 adjustTree(m_root, node);
418 } else {
419 QRectF bb(node->boundingBox());
420 NonLeafNode * newParent = m_root->chooseNode(bb, node->level() + 1);
421
422 newParent->insert(bb, node);
423
424 QPair<Node *, Node *> newNodes(node, 0);
425 if (newParent->childCount() > m_capacity) {
426 newNodes = splitNode(newParent);
427 }
428 adjustTree(newNodes.first, newNodes.second);
429 }
430}
431
432template <typename T>
433bool KoRTree<T>::contains(const T &data)
434{
435 return m_leafMap[data];
436}
437
438
439template <typename T>
440void KoRTree<T>::remove(const T&data)
441{
442 //debugFlake << "KoRTree remove";
443 LeafNode * leaf = m_leafMap[data];
444
445 // Trying to remove inexistent leaf. Most probably, this leaf hasn't been added
446 // to the shape manager correctly
448
449 m_leafMap.remove(data);
450 leaf->remove(data);
451
459 QVector<Node *> reinsert;
460 condenseTree(leaf, reinsert);
461
462 for (int i = 0; i < reinsert.size(); ++i) {
463 if (reinsert[i]->isLeaf()) {
464 LeafNode * leaf = dynamic_cast<LeafNode *>(reinsert[i]);
465 KIS_SAFE_ASSERT_RECOVER(leaf) { reinsert[i]->clear(); delete reinsert[i]; continue; } // mostly for the sake of Coverity
466 for (int j = 0; j < leaf->childCount(); ++j) {
467 insertHelper(leaf->childBoundingBox(j), leaf->getData(j), leaf->getDataId(j));
468 }
469 // clear is needed as the data items are not removed when insert into a new node
470 leaf->clear();
471 delete leaf;
472 } else {
473 NonLeafNode * node = dynamic_cast<NonLeafNode *>(reinsert[i]);
474 KIS_SAFE_ASSERT_RECOVER(node) { reinsert[i]->clear(); delete reinsert[i]; continue; } // mostly for the sake of Coverity
475 for (int j = 0; j < node->childCount(); ++j) {
476 insert(node->getNode(j));
477 }
478 // clear is needed as the data items are not removed when insert into a new node
479 node->clear();
480 delete node;
481 }
482 }
483}
484
485template <typename T>
487{
488 QMap<int, T> found;
489 m_root->intersects(rect, found);
490 return found.values();
491}
492
493template <typename T>
494QList<T> KoRTree<T>::contains(const QPointF &point) const
495{
496 QMap<int, T> found;
497 m_root->contains(point, found);
498 return found.values();
499}
500
501template <typename T>
503{
504 QMap<int, T> found;
505 m_root->contained(rect, found);
506 return found.values();
507}
508
509
510template <typename T>
512{
513 QList<QRectF> found;
514 m_root->keys(found);
515 return found;
516}
517
518template <typename T>
520{
521 QMap<int, T> found;
522 m_root->values(found);
523 return found.values();
524}
525
526#ifdef CALLIGRA_RTREE_DEBUG
527template <typename T>
528void KoRTree<T>::paint(QPainter & p) const
529{
530 if (m_root) {
531 m_root->paint(p, 0);
532 }
533}
534
535template <typename T>
536void KoRTree<T>::debug() const
537{
538 QString prefix("");
539 m_root->debug(prefix);
540}
541#endif
542
543template <typename T>
544QPair< typename KoRTree<T>::Node*, typename KoRTree<T>::Node* > KoRTree<T>::splitNode(typename KoRTree<T>::Node* node)
545{
546 //debugFlake << "KoRTree::splitNode" << node;
547 Node * n1;
548 Node * n2;
549 if (node->isLeaf()) {
550 n1 = createLeafNode(m_capacity + 1, node->level(), node->parent());
551 n2 = createLeafNode(m_capacity + 1, node->level(), node->parent());
552 } else {
553 n1 = createNonLeafNode(m_capacity + 1, node->level(), node->parent());
554 n2 = createNonLeafNode(m_capacity + 1, node->level(), node->parent());
555 }
556 //debugFlake << " n1" << n1 << n1->nodeId();
557 //debugFlake << " n2" << n2 << n2->nodeId();
558
559 QVector<bool> marker(m_capacity + 1);
560
561 QPair<int, int> seeds(pickSeeds(node));
562
563 n1->move(node, seeds.first);
564 n2->move(node, seeds.second);
565
566 marker[seeds.first] = true;
567 marker[seeds.second] = true;
568
569 // There is one more in a node to split than the capacity and as we
570 // already put the seeds in the new nodes subtract them.
571 int remaining = m_capacity + 1 - 2;
572
573 while (remaining > 0) {
574 if (m_minimum - n1->childCount() == remaining) {
575 for (int i = 0; i < m_capacity + 1; ++i) {
576 if (!marker[i]) {
577 n1->move(node, i);
578 --remaining;
579 }
580 }
581 } else if (m_minimum - n2->childCount() == remaining) {
582 for (int i = 0; i < m_capacity + 1; ++i) {
583 if (!marker[i]) {
584 n2->move(node, i);
585 --remaining;
586 }
587 }
588 } else {
589 QPair<int, int> next(pickNext(node, marker, n1, n2));
590
591 if (next.first == 0) {
592 n1->move(node, next.second);
593 } else {
594 n2->move(node, next.second);
595 }
596 --remaining;
597 }
598 }
599 Q_ASSERT(n1->childCount() + n2->childCount() == node->childCount());
600
601 // move the data back to the old node
602 // this has to be done as the current node is already in the tree.
603 node->clear();
604 for (int i = 0; i < n1->childCount(); ++i) {
605 node->move(n1, i);
606 }
607
608 //debugFlake << " delete n1" << n1 << n1->nodeId();
609 // clear is needed as the data items are not removed
610 n1->clear();
611 delete n1;
612 return qMakePair(node, n2);
613}
614
615template <typename T>
616QPair<int, int> KoRTree<T>::pickSeeds(Node *node)
617{
618 int s1 = 0;
619 int s2 = 1;
620 qreal max = 0;
621 for (int i = 0; i < m_capacity + 1; ++i) {
622 for (int j = i+1; j < m_capacity + 1; ++j) {
623 if (i != j) {
624 QRectF bb1(node->childBoundingBox(i));
625 QRectF bb2(node->childBoundingBox(j));
626 QRectF comp(node->childBoundingBox(i).united(node->childBoundingBox(j)));
627 qreal area = comp.width() * comp.height() - bb1.width() * bb1.height() - bb2.width() * bb2.height();
628 //debugFlake << " ps" << i << j << area;
629 if (area > max) {
630 max = area;
631 s1 = i;
632 s2 = j;
633 }
634 }
635 }
636 }
637 return qMakePair(s1, s2);
638}
639
640template <typename T>
641QPair<int, int> KoRTree<T>::pickNext(Node * node, QVector<bool> & marker, Node * group1, Node * group2)
642{
643 //debugFlake << "KoRTree::pickNext" << marker;
644 qreal max = -1.0;
645 int select = 0;
646 int group = 0;
647 for (int i = 0; i < m_capacity + 1; ++i) {
648 if (marker[i] == false) {
649 QRectF bb1 = group1->boundingBox().united(node->childBoundingBox(i));
650 QRectF bb2 = group2->boundingBox().united(node->childBoundingBox(i));
651 qreal d1 = bb1.width() * bb1.height() - group1->boundingBox().width() * group1->boundingBox().height();
652 qreal d2 = bb2.width() * bb2.height() - group2->boundingBox().width() * group2->boundingBox().height();
653 qreal diff = qAbs(d1 - d2);
654 //debugFlake << " diff" << diff << i << d1 << d2;
655 if (diff > max) {
656 max = diff;
657 select = i;
658 //debugFlake << " i =" << i;
659 if (qAbs(d1) > qAbs(d2)) {
660 group = 1;
661 } else {
662 group = 0;
663 }
664 //debugFlake << " group =" << group;
665 }
666 }
667 }
668 marker[select] = true;
669 return qMakePair(group, select);
670}
671
672template <typename T>
673void KoRTree<T>::adjustTree(Node *node1, Node *node2)
674{
675 //debugFlake << "KoRTree::adjustTree";
676 if (node1->isRoot()) {
677 //debugFlake << " root";
678 if (node2) {
679 NonLeafNode * newRoot = createNonLeafNode(m_capacity + 1, node1->level() + 1, 0);
680 newRoot->insert(node1->boundingBox(), node1);
681 newRoot->insert(node2->boundingBox(), node2);
682 m_root = newRoot;
683 //debugFlake << "new root" << m_root->nodeId();
684 }
685 } else {
686 NonLeafNode * parent = dynamic_cast<NonLeafNode *>(node1->parent());
687 if (!parent) {
688 qFatal("KoRTree::adjustTree: no parent node found!");
689 return;
690 }
691 //QRectF pbbold( parent->boundingBox() );
692 parent->setChildBoundingBox(node1->place(), node1->boundingBox());
693 parent->updateBoundingBox();
694 //debugFlake << " bb1 =" << node1->boundingBox() << node1->place() << pbbold << "->" << parent->boundingBox() << parent->nodeId();
695
696 if (!node2) {
697 //debugFlake << " update";
698 adjustTree(parent, 0);
699 } else {
700 if (parent->childCount() < m_capacity) {
701 //debugFlake << " no split needed";
702 parent->insert(node2->boundingBox(), node2);
703 adjustTree(parent, 0);
704 } else {
705 //debugFlake << " split again";
706 parent->insert(node2->boundingBox(), node2);
707 QPair<Node *, Node *> newNodes = splitNode(parent);
708 adjustTree(newNodes.first, newNodes.second);
709 }
710 }
711 }
712}
713
714template <typename T>
716{
717 //debugFlake << "KoRTree::condenseTree begin reinsert.size()" << reinsert.size();
718 if (!node->isRoot()) {
719 Node * parent = node->parent();
720 //debugFlake << " !node->isRoot us" << node->childCount();
721
722 if (node->childCount() < m_minimum) {
723 //debugFlake << " remove node";
724 parent->remove(node->place());
725 reinsert.push_back(node);
726
734 } else {
735 //debugFlake << " update BB parent is root" << parent->isRoot();
736 parent->setChildBoundingBox(node->place(), node->boundingBox());
737 parent->updateBoundingBox();
738 }
739 condenseTree(parent, reinsert);
740 } else {
741 //debugFlake << " node->isRoot us" << node->childCount();
742 if (node->childCount() == 1 && !node->isLeaf()) {
743 //debugFlake << " usedSpace = 1";
744 NonLeafNode * n = dynamic_cast<NonLeafNode *>(node);
745 if (n) {
746 Node * kid = n->getNode(0);
747 // clear is needed as the data items are not removed
748 m_root->clear();
749 delete m_root;
750 m_root = kid;
751 m_root->setParent(0);
752 //debugFlake << " new root" << m_root;
753 } else {
754 qFatal("KoRTree::condenseTree cast to NonLeafNode failed");
755 }
756 }
757 }
758 //debugFlake << "KoRTree::condenseTree end reinsert.size()" << reinsert.size();
759}
760
761#ifdef CALLIGRA_RTREE_DEBUG
762template <typename T>
764 QColor(Qt::green),
765 QColor(Qt::red),
766 QColor(Qt::cyan),
767 QColor(Qt::magenta),
768 QColor(Qt::yellow),
769};
770
771template <class T>
773#endif
774
775template <typename T>
776KoRTree<T>::Node::Node(int capacity, int level, Node * parent)
777 : m_parent(parent)
778 , m_childBoundingBox(capacity)
779 , m_counter(0)
780 , m_place(0)
781#ifdef CALLIGRA_RTREE_DEBUG
782 , m_nodeId(nodeIdCnt++)
783#endif
784 , m_level(level)
785{
786}
787
788template <typename T>
790{
791 for (int i = index + 1; i < m_counter; ++i) {
792 m_childBoundingBox[i-1] = m_childBoundingBox[i];
793 }
794 --m_counter;
795 updateBoundingBox();
796}
797
798template <typename T>
800{
801 m_boundingBox = QRectF();
802 for (int i = 0; i < m_counter; ++i) {
803 m_boundingBox = m_boundingBox.united(m_childBoundingBox[i]);
804 }
805}
806
807template <typename T>
809{
810 m_counter = 0;
811 m_boundingBox = QRectF();
812}
813
814#ifdef CALLIGRA_RTREE_DEBUG
815template <typename T>
816void KoRTree<T>::Node::paintRect(QPainter & p, int level) const
817{
818 QColor c(Qt::black);
819 if (level < levelColorSize) {
820 c = levelColor[level];
821 }
822
823 QPen pen(c, 0);
824 p.setPen(pen);
825
826 QRectF bbdraw(this->m_boundingBox);
827 bbdraw.adjust(level * 2, level * 2, -level * 2, -level * 2);
828 p.drawRect(bbdraw);
829}
830#endif
831
832template <typename T>
833KoRTree<T>::NonLeafNode::NonLeafNode(int capacity, int level, Node * parent)
834 : Node(capacity, level, parent)
835 , m_childs(capacity)
836{
837 //debugFlake << "NonLeafNode::NonLeafNode()" << this;
838}
839
840template <typename T>
842{
843 //debugFlake << "NonLeafNode::~NonLeafNode()" << this;
844 for (int i = 0; i < this->m_counter; ++i) {
845 delete m_childs[i];
846 }
847}
848
849template <typename T>
850void KoRTree<T>::NonLeafNode::insert(const QRectF& bb, Node * data)
851{
852 m_childs[this->m_counter] = data;
853 data->setPlace(this->m_counter);
854 data->setParent(this);
855 this->m_childBoundingBox[this->m_counter] = bb;
856 this->m_boundingBox = this->m_boundingBox.united(bb);
857 //debugFlake << "NonLeafNode::insert" << this->nodeId() << data->nodeId();
858 ++this->m_counter;
859}
860
861template <typename T>
863{
864 for (int i = index + 1; i < this->m_counter; ++i) {
865 m_childs[i-1] = m_childs[i];
866 m_childs[i-1]->setPlace(i - 1);
867 }
868 Node::remove(index);
869}
870
871template <typename T>
872void KoRTree<T>::NonLeafNode::move(Node * node, int index)
873{
874 //debugFlake << "NonLeafNode::move" << this << node << index << node->nodeId() << "->" << this->nodeId();
875 NonLeafNode * n = dynamic_cast<NonLeafNode *>(node);
876 if (n) {
877 QRectF bb = n->childBoundingBox(index);
878 insert(bb, n->getNode(index));
879 }
880}
881
882template <typename T>
884{
885 return getLeastEnlargement(bb)->chooseLeaf(bb);
886}
887
888template <typename T>
890{
891 if (this->m_level > level) {
892 return getLeastEnlargement(bb)->chooseNode(bb, level);
893 } else {
894 return this;
895 }
896
897}
898
899template <typename T>
900void KoRTree<T>::NonLeafNode::intersects(const QRectF& rect, QMap<int, T> & result) const
901{
902 for (int i = 0; i < this->m_counter; ++i) {
903 if (this->m_childBoundingBox[i].intersects(rect)) {
904 m_childs[i]->intersects(rect, result);
905 }
906 }
907}
908
909template <typename T>
910void KoRTree<T>::NonLeafNode::contains(const QPointF & point, QMap<int, T> & result) const
911{
912 for (int i = 0; i < this->m_counter; ++i) {
913 if (this->m_childBoundingBox[i].contains(point)) {
914 m_childs[i]->contains(point, result);
915 }
916 }
917}
918
919template <typename T>
920void KoRTree<T>::NonLeafNode::contained(const QRectF& rect, QMap<int, T> & result) const
921{
922 for (int i = 0; i < this->m_counter; ++i) {
923 if (this->m_childBoundingBox[i].intersects(rect)) {
924 m_childs[i]->contained(rect, result);
925 }
926 }
927}
928
929template <typename T>
931{
932 for (int i = 0; i < this->m_counter; ++i) {
933 m_childs[i]->keys(result);
934 }
935}
936
937template <typename T>
938void KoRTree<T>::NonLeafNode::values(QMap<int, T> & result) const
939{
940 for (int i = 0; i < this->m_counter; ++i) {
941 m_childs[i]->values(result);
942 }
943}
944
945template <typename T>
947{
948 return m_childs[index];
949}
950
951template <typename T>
953{
954 //debugFlake << "NonLeafNode::getLeastEnlargement";
955 QVarLengthArray<qreal> area(this->m_counter);
956 for (int i = 0; i < this->m_counter; ++i) {
957 QSizeF big(this->m_childBoundingBox[i].united(bb).size());
958 area[i] = big.width() * big.height() - this->m_childBoundingBox[i].width() * this->m_childBoundingBox[i].height();
959 }
960
961 int minIndex = 0;
962 qreal minArea = area[minIndex];
963 //debugFlake << " min" << minIndex << minArea;
964
965 for (int i = 1; i < this->m_counter; ++i) {
966 if (area[i] < minArea) {
967 minIndex = i;
968 minArea = area[i];
969 //debugFlake << " min" << minIndex << minArea;
970 }
971 }
972
973 return m_childs[minIndex];
974}
975
976#ifdef CALLIGRA_RTREE_DEBUG
977template <typename T>
978void KoRTree<T>::NonLeafNode::debug(QString line) const
979{
980 for (int i = 0; i < this->m_counter; ++i) {
981 qDebug("%s %d %d", qPrintable(line), this->nodeId(), i);
982 m_childs[i]->debug(line + " ");
983 }
984}
985
986template <typename T>
987void KoRTree<T>::NonLeafNode::paint(QPainter & p, int level) const
988{
989 this->paintRect(p, level);
990 for (int i = 0; i < this->m_counter; ++i) {
991 m_childs[i]->paint(p, level + 1);
992 }
993
994}
995#endif
996
997template <class T>
999
1000template <typename T>
1001KoRTree<T>::LeafNode::LeafNode(int capacity, int level, Node * parent)
1002 : Node(capacity, level, parent)
1003 , m_data(capacity)
1004 , m_dataIds(capacity)
1005{
1006 //debugFlake << "LeafNode::LeafNode" << this;
1007}
1008
1009template <typename T>
1011{
1012 //debugFlake << "LeafNode::~LeafNode" << this;
1013}
1014
1015template <typename T>
1016void KoRTree<T>::LeafNode::insert(const QRectF& bb, const T& data, int id)
1017{
1018 m_data[this->m_counter] = data;
1019 m_dataIds[this->m_counter] = id;
1020 this->m_childBoundingBox[this->m_counter] = bb;
1021 this->m_boundingBox = this->m_boundingBox.united(bb);
1022 ++this->m_counter;
1023}
1024
1025template <typename T>
1027{
1028 for (int i = index + 1; i < this->m_counter; ++i) {
1029 m_data[i-1] = m_data[i];
1030 m_dataIds[i-1] = m_dataIds[i];
1031 }
1032 Node::remove(index);
1033}
1034
1035template <typename T>
1037{
1038 int old_counter = this->m_counter;
1039 for (int i = 0; i < this->m_counter; ++i) {
1040 if (m_data[i] == data) {
1041 //debugFlake << "LeafNode::remove id" << i;
1042 remove(i);
1043 break;
1044 }
1045 }
1046 if (old_counter == this->m_counter) {
1047 qWarning() << "LeafNode::remove( const T&data) data not found";
1048 }
1049}
1050
1051template <typename T>
1052void KoRTree<T>::LeafNode::move(Node * node, int index)
1053{
1054 LeafNode * n = dynamic_cast<LeafNode*>(node);
1055 if (n) {
1056 //debugFlake << "LeafNode::move" << this << node << index
1057 // << node->nodeId() << "->" << this->nodeId() << n->childBoundingBox( index );
1058 QRectF bb = n->childBoundingBox(index);
1059 insert(bb, n->getData(index), n->getDataId(index));
1060 }
1061}
1062
1063template <typename T>
1065{
1066 Q_UNUSED(bb);
1067 return this;
1068}
1069
1070template <typename T>
1071typename KoRTree<T>::NonLeafNode * KoRTree<T>::LeafNode::chooseNode(const QRectF& bb, int level)
1072{
1073 Q_UNUSED(bb);
1074 Q_UNUSED(level);
1075 qFatal("LeafNode::chooseNode called. This should not happen!");
1076 return 0;
1077}
1078
1079template <typename T>
1080void KoRTree<T>::LeafNode::intersects(const QRectF& rect, QMap<int, T> & result) const
1081{
1082 for (int i = 0; i < this->m_counter; ++i) {
1083 if (this->m_childBoundingBox[i].intersects(rect)) {
1084 result.insert(m_dataIds[i], m_data[i]);
1085 }
1086 }
1087}
1088
1089template <typename T>
1090void KoRTree<T>::LeafNode::contains(const QPointF & point, QMap<int, T> & result) const
1091{
1092 for (int i = 0; i < this->m_counter; ++i) {
1093 if (this->m_childBoundingBox[i].contains(point)) {
1094 result.insert(m_dataIds[i], m_data[i]);
1095 }
1096 }
1097}
1098
1099template <typename T>
1100void KoRTree<T>::LeafNode::contained(const QRectF& rect, QMap<int, T> & result) const
1101{
1102 for (int i = 0; i < this->m_counter; ++i) {
1103 if (rect.contains(this->m_childBoundingBox[i])) {
1104 result.insert(m_dataIds[i], m_data[i]);
1105 }
1106 }
1107}
1108
1109template <typename T>
1111{
1112 for (int i = 0; i < this->m_counter; ++i) {
1113 result.push_back(this->m_childBoundingBox[i]);
1114 }
1115}
1116
1117template <typename T>
1118void KoRTree<T>::LeafNode::values(QMap<int, T> & result) const
1119{
1120 for (int i = 0; i < this->m_counter; ++i) {
1121 result.insert(m_dataIds[i], m_data[i]);
1122 }
1123}
1124
1125template <typename T>
1126const T& KoRTree<T>::LeafNode::getData(int index) const
1127{
1128 return m_data[ index ];
1129}
1130
1131template <typename T>
1133{
1134 return m_dataIds[ index ];
1135}
1136
1137#ifdef CALLIGRA_RTREE_DEBUG
1138template <typename T>
1139void KoRTree<T>::LeafNode::debug(QString line) const
1140{
1141 for (int i = 0; i < this->m_counter; ++i) {
1142 qDebug("%s %d %d %p", qPrintable(line), this->nodeId(), i, &(m_data[i]));
1143 debugFlake << this->m_childBoundingBox[i].toRect();
1144 }
1145}
1146
1147template <typename T>
1148void KoRTree<T>::LeafNode::paint(QPainter & p, int level) const
1149{
1150 if (this->m_counter) {
1151 this->paintRect(p, level);
1152 }
1153}
1154#endif
1155
1156#endif /* KORTREE_H */
#define debugFlake
Definition FlakeDebug.h:15
QPointF s1
const Params2D p
QPointF s2
void values(QMap< int, T > &result) const override
Definition KoRTree.h:1118
virtual void insert(const QRectF &bb, const T &data, int id)
Definition KoRTree.h:1016
~LeafNode() override
Definition KoRTree.h:1010
void contained(const QRectF &point, QMap< int, T > &result) const override
Definition KoRTree.h:1100
void intersects(const QRectF &rect, QMap< int, T > &result) const override
Definition KoRTree.h:1080
virtual int getDataId(int index) const
Definition KoRTree.h:1132
bool isLeaf() const override
Definition KoRTree.h:303
QVector< int > m_dataIds
Definition KoRTree.h:313
LeafNode * chooseLeaf(const QRectF &bb) override
Definition KoRTree.h:1064
void keys(QList< QRectF > &result) const override
Definition KoRTree.h:1110
QVector< T > m_data
Definition KoRTree.h:312
virtual const T & getData(int index) const
Definition KoRTree.h:1126
static int dataIdCounter
Definition KoRTree.h:280
void move(Node *node, int index) override
Definition KoRTree.h:1052
void remove(int index) override
Definition KoRTree.h:1026
LeafNode(int capacity, int level, Node *parent)
Definition KoRTree.h:1001
NonLeafNode * chooseNode(const QRectF &bb, int level) override
Definition KoRTree.h:1071
void contains(const QPointF &point, QMap< int, T > &result) const override
Definition KoRTree.h:1090
virtual const QRectF & childBoundingBox(int index) const
Definition KoRTree.h:190
virtual void keys(QList< QRectF > &result) const =0
virtual void updateBoundingBox()
Definition KoRTree.h:799
virtual bool isLeaf() const
Definition KoRTree.h:201
virtual bool isRoot() const
Definition KoRTree.h:198
virtual int place() const
Definition KoRTree.h:205
virtual void clear()
Definition KoRTree.h:808
virtual void intersects(const QRectF &rect, QMap< int, T > &result) const =0
QRectF m_boundingBox
Definition KoRTree.h:234
virtual const QRectF & boundingBox() const
Definition KoRTree.h:185
virtual void contains(const QPointF &point, QMap< int, T > &result) const =0
virtual void setPlace(int place)
Definition KoRTree.h:208
Node(int capacity, int level, Node *parent)
Definition KoRTree.h:776
virtual int childCount() const
Definition KoRTree.h:181
virtual void contained(const QRectF &point, QMap< int, T > &result) const =0
virtual NonLeafNode * chooseNode(const QRectF &bb, int level)=0
virtual void setParent(Node *parent)
Definition KoRTree.h:177
Node * m_parent
Definition KoRTree.h:233
virtual ~Node()
Definition KoRTree.h:158
virtual LeafNode * chooseLeaf(const QRectF &bb)=0
virtual void move(Node *node, int index)=0
virtual int level() const
Definition KoRTree.h:212
virtual Node * parent() const
Definition KoRTree.h:174
virtual void values(QMap< int, T > &result) const =0
virtual void setChildBoundingBox(int index, const QRectF &rect)
Definition KoRTree.h:193
QVector< QRectF > m_childBoundingBox
Definition KoRTree.h:235
virtual void setLevel(int level)
Definition KoRTree.h:215
virtual void remove(int index)
Definition KoRTree.h:789
~NonLeafNode() override
Definition KoRTree.h:841
void contained(const QRectF &point, QMap< int, T > &result) const override
Definition KoRTree.h:920
virtual void insert(const QRectF &bb, Node *data)
Definition KoRTree.h:850
void remove(int index) override
Definition KoRTree.h:862
void intersects(const QRectF &rect, QMap< int, T > &result) const override
Definition KoRTree.h:900
NonLeafNode * chooseNode(const QRectF &bb, int level) override
Definition KoRTree.h:889
void move(Node *node, int index) override
Definition KoRTree.h:872
LeafNode * chooseLeaf(const QRectF &bb) override
Definition KoRTree.h:883
NonLeafNode(int capacity, int level, Node *parent)
Definition KoRTree.h:833
void values(QMap< int, T > &result) const override
Definition KoRTree.h:938
void keys(QList< QRectF > &result) const override
Definition KoRTree.h:930
virtual Node * getNode(int index) const
Definition KoRTree.h:946
QVector< Node * > m_childs
Definition KoRTree.h:274
virtual Node * getLeastEnlargement(const QRectF &bb) const
Definition KoRTree.h:952
void contains(const QPointF &point, QMap< int, T > &result) const override
Definition KoRTree.h:910
The KoRTree class is a template class that provides a R-tree.
Definition KoRTree.h:39
virtual LeafNode * createLeafNode(int capacity, int level, Node *parent)
Definition KoRTree.h:317
virtual void condenseTree(Node *node, QVector< Node * > &reinsert)
Definition KoRTree.h:715
void remove(const T &data)
Remove a data item from the tree.
Definition KoRTree.h:440
bool contains(const T &data)
Show if a shape is a part of the tree.
Definition KoRTree.h:433
QPair< int, int > pickSeeds(Node *node)
Definition KoRTree.h:616
QList< QRectF > keys() const
Find all data rectangles The order is NOT guaranteed to be the same as that used by values().
Definition KoRTree.h:511
void insertHelper(const QRectF &bb, const T &data, int id)
Definition KoRTree.h:368
QList< T > contains(const QPointF &point) const
Find all data item which contain the point The items are sorted by insertion time in ascending order.
Definition KoRTree.h:494
virtual ~KoRTree()
Destructor.
Definition KoRTree.h:353
int m_minimum
Definition KoRTree.h:336
KoRTree(int capacity, int minimum)
Constructor.
Definition KoRTree.h:342
virtual void insert(const QRectF &bb, const T &data)
Insert data item into the tree.
Definition KoRTree.h:359
QList< T > contained(const QRectF &point) const
Find all data item which contain the point The items are sorted by insertion time in ascending order.
Definition KoRTree.h:502
virtual QList< T > intersects(const QRectF &rect) const
Find all data items which intersects rect The items are sorted by insertion time in ascending order.
Definition KoRTree.h:486
QList< T > values() const
Find all data items The order is NOT guaranteed to be the same as that used by keys().
Definition KoRTree.h:519
virtual void clear()
Definition KoRTree.h:127
QPair< int, int > pickNext(Node *node, QVector< bool > &marker, Node *group1, Node *group2)
Definition KoRTree.h:641
Node * m_root
Definition KoRTree.h:337
virtual NonLeafNode * createNonLeafNode(int capacity, int level, Node *parent)
Definition KoRTree.h:320
void insert(Node *node)
Definition KoRTree.h:414
virtual void adjustTree(Node *node1, Node *node2)
Definition KoRTree.h:673
QPair< Node *, Node * > splitNode(Node *node)
Definition KoRTree.h:544
int m_capacity
Definition KoRTree.h:335
QMap< T, LeafNode * > m_leafMap
Definition KoRTree.h:338
Definition Node.h:24
bool remove()
remove removes this node from its parent image.
Definition Node.cpp:634
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130