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 */