File indexing completed on 2024-05-12 15:56:46
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 2006 Thorsten Zachmann <zachmann@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 0006 Based on code from Wolfgang Baer - WBaer@gmx.de 0007 */ 0008 0009 #ifndef KORTREE_H 0010 #define KORTREE_H 0011 0012 #include <QPair> 0013 #include <QMap> 0014 #include <QList> 0015 #include <QVector> 0016 #include <QPointF> 0017 #include <QRectF> 0018 #include <QVarLengthArray> 0019 0020 #include <QDebug> 0021 #include "kis_assert.h" 0022 0023 // #define CALLIGRA_RTREE_DEBUG 0024 #ifdef CALLIGRA_RTREE_DEBUG 0025 #include <QPainter> 0026 #endif 0027 0028 /** 0029 * @brief The KoRTree class is a template class that provides a R-tree. 0030 * 0031 * This class implements a R-tree as described in 0032 * "R-TREES. A DYNAMIC INDEX STRUCTURE FOR SPATIAL SEARCHING" by Antonin Guttman 0033 * 0034 * It only supports 2 dimensional bounding boxes which are represented by a QRectF. 0035 * For node splitting the Quadratic-Cost Algorithm is used as described by Guttman. 0036 */ 0037 template <typename T> 0038 class KoRTree 0039 { 0040 public: 0041 /** 0042 * @brief Constructor 0043 * 0044 * @param capacity the capacity a node can take 0045 * @param minimum the minimum filling of a node max 0.5 * capacity 0046 */ 0047 KoRTree(int capacity, int minimum); 0048 0049 /** 0050 * @brief Destructor 0051 */ 0052 virtual ~KoRTree(); 0053 0054 /** 0055 * @brief Insert data item into the tree 0056 * 0057 * This will insert a data item into the tree. If necessary the tree will 0058 * adjust itself. 0059 * 0060 * @param data 0061 * @param bb 0062 */ 0063 virtual void insert(const QRectF& bb, const T& data); 0064 0065 /** 0066 * @brief Show if a shape is a part of the tree 0067 * @param data 0068 */ 0069 bool contains(const T &data); 0070 0071 /** 0072 * @brief Remove a data item from the tree 0073 * 0074 * This removed a data item from the tree. If necessary the tree will 0075 * adjust itself. 0076 * 0077 * @param data 0078 */ 0079 void remove(const T& data); 0080 0081 /** 0082 * @brief Find all data items which intersects rect 0083 * The items are sorted by insertion time in ascending order. 0084 * 0085 * @param rect where the objects have to be in 0086 * 0087 * @return objects intersecting the rect 0088 */ 0089 virtual QList<T> intersects(const QRectF& rect) const; 0090 0091 /** 0092 * @brief Find all data item which contain the point 0093 * The items are sorted by insertion time in ascending order. 0094 * 0095 * @param point which should be contained in the objects 0096 * 0097 * @return objects which contain the point 0098 */ 0099 QList<T> contains(const QPointF &point) const; 0100 0101 /** 0102 * @brief Find all data item which contain the point 0103 * The items are sorted by insertion time in ascending order. 0104 * 0105 * @param point which should be contained in the objects 0106 * 0107 * @return objects which contain the point 0108 */ 0109 QList<T> contained(const QRectF &point) const; 0110 0111 /** 0112 * @brief Find all data rectangles 0113 * The order is NOT guaranteed to be the same as that used by values(). 0114 * 0115 * @return a list containing all the data rectangles used in the tree 0116 */ 0117 QList<QRectF> keys() const; 0118 0119 /** 0120 * @brief Find all data items 0121 * The order is NOT guaranteed to be the same as that used by keys(). 0122 * 0123 * @return a list containing all the data used in the tree 0124 */ 0125 QList<T> values() const; 0126 0127 virtual void clear() { 0128 delete m_root; 0129 m_root = createLeafNode(m_capacity + 1, 0, 0); 0130 m_leafMap.clear(); 0131 } 0132 0133 #ifdef CALLIGRA_RTREE_DEBUG 0134 /** 0135 * @brief Paint the tree 0136 * 0137 * @param p painter which should be used for painting 0138 */ 0139 void paint(QPainter & p) const; 0140 0141 /** 0142 * @brief Print the tree using qdebug 0143 */ 0144 void debug() const; 0145 #endif 0146 0147 protected: 0148 class NonLeafNode; 0149 class LeafNode; 0150 0151 class Node 0152 { 0153 public: 0154 #ifdef CALLIGRA_RTREE_DEBUG 0155 static int nodeIdCnt; 0156 #endif 0157 Node(int capacity, int level, Node * parent); 0158 virtual ~Node() {} 0159 0160 virtual void remove(int index); 0161 // move node between nodes of the same type from node 0162 virtual void move(Node * node, int index) = 0; 0163 0164 virtual LeafNode * chooseLeaf(const QRectF& bb) = 0; 0165 virtual NonLeafNode * chooseNode(const QRectF& bb, int level) = 0; 0166 0167 virtual void intersects(const QRectF& rect, QMap<int, T> & result) const = 0; 0168 virtual void contains(const QPointF & point, QMap<int, T> & result) const = 0; 0169 virtual void contained(const QRectF & point, QMap<int, T> & result) const = 0; 0170 0171 virtual void keys(QList<QRectF> & result) const = 0; 0172 virtual void values(QMap<int, T> & result) const = 0; 0173 0174 virtual Node * parent() const { 0175 return m_parent; 0176 } 0177 virtual void setParent(Node * parent) { 0178 m_parent = parent; 0179 } 0180 0181 virtual int childCount() const { 0182 return m_counter; 0183 } 0184 0185 virtual const QRectF& boundingBox() const { 0186 return m_boundingBox; 0187 } 0188 virtual void updateBoundingBox(); 0189 0190 virtual const QRectF& childBoundingBox(int index) const { 0191 return m_childBoundingBox[index]; 0192 } 0193 virtual void setChildBoundingBox(int index, const QRectF& rect) { 0194 m_childBoundingBox[index] = rect; 0195 } 0196 0197 virtual void clear(); 0198 virtual bool isRoot() const { 0199 return m_parent == 0; 0200 } 0201 virtual bool isLeaf() const { 0202 return false; 0203 } 0204 0205 virtual int place() const { 0206 return m_place; 0207 } 0208 virtual void setPlace(int place) { 0209 m_place = place; 0210 } 0211 0212 virtual int level() const { 0213 return m_level; 0214 } 0215 virtual void setLevel(int level) { 0216 m_level = level; 0217 } 0218 0219 #ifdef CALLIGRA_RTREE_DEBUG 0220 virtual int nodeId() const { 0221 return m_nodeId; 0222 } 0223 0224 virtual void paint(QPainter & p, int level) const = 0; 0225 virtual void debug(QString line) const = 0; 0226 0227 protected: 0228 #define levelColorSize 5 0229 static QColor levelColor[levelColorSize]; 0230 virtual void paintRect(QPainter & p, int level) const; 0231 #endif 0232 protected: 0233 Node * m_parent; 0234 QRectF m_boundingBox; 0235 QVector<QRectF> m_childBoundingBox; 0236 int m_counter; 0237 // the position in the parent 0238 int m_place; 0239 #ifdef CALLIGRA_RTREE_DEBUG 0240 int m_nodeId; 0241 #endif 0242 int m_level; 0243 }; 0244 0245 class NonLeafNode : virtual public Node 0246 { 0247 public: 0248 NonLeafNode(int capacity, int level, Node * parent); 0249 ~NonLeafNode() override; 0250 0251 virtual void insert(const QRectF& bb, Node * data); 0252 void remove(int index) override; 0253 void move(Node * node, int index) override; 0254 0255 LeafNode * chooseLeaf(const QRectF& bb) override; 0256 NonLeafNode * chooseNode(const QRectF& bb, int level) override; 0257 0258 void intersects(const QRectF& rect, QMap<int, T> & result) const override; 0259 void contains(const QPointF & point, QMap<int, T> & result) const override; 0260 void contained(const QRectF & point, QMap<int, T> & result) const override; 0261 0262 void keys(QList<QRectF> & result) const override; 0263 void values(QMap<int, T> & result) const override; 0264 0265 virtual Node * getNode(int index) const; 0266 0267 #ifdef CALLIGRA_RTREE_DEBUG 0268 virtual void paint(QPainter & p, int level) const; 0269 virtual void debug(QString line) const; 0270 #endif 0271 protected: 0272 virtual Node * getLeastEnlargement(const QRectF& bb) const; 0273 0274 QVector<Node *> m_childs; 0275 }; 0276 0277 class LeafNode : virtual public Node 0278 { 0279 public: 0280 static int dataIdCounter; 0281 0282 LeafNode(int capacity, int level, Node * parent); 0283 ~LeafNode() override; 0284 0285 virtual void insert(const QRectF& bb, const T& data, int id); 0286 void remove(int index) override; 0287 virtual void remove(const T& data); 0288 void move(Node * node, int index) override; 0289 0290 LeafNode * chooseLeaf(const QRectF& bb) override; 0291 NonLeafNode * chooseNode(const QRectF& bb, int level) override; 0292 0293 void intersects(const QRectF& rect, QMap<int, T> & result) const override; 0294 void contains(const QPointF & point, QMap<int, T> & result) const override; 0295 void contained(const QRectF & point, QMap<int, T> & result) const override; 0296 0297 void keys(QList<QRectF> & result) const override; 0298 void values(QMap<int, T> & result) const override; 0299 0300 virtual const T& getData(int index) const; 0301 virtual int getDataId(int index) const; 0302 0303 bool isLeaf() const override { 0304 return true; 0305 } 0306 0307 #ifdef CALLIGRA_RTREE_DEBUG 0308 virtual void debug(QString line) const; 0309 virtual void paint(QPainter & p, int level) const; 0310 #endif 0311 protected: 0312 QVector<T> m_data; 0313 QVector<int> m_dataIds; 0314 }; 0315 0316 // factory methods 0317 virtual LeafNode* createLeafNode(int capacity, int level, Node * parent) { 0318 return new LeafNode(capacity, level, parent); 0319 } 0320 virtual NonLeafNode* createNonLeafNode(int capacity, int level, Node * parent) { 0321 return new NonLeafNode(capacity, level, parent); 0322 } 0323 0324 // methods for insert 0325 QPair<Node *, Node *> splitNode(Node * node); 0326 QPair<int, int> pickSeeds(Node * node); 0327 QPair<int, int> pickNext(Node * node, QVector<bool> & marker, Node * group1, Node * group2); 0328 virtual void adjustTree(Node * node1, Node * node2); 0329 void insertHelper(const QRectF& bb, const T& data, int id); 0330 0331 // methods for delete 0332 void insert(Node * node); 0333 virtual void condenseTree(Node * node, QVector<Node *> & reinsert); 0334 0335 int m_capacity; 0336 int m_minimum; 0337 Node * m_root; 0338 QMap<T, LeafNode *> m_leafMap; 0339 }; 0340 0341 template <typename T> 0342 KoRTree<T>::KoRTree(int capacity, int minimum) 0343 : m_capacity(capacity) 0344 , m_minimum(minimum) 0345 , m_root(createLeafNode(m_capacity + 1, 0, 0)) 0346 { 0347 if (minimum > capacity / 2) 0348 qFatal("KoRTree::KoRTree minimum can be maximal capacity/2"); 0349 //debugFlake << "root node " << m_root->nodeId(); 0350 } 0351 0352 template <typename T> 0353 KoRTree<T>::~KoRTree() 0354 { 0355 delete m_root; 0356 } 0357 0358 template <typename T> 0359 void KoRTree<T>::insert(const QRectF& bb, const T& data) 0360 { 0361 // check if the shape is not already registered 0362 KIS_SAFE_ASSERT_RECOVER_NOOP(!m_leafMap[data]); 0363 0364 insertHelper(bb, data, LeafNode::dataIdCounter++); 0365 } 0366 0367 template <typename T> 0368 void KoRTree<T>::insertHelper(const QRectF& bb, const T& data, int id) 0369 { 0370 QRectF nbb(bb.normalized()); 0371 // This has to be done as it is not possible to use QRectF::united() with a isNull() 0372 if (nbb.isNull()) { 0373 qWarning() << "KoRTree::insert boundingBox isNull setting size to" << nbb.size(); 0374 0375 nbb.setWidth(0.0001); 0376 nbb.setHeight(0.0001); 0377 } 0378 else { 0379 // This has to be done as QRectF::intersects() return false if the rect does not have any area overlapping. 0380 // If there is no width or height there is no area and therefore no overlapping. 0381 if ( nbb.width() == 0 ) { 0382 nbb.setWidth(0.0001); 0383 } 0384 if ( nbb.height() == 0 ) { 0385 nbb.setHeight(0.0001); 0386 } 0387 } 0388 0389 LeafNode * leaf = m_root->chooseLeaf(nbb); 0390 //debugFlake << " leaf" << leaf->nodeId() << nbb; 0391 0392 if (leaf->childCount() < m_capacity) { 0393 leaf->insert(nbb, data, id); 0394 m_leafMap[data] = leaf; 0395 adjustTree(leaf, 0); 0396 } else { 0397 leaf->insert(nbb, data, id); 0398 m_leafMap[data] = leaf; 0399 QPair<Node *, Node *> newNodes = splitNode(leaf); 0400 LeafNode * l = dynamic_cast<LeafNode *>(newNodes.first); 0401 if (l) 0402 for (int i = 0; i < l->childCount(); ++i) 0403 m_leafMap[l->getData(i)] = l; 0404 l = dynamic_cast<LeafNode *>(newNodes.second); 0405 if (l) 0406 for (int i = 0; i < l->childCount(); ++i) 0407 m_leafMap[l->getData(i)] = l; 0408 0409 adjustTree(newNodes.first, newNodes.second); 0410 } 0411 } 0412 0413 template <typename T> 0414 void KoRTree<T>::insert(Node * node) 0415 { 0416 if (node->level() == m_root->level()) { 0417 adjustTree(m_root, node); 0418 } else { 0419 QRectF bb(node->boundingBox()); 0420 NonLeafNode * newParent = m_root->chooseNode(bb, node->level() + 1); 0421 0422 newParent->insert(bb, node); 0423 0424 QPair<Node *, Node *> newNodes(node, 0); 0425 if (newParent->childCount() > m_capacity) { 0426 newNodes = splitNode(newParent); 0427 } 0428 adjustTree(newNodes.first, newNodes.second); 0429 } 0430 } 0431 0432 template <typename T> 0433 bool KoRTree<T>::contains(const T &data) 0434 { 0435 return m_leafMap[data]; 0436 } 0437 0438 0439 template <typename T> 0440 void KoRTree<T>::remove(const T&data) 0441 { 0442 //debugFlake << "KoRTree remove"; 0443 LeafNode * leaf = m_leafMap[data]; 0444 0445 // Trying to remove inexistent leaf. Most probably, this leaf hasn't been added 0446 // to the shape manager correctly 0447 KIS_SAFE_ASSERT_RECOVER_RETURN(leaf); 0448 0449 m_leafMap.remove(data); 0450 leaf->remove(data); 0451 0452 /** 0453 * WARNING: after calling condenseTree() the temporary enters an inconsistent state! 0454 * m_leafMap still points to the nodes now stored in 'reinsert' list, although 0455 * they are not a part of the hierarchy. This state does not cause any use 0456 * visible changes, but should be considered while implementing sanity checks. 0457 */ 0458 0459 QVector<Node *> reinsert; 0460 condenseTree(leaf, reinsert); 0461 0462 for (int i = 0; i < reinsert.size(); ++i) { 0463 if (reinsert[i]->isLeaf()) { 0464 LeafNode * leaf = dynamic_cast<LeafNode *>(reinsert[i]); 0465 KIS_SAFE_ASSERT_RECOVER(leaf) { reinsert[i]->clear(); delete reinsert[i]; continue; } // mostly for the sake of Coverity 0466 for (int j = 0; j < leaf->childCount(); ++j) { 0467 insertHelper(leaf->childBoundingBox(j), leaf->getData(j), leaf->getDataId(j)); 0468 } 0469 // clear is needed as the data items are not removed when insert into a new node 0470 leaf->clear(); 0471 delete leaf; 0472 } else { 0473 NonLeafNode * node = dynamic_cast<NonLeafNode *>(reinsert[i]); 0474 KIS_SAFE_ASSERT_RECOVER(node) { reinsert[i]->clear(); delete reinsert[i]; continue; } // mostly for the sake of Coverity 0475 for (int j = 0; j < node->childCount(); ++j) { 0476 insert(node->getNode(j)); 0477 } 0478 // clear is needed as the data items are not removed when insert into a new node 0479 node->clear(); 0480 delete node; 0481 } 0482 } 0483 } 0484 0485 template <typename T> 0486 QList<T> KoRTree<T>::intersects(const QRectF& rect) const 0487 { 0488 QMap<int, T> found; 0489 m_root->intersects(rect, found); 0490 return found.values(); 0491 } 0492 0493 template <typename T> 0494 QList<T> KoRTree<T>::contains(const QPointF &point) const 0495 { 0496 QMap<int, T> found; 0497 m_root->contains(point, found); 0498 return found.values(); 0499 } 0500 0501 template <typename T> 0502 QList<T> KoRTree<T>::contained(const QRectF& rect) const 0503 { 0504 QMap<int, T> found; 0505 m_root->contained(rect, found); 0506 return found.values(); 0507 } 0508 0509 0510 template <typename T> 0511 QList<QRectF> KoRTree<T>::keys() const 0512 { 0513 QList<QRectF> found; 0514 m_root->keys(found); 0515 return found; 0516 } 0517 0518 template <typename T> 0519 QList<T> KoRTree<T>::values() const 0520 { 0521 QMap<int, T> found; 0522 m_root->values(found); 0523 return found.values(); 0524 } 0525 0526 #ifdef CALLIGRA_RTREE_DEBUG 0527 template <typename T> 0528 void KoRTree<T>::paint(QPainter & p) const 0529 { 0530 if (m_root) { 0531 m_root->paint(p, 0); 0532 } 0533 } 0534 0535 template <typename T> 0536 void KoRTree<T>::debug() const 0537 { 0538 QString prefix(""); 0539 m_root->debug(prefix); 0540 } 0541 #endif 0542 0543 template <typename T> 0544 QPair< typename KoRTree<T>::Node*, typename KoRTree<T>::Node* > KoRTree<T>::splitNode(typename KoRTree<T>::Node* node) 0545 { 0546 //debugFlake << "KoRTree::splitNode" << node; 0547 Node * n1; 0548 Node * n2; 0549 if (node->isLeaf()) { 0550 n1 = createLeafNode(m_capacity + 1, node->level(), node->parent()); 0551 n2 = createLeafNode(m_capacity + 1, node->level(), node->parent()); 0552 } else { 0553 n1 = createNonLeafNode(m_capacity + 1, node->level(), node->parent()); 0554 n2 = createNonLeafNode(m_capacity + 1, node->level(), node->parent()); 0555 } 0556 //debugFlake << " n1" << n1 << n1->nodeId(); 0557 //debugFlake << " n2" << n2 << n2->nodeId(); 0558 0559 QVector<bool> marker(m_capacity + 1); 0560 0561 QPair<int, int> seeds(pickSeeds(node)); 0562 0563 n1->move(node, seeds.first); 0564 n2->move(node, seeds.second); 0565 0566 marker[seeds.first] = true; 0567 marker[seeds.second] = true; 0568 0569 // There is one more in a node to split than the capacity and as we 0570 // already put the seeds in the new nodes subtract them. 0571 int remaining = m_capacity + 1 - 2; 0572 0573 while (remaining > 0) { 0574 if (m_minimum - n1->childCount() == remaining) { 0575 for (int i = 0; i < m_capacity + 1; ++i) { 0576 if (!marker[i]) { 0577 n1->move(node, i); 0578 --remaining; 0579 } 0580 } 0581 } else if (m_minimum - n2->childCount() == remaining) { 0582 for (int i = 0; i < m_capacity + 1; ++i) { 0583 if (!marker[i]) { 0584 n2->move(node, i); 0585 --remaining; 0586 } 0587 } 0588 } else { 0589 QPair<int, int> next(pickNext(node, marker, n1, n2)); 0590 0591 if (next.first == 0) { 0592 n1->move(node, next.second); 0593 } else { 0594 n2->move(node, next.second); 0595 } 0596 --remaining; 0597 } 0598 } 0599 Q_ASSERT(n1->childCount() + n2->childCount() == node->childCount()); 0600 0601 // move the data back to the old node 0602 // this has to be done as the current node is already in the tree. 0603 node->clear(); 0604 for (int i = 0; i < n1->childCount(); ++i) { 0605 node->move(n1, i); 0606 } 0607 0608 //debugFlake << " delete n1" << n1 << n1->nodeId(); 0609 // clear is needed as the data items are not removed 0610 n1->clear(); 0611 delete n1; 0612 return qMakePair(node, n2); 0613 } 0614 0615 template <typename T> 0616 QPair<int, int> KoRTree<T>::pickSeeds(Node *node) 0617 { 0618 int s1 = 0; 0619 int s2 = 1; 0620 qreal max = 0; 0621 for (int i = 0; i < m_capacity + 1; ++i) { 0622 for (int j = i+1; j < m_capacity + 1; ++j) { 0623 if (i != j) { 0624 QRectF bb1(node->childBoundingBox(i)); 0625 QRectF bb2(node->childBoundingBox(j)); 0626 QRectF comp(node->childBoundingBox(i).united(node->childBoundingBox(j))); 0627 qreal area = comp.width() * comp.height() - bb1.width() * bb1.height() - bb2.width() * bb2.height(); 0628 //debugFlake << " ps" << i << j << area; 0629 if (area > max) { 0630 max = area; 0631 s1 = i; 0632 s2 = j; 0633 } 0634 } 0635 } 0636 } 0637 return qMakePair(s1, s2); 0638 } 0639 0640 template <typename T> 0641 QPair<int, int> KoRTree<T>::pickNext(Node * node, QVector<bool> & marker, Node * group1, Node * group2) 0642 { 0643 //debugFlake << "KoRTree::pickNext" << marker; 0644 qreal max = -1.0; 0645 int select = 0; 0646 int group = 0; 0647 for (int i = 0; i < m_capacity + 1; ++i) { 0648 if (marker[i] == false) { 0649 QRectF bb1 = group1->boundingBox().united(node->childBoundingBox(i)); 0650 QRectF bb2 = group2->boundingBox().united(node->childBoundingBox(i)); 0651 qreal d1 = bb1.width() * bb1.height() - group1->boundingBox().width() * group1->boundingBox().height(); 0652 qreal d2 = bb2.width() * bb2.height() - group2->boundingBox().width() * group2->boundingBox().height(); 0653 qreal diff = qAbs(d1 - d2); 0654 //debugFlake << " diff" << diff << i << d1 << d2; 0655 if (diff > max) { 0656 max = diff; 0657 select = i; 0658 //debugFlake << " i =" << i; 0659 if (qAbs(d1) > qAbs(d2)) { 0660 group = 1; 0661 } else { 0662 group = 0; 0663 } 0664 //debugFlake << " group =" << group; 0665 } 0666 } 0667 } 0668 marker[select] = true; 0669 return qMakePair(group, select); 0670 } 0671 0672 template <typename T> 0673 void KoRTree<T>::adjustTree(Node *node1, Node *node2) 0674 { 0675 //debugFlake << "KoRTree::adjustTree"; 0676 if (node1->isRoot()) { 0677 //debugFlake << " root"; 0678 if (node2) { 0679 NonLeafNode * newRoot = createNonLeafNode(m_capacity + 1, node1->level() + 1, 0); 0680 newRoot->insert(node1->boundingBox(), node1); 0681 newRoot->insert(node2->boundingBox(), node2); 0682 m_root = newRoot; 0683 //debugFlake << "new root" << m_root->nodeId(); 0684 } 0685 } else { 0686 NonLeafNode * parent = dynamic_cast<NonLeafNode *>(node1->parent()); 0687 if (!parent) { 0688 qFatal("KoRTree::adjustTree: no parent node found!"); 0689 return; 0690 } 0691 //QRectF pbbold( parent->boundingBox() ); 0692 parent->setChildBoundingBox(node1->place(), node1->boundingBox()); 0693 parent->updateBoundingBox(); 0694 //debugFlake << " bb1 =" << node1->boundingBox() << node1->place() << pbbold << "->" << parent->boundingBox() << parent->nodeId(); 0695 0696 if (!node2) { 0697 //debugFlake << " update"; 0698 adjustTree(parent, 0); 0699 } else { 0700 if (parent->childCount() < m_capacity) { 0701 //debugFlake << " no split needed"; 0702 parent->insert(node2->boundingBox(), node2); 0703 adjustTree(parent, 0); 0704 } else { 0705 //debugFlake << " split again"; 0706 parent->insert(node2->boundingBox(), node2); 0707 QPair<Node *, Node *> newNodes = splitNode(parent); 0708 adjustTree(newNodes.first, newNodes.second); 0709 } 0710 } 0711 } 0712 } 0713 0714 template <typename T> 0715 void KoRTree<T>::condenseTree(Node *node, QVector<Node*> & reinsert) 0716 { 0717 //debugFlake << "KoRTree::condenseTree begin reinsert.size()" << reinsert.size(); 0718 if (!node->isRoot()) { 0719 Node * parent = node->parent(); 0720 //debugFlake << " !node->isRoot us" << node->childCount(); 0721 0722 if (node->childCount() < m_minimum) { 0723 //debugFlake << " remove node"; 0724 parent->remove(node->place()); 0725 reinsert.push_back(node); 0726 0727 /** 0728 * WARNING: here we leave the tree in an inconsistent state! 'reinsert' 0729 * nodes may still be kept in m_leafMap structure, but we will 0730 * *not* remove them for the efficiency reasons. They are guaranteed 0731 * to be readded in remove(). 0732 */ 0733 0734 } else { 0735 //debugFlake << " update BB parent is root" << parent->isRoot(); 0736 parent->setChildBoundingBox(node->place(), node->boundingBox()); 0737 parent->updateBoundingBox(); 0738 } 0739 condenseTree(parent, reinsert); 0740 } else { 0741 //debugFlake << " node->isRoot us" << node->childCount(); 0742 if (node->childCount() == 1 && !node->isLeaf()) { 0743 //debugFlake << " usedSpace = 1"; 0744 NonLeafNode * n = dynamic_cast<NonLeafNode *>(node); 0745 if (n) { 0746 Node * kid = n->getNode(0); 0747 // clear is needed as the data items are not removed 0748 m_root->clear(); 0749 delete m_root; 0750 m_root = kid; 0751 m_root->setParent(0); 0752 //debugFlake << " new root" << m_root; 0753 } else { 0754 qFatal("KoRTree::condenseTree cast to NonLeafNode failed"); 0755 } 0756 } 0757 } 0758 //debugFlake << "KoRTree::condenseTree end reinsert.size()" << reinsert.size(); 0759 } 0760 0761 #ifdef CALLIGRA_RTREE_DEBUG 0762 template <typename T> 0763 QColor KoRTree<T>::Node::levelColor[] = { 0764 QColor(Qt::green), 0765 QColor(Qt::red), 0766 QColor(Qt::cyan), 0767 QColor(Qt::magenta), 0768 QColor(Qt::yellow), 0769 }; 0770 0771 template <class T> 0772 int KoRTree<T>::Node::nodeIdCnt = 0; 0773 #endif 0774 0775 template <typename T> 0776 KoRTree<T>::Node::Node(int capacity, int level, Node * parent) 0777 : m_parent(parent) 0778 , m_childBoundingBox(capacity) 0779 , m_counter(0) 0780 , m_place(0) 0781 #ifdef CALLIGRA_RTREE_DEBUG 0782 , m_nodeId(nodeIdCnt++) 0783 #endif 0784 , m_level(level) 0785 { 0786 } 0787 0788 template <typename T> 0789 void KoRTree<T>::Node::remove(int index) 0790 { 0791 for (int i = index + 1; i < m_counter; ++i) { 0792 m_childBoundingBox[i-1] = m_childBoundingBox[i]; 0793 } 0794 --m_counter; 0795 updateBoundingBox(); 0796 } 0797 0798 template <typename T> 0799 void KoRTree<T>::Node::updateBoundingBox() 0800 { 0801 m_boundingBox = QRectF(); 0802 for (int i = 0; i < m_counter; ++i) { 0803 m_boundingBox = m_boundingBox.united(m_childBoundingBox[i]); 0804 } 0805 } 0806 0807 template <typename T> 0808 void KoRTree<T>::Node::clear() 0809 { 0810 m_counter = 0; 0811 m_boundingBox = QRectF(); 0812 } 0813 0814 #ifdef CALLIGRA_RTREE_DEBUG 0815 template <typename T> 0816 void KoRTree<T>::Node::paintRect(QPainter & p, int level) const 0817 { 0818 QColor c(Qt::black); 0819 if (level < levelColorSize) { 0820 c = levelColor[level]; 0821 } 0822 0823 QPen pen(c, 0); 0824 p.setPen(pen); 0825 0826 QRectF bbdraw(this->m_boundingBox); 0827 bbdraw.adjust(level * 2, level * 2, -level * 2, -level * 2); 0828 p.drawRect(bbdraw); 0829 } 0830 #endif 0831 0832 template <typename T> 0833 KoRTree<T>::NonLeafNode::NonLeafNode(int capacity, int level, Node * parent) 0834 : Node(capacity, level, parent) 0835 , m_childs(capacity) 0836 { 0837 //debugFlake << "NonLeafNode::NonLeafNode()" << this; 0838 } 0839 0840 template <typename T> 0841 KoRTree<T>::NonLeafNode::~NonLeafNode() 0842 { 0843 //debugFlake << "NonLeafNode::~NonLeafNode()" << this; 0844 for (int i = 0; i < this->m_counter; ++i) { 0845 delete m_childs[i]; 0846 } 0847 } 0848 0849 template <typename T> 0850 void KoRTree<T>::NonLeafNode::insert(const QRectF& bb, Node * data) 0851 { 0852 m_childs[this->m_counter] = data; 0853 data->setPlace(this->m_counter); 0854 data->setParent(this); 0855 this->m_childBoundingBox[this->m_counter] = bb; 0856 this->m_boundingBox = this->m_boundingBox.united(bb); 0857 //debugFlake << "NonLeafNode::insert" << this->nodeId() << data->nodeId(); 0858 ++this->m_counter; 0859 } 0860 0861 template <typename T> 0862 void KoRTree<T>::NonLeafNode::remove(int index) 0863 { 0864 for (int i = index + 1; i < this->m_counter; ++i) { 0865 m_childs[i-1] = m_childs[i]; 0866 m_childs[i-1]->setPlace(i - 1); 0867 } 0868 Node::remove(index); 0869 } 0870 0871 template <typename T> 0872 void KoRTree<T>::NonLeafNode::move(Node * node, int index) 0873 { 0874 //debugFlake << "NonLeafNode::move" << this << node << index << node->nodeId() << "->" << this->nodeId(); 0875 NonLeafNode * n = dynamic_cast<NonLeafNode *>(node); 0876 if (n) { 0877 QRectF bb = n->childBoundingBox(index); 0878 insert(bb, n->getNode(index)); 0879 } 0880 } 0881 0882 template <typename T> 0883 typename KoRTree<T>::LeafNode * KoRTree<T>::NonLeafNode::chooseLeaf(const QRectF& bb) 0884 { 0885 return getLeastEnlargement(bb)->chooseLeaf(bb); 0886 } 0887 0888 template <typename T> 0889 typename KoRTree<T>::NonLeafNode * KoRTree<T>::NonLeafNode::chooseNode(const QRectF& bb, int level) 0890 { 0891 if (this->m_level > level) { 0892 return getLeastEnlargement(bb)->chooseNode(bb, level); 0893 } else { 0894 return this; 0895 } 0896 0897 } 0898 0899 template <typename T> 0900 void KoRTree<T>::NonLeafNode::intersects(const QRectF& rect, QMap<int, T> & result) const 0901 { 0902 for (int i = 0; i < this->m_counter; ++i) { 0903 if (this->m_childBoundingBox[i].intersects(rect)) { 0904 m_childs[i]->intersects(rect, result); 0905 } 0906 } 0907 } 0908 0909 template <typename T> 0910 void KoRTree<T>::NonLeafNode::contains(const QPointF & point, QMap<int, T> & result) const 0911 { 0912 for (int i = 0; i < this->m_counter; ++i) { 0913 if (this->m_childBoundingBox[i].contains(point)) { 0914 m_childs[i]->contains(point, result); 0915 } 0916 } 0917 } 0918 0919 template <typename T> 0920 void KoRTree<T>::NonLeafNode::contained(const QRectF& rect, QMap<int, T> & result) const 0921 { 0922 for (int i = 0; i < this->m_counter; ++i) { 0923 if (this->m_childBoundingBox[i].intersects(rect)) { 0924 m_childs[i]->contained(rect, result); 0925 } 0926 } 0927 } 0928 0929 template <typename T> 0930 void KoRTree<T>::NonLeafNode::keys(QList<QRectF> & result) const 0931 { 0932 for (int i = 0; i < this->m_counter; ++i) { 0933 m_childs[i]->keys(result); 0934 } 0935 } 0936 0937 template <typename T> 0938 void KoRTree<T>::NonLeafNode::values(QMap<int, T> & result) const 0939 { 0940 for (int i = 0; i < this->m_counter; ++i) { 0941 m_childs[i]->values(result); 0942 } 0943 } 0944 0945 template <typename T> 0946 typename KoRTree<T>::Node * KoRTree<T>::NonLeafNode::getNode(int index) const 0947 { 0948 return m_childs[index]; 0949 } 0950 0951 template <typename T> 0952 typename KoRTree<T>::Node * KoRTree<T>::NonLeafNode::getLeastEnlargement(const QRectF& bb) const 0953 { 0954 //debugFlake << "NonLeafNode::getLeastEnlargement"; 0955 QVarLengthArray<qreal> area(this->m_counter); 0956 for (int i = 0; i < this->m_counter; ++i) { 0957 QSizeF big(this->m_childBoundingBox[i].united(bb).size()); 0958 area[i] = big.width() * big.height() - this->m_childBoundingBox[i].width() * this->m_childBoundingBox[i].height(); 0959 } 0960 0961 int minIndex = 0; 0962 qreal minArea = area[minIndex]; 0963 //debugFlake << " min" << minIndex << minArea; 0964 0965 for (int i = 1; i < this->m_counter; ++i) { 0966 if (area[i] < minArea) { 0967 minIndex = i; 0968 minArea = area[i]; 0969 //debugFlake << " min" << minIndex << minArea; 0970 } 0971 } 0972 0973 return m_childs[minIndex]; 0974 } 0975 0976 #ifdef CALLIGRA_RTREE_DEBUG 0977 template <typename T> 0978 void KoRTree<T>::NonLeafNode::debug(QString line) const 0979 { 0980 for (int i = 0; i < this->m_counter; ++i) { 0981 qDebug("%s %d %d", qPrintable(line), this->nodeId(), i); 0982 m_childs[i]->debug(line + " "); 0983 } 0984 } 0985 0986 template <typename T> 0987 void KoRTree<T>::NonLeafNode::paint(QPainter & p, int level) const 0988 { 0989 this->paintRect(p, level); 0990 for (int i = 0; i < this->m_counter; ++i) { 0991 m_childs[i]->paint(p, level + 1); 0992 } 0993 0994 } 0995 #endif 0996 0997 template <class T> 0998 int KoRTree<T>::LeafNode::dataIdCounter = 0; 0999 1000 template <typename T> 1001 KoRTree<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 1009 template <typename T> 1010 KoRTree<T>::LeafNode::~LeafNode() 1011 { 1012 //debugFlake << "LeafNode::~LeafNode" << this; 1013 } 1014 1015 template <typename T> 1016 void 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 1025 template <typename T> 1026 void KoRTree<T>::LeafNode::remove(int index) 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 1035 template <typename T> 1036 void KoRTree<T>::LeafNode::remove(const T& data) 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 1051 template <typename T> 1052 void 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 1063 template <typename T> 1064 typename KoRTree<T>::LeafNode * KoRTree<T>::LeafNode::chooseLeaf(const QRectF& bb) 1065 { 1066 Q_UNUSED(bb); 1067 return this; 1068 } 1069 1070 template <typename T> 1071 typename 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 1079 template <typename T> 1080 void 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 1089 template <typename T> 1090 void 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 1099 template <typename T> 1100 void 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 1109 template <typename T> 1110 void KoRTree<T>::LeafNode::keys(QList<QRectF> & result) const 1111 { 1112 for (int i = 0; i < this->m_counter; ++i) { 1113 result.push_back(this->m_childBoundingBox[i]); 1114 } 1115 } 1116 1117 template <typename T> 1118 void 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 1125 template <typename T> 1126 const T& KoRTree<T>::LeafNode::getData(int index) const 1127 { 1128 return m_data[ index ]; 1129 } 1130 1131 template <typename T> 1132 int KoRTree<T>::LeafNode::getDataId(int index) const 1133 { 1134 return m_dataIds[ index ]; 1135 } 1136 1137 #ifdef CALLIGRA_RTREE_DEBUG 1138 template <typename T> 1139 void 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 1147 template <typename T> 1148 void 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 */