libs/flake

KoRTree.h

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002    Copyright (c) 2006 Thorsten Zachmann <zachmann@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 
00019    Based on code from Wolfgang Baer - WBaer@gmx.de
00020 */
00021 
00022 #ifndef KORTREE_H
00023 #define KORTREE_H
00024 
00025 #include <KDebug>
00026 
00027 #include <QtCore/QPair>
00028 #include <QtCore/QMap>
00029 #include <QtCore/QList>
00030 #include <QtCore/QVector>
00031 #include <QtCore/QPointF>
00032 #include <QtCore/QRectF>
00033 #include <QtCore/QVarLengthArray>
00034 
00035 // #define KOFFICE_RTREE_DEBUG
00036 #ifdef KOFFICE_RTREE_DEBUG
00037 #include <QtGui/QPainter>
00038 #endif
00039 
00049 template <typename T>
00050 class KoRTree
00051 {
00052 public:
00059     KoRTree(int capacity, int minimum);
00060 
00064     virtual ~KoRTree();
00065 
00075     virtual void insert(const QRectF& bb, const T& data);
00076 
00085     void remove(const T& data);
00086 
00095     virtual QList<T> intersects(const QRectF& rect) const;
00096 
00105     QList<T> contains(const QPointF &point) const;
00106 
00113     QList<QRectF> keys() const;
00114 
00121     QList<T> values() const;
00122 
00123     void clear() {
00124         delete m_root;
00125         m_root = createLeafNode(m_capacity + 1, 0, 0);
00126         m_leafMap.clear();
00127     }
00128 
00129 #ifdef KOFFICE_RTREE_DEBUG
00130 
00135     void paint(QPainter & p) const;
00136 
00140     void debug() const;
00141 #endif
00142 
00143 protected:
00144     class NoneLeafNode;
00145     class LeafNode;
00146 
00147     class Node
00148     {
00149     public:
00150 #ifdef KOFFICE_RTREE_DEBUG
00151         static int nodeIdCnt;
00152 #endif
00153         Node(int capacity, int level, Node * parent);
00154         virtual ~Node() {}
00155 
00156         virtual void remove(int index);
00157         // move node between nodes of the same type from node
00158         virtual void move(Node * node, int index) = 0;
00159 
00160         virtual LeafNode * chooseLeaf(const QRectF& bb) = 0;
00161         virtual NoneLeafNode * chooseNode(const QRectF& bb, int level) = 0;
00162 
00163         virtual void intersects(const QRectF& rect, QMap<int, T> & result) const = 0;
00164         virtual void contains(const QPointF & point, QMap<int, T> & result) const = 0;
00165 
00166         virtual void keys(QList<QRectF> & result) const = 0;
00167         virtual void values(QMap<int, T> & result) const = 0;
00168 
00169         virtual Node * parent() const {
00170             return m_parent;
00171         }
00172         virtual void setParent(Node * parent) {
00173             m_parent = parent;
00174         }
00175 
00176         virtual int childCount() const {
00177             return m_counter;
00178         }
00179 
00180         virtual const QRectF& boundingBox() const {
00181             return m_boundingBox;
00182         }
00183         virtual void updateBoundingBox();
00184 
00185         virtual const QRectF& childBoundingBox(int index) const {
00186             return m_childBoundingBox[index];
00187         }
00188         virtual void setChildBoundingBox(int index, const QRectF& rect) {
00189             m_childBoundingBox[index] = rect;
00190         }
00191 
00192         virtual void clear();
00193         virtual bool isRoot() const {
00194             return m_parent == 0;
00195         }
00196         virtual bool isLeaf() const {
00197             return false;
00198         }
00199 
00200         virtual int place() const {
00201             return m_place;
00202         }
00203         virtual void setPlace(int place) {
00204             m_place = place;
00205         }
00206 
00207         virtual int level() const {
00208             return m_level;
00209         }
00210         virtual void setLevel(int level) {
00211             m_level = level;
00212         }
00213 
00214 #ifdef KOFFICE_RTREE_DEBUG
00215         virtual int nodeId() const {
00216             return m_nodeId;
00217         }
00218 
00219         virtual void paint(QPainter & p, int level) const = 0;
00220         virtual void debug(QString line) const = 0;
00221 
00222     protected:
00223 #define levelColorSize 5
00224         static QColor levelColor[levelColorSize];
00225         virtual void paintRect(QPainter & p, int level) const;
00226 #endif
00227     protected:
00228         Node * m_parent;
00229         QRectF m_boundingBox;
00230         QVector<QRectF> m_childBoundingBox;
00231         int m_counter;
00232         // the position in the parent
00233         int m_place;
00234 #ifdef KOFFICE_RTREE_DEBUG
00235         int m_nodeId;
00236 #endif
00237         int m_level;
00238     };
00239 
00240 class NoneLeafNode : virtual public Node
00241     {
00242     public:
00243         NoneLeafNode(int capacity, int level, Node * parent);
00244         virtual ~NoneLeafNode();
00245 
00246         virtual void insert(const QRectF& bb, Node * data);
00247         virtual void remove(int index);
00248         virtual void move(Node * node, int index);
00249 
00250         virtual LeafNode * chooseLeaf(const QRectF& bb);
00251         virtual NoneLeafNode * chooseNode(const QRectF& bb, int level);
00252 
00253         virtual void intersects(const QRectF& rect, QMap<int, T> & result) const;
00254         virtual void contains(const QPointF & point, QMap<int, T> & result) const;
00255 
00256         virtual void keys(QList<QRectF> & result) const;
00257         virtual void values(QMap<int, T> & result) const;
00258 
00259         virtual Node * getNode(int index) const;
00260 
00261 #ifdef KOFFICE_RTREE_DEBUG
00262         virtual void paint(QPainter & p, int level) const;
00263         virtual void debug(QString line) const;
00264 #endif
00265     protected:
00266         virtual Node * getLeastEnlargement(const QRectF& bb) const;
00267 
00268         QVector<Node *> m_childs;
00269     };
00270 
00271 class LeafNode : virtual public Node
00272     {
00273     public:
00274         static int dataIdCounter;
00275 
00276         LeafNode(int capacity, int level, Node * parent);
00277         virtual ~LeafNode();
00278 
00279         virtual void insert(const QRectF& bb, const T& data, int id);
00280         virtual void remove(int index);
00281         virtual void remove(const T& data);
00282         virtual void move(Node * node, int index);
00283 
00284         virtual LeafNode * chooseLeaf(const QRectF& bb);
00285         virtual NoneLeafNode * chooseNode(const QRectF& bb, int level);
00286 
00287         virtual void intersects(const QRectF& rect, QMap<int, T> & result) const;
00288         virtual void contains(const QPointF & point, QMap<int, T> & result) const;
00289 
00290         virtual void keys(QList<QRectF> & result) const;
00291         virtual void values(QMap<int, T> & result) const;
00292 
00293         virtual const T& getData(int index) const;
00294         virtual int getDataId(int index) const;
00295 
00296         virtual bool isLeaf() const {
00297             return true;
00298         }
00299 
00300 #ifdef KOFFICE_RTREE_DEBUG
00301         virtual void debug(QString line) const;
00302         virtual void paint(QPainter & p, int level) const;
00303 #endif
00304     protected:
00305         QVector<T> m_data;
00306         QVector<int> m_dataIds;
00307     };
00308 
00309     // factory methods
00310     virtual LeafNode* createLeafNode(int capacity, int level, Node * parent) {
00311         return new LeafNode(capacity, level, parent);
00312     }
00313     virtual NoneLeafNode* createNoneLeafNode(int capacity, int level, Node * parent) {
00314         return new NoneLeafNode(capacity, level, parent);
00315     }
00316 
00317     // methods for insert
00318     QPair<Node *, Node *> splitNode(Node * node);
00319     QPair<int, int> pickSeeds(Node * node);
00320     QPair<int, int> pickNext(Node * node, QVector<bool> & marker, Node * group1, Node * group2);
00321     void adjustTree(Node * node1, Node * node2);
00322     void insertHelper(const QRectF& bb, const T& data, int id);
00323 
00324     // methods for delete
00325     void insert(Node * node);
00326     void condenseTree(Node * node, QVector<Node *> & reinsert);
00327 
00328     int m_capacity;
00329     int m_minimum;
00330     Node * m_root;
00331     QMap<T, LeafNode *> m_leafMap;
00332 };
00333 
00334 template <typename T>
00335 KoRTree<T>::KoRTree(int capacity, int minimum)
00336         : m_capacity(capacity)
00337         , m_minimum(minimum)
00338         , m_root(createLeafNode(m_capacity + 1, 0, 0))
00339 {
00340     if (minimum > capacity / 2)
00341         qFatal("KoRTree::KoRTree minimum can be maximal capacity/2");
00342     //qDebug() << "root node " << m_root->nodeId();
00343 }
00344 
00345 template <typename T>
00346 KoRTree<T>::~KoRTree()
00347 {
00348     delete m_root;
00349 }
00350 
00351 template <typename T>
00352 void KoRTree<T>::insert(const QRectF& bb, const T& data)
00353 {
00354     insertHelper(bb, data, LeafNode::dataIdCounter++);
00355 }
00356 
00357 template <typename T>
00358 void KoRTree<T>::insertHelper(const QRectF& bb, const T& data, int id)
00359 {
00360     QRectF nbb(bb.normalized());
00361     // This has to be done as it is not possible to use QRectF::unite() with a isNull()
00362     if (nbb.isNull()) {
00363         nbb.setWidth(0.0001);
00364         nbb.setHeight(0.0001);
00365         kWarning(30003) <<  "KoRTree::insert boundingBox isNull setting size to" << nbb.size();
00366     }
00367     else {
00368         // This has to be done as QRectF::intersects() return false if the rect does not have any area overlapping.
00369         // If there is no width or height there is no area and therefore no overlapping.
00370         if ( nbb.width() == 0 ) {
00371             nbb.setWidth(0.0001);
00372         }
00373         if ( nbb.height() == 0 ) {
00374             nbb.setHeight(0.0001);
00375         }
00376     }
00377 
00378     LeafNode * leaf = m_root->chooseLeaf(nbb);
00379     //qDebug() << " leaf" << leaf->nodeId() << nbb;
00380 
00381     if (leaf->childCount() < m_capacity) {
00382         leaf->insert(nbb, data, id);
00383         m_leafMap[data] = leaf;
00384         adjustTree(leaf, 0);
00385     } else {
00386         leaf->insert(nbb, data, id);
00387         m_leafMap[data] = leaf;
00388         QPair<Node *, Node *> newNodes = splitNode(leaf);
00389         LeafNode * l = dynamic_cast<LeafNode *>(newNodes.first);
00390         if (l)
00391             for (int i = 0; i < l->childCount(); ++i)
00392                 m_leafMap[l->getData(i)] = l;
00393         l = dynamic_cast<LeafNode *>(newNodes.second);
00394         if (l)
00395             for (int i = 0; i < l->childCount(); ++i)
00396                 m_leafMap[l->getData(i)] = l;
00397 
00398         adjustTree(newNodes.first, newNodes.second);
00399     }
00400 }
00401 
00402 template <typename T>
00403 void KoRTree<T>::insert(Node * node)
00404 {
00405     if (node->level() == m_root->level()) {
00406         adjustTree(m_root, node);
00407     } else {
00408         QRectF bb(node->boundingBox());
00409         NoneLeafNode * newParent = m_root->chooseNode(bb, node->level() + 1);
00410 
00411         newParent->insert(bb, node);
00412 
00413         QPair<Node *, Node *> newNodes(node, 0);
00414         if (newParent->childCount() > m_capacity) {
00415             newNodes = splitNode(newParent);
00416         }
00417         adjustTree(newNodes.first, newNodes.second);
00418     }
00419 }
00420 
00421 template <typename T>
00422 void KoRTree<T>::remove(const T&data)
00423 {
00424     //qDebug() << "KoRTree remove";
00425     LeafNode * leaf = m_leafMap[data];
00426     if (leaf == 0) {
00427         kWarning(30003) << "KoRTree<T>::remove( const T&data) data not found";
00428         return;
00429     }
00430     m_leafMap.remove(data);
00431     leaf->remove(data);
00432 
00433     QVector<Node *> reinsert;
00434     condenseTree(leaf, reinsert);
00435 
00436     for (int i = 0; i < reinsert.size(); ++i) {
00437         if (reinsert[i]->isLeaf()) {
00438             LeafNode * leaf = dynamic_cast<LeafNode *>(reinsert[i]);
00439             for (int j = 0; j < leaf->childCount(); ++j) {
00440                 insertHelper(leaf->childBoundingBox(j), leaf->getData(j), leaf->getDataId(j));
00441             }
00442             // clear is needed as the data items are not removed when insert into a new node
00443             leaf->clear();
00444             delete leaf;
00445         } else {
00446             NoneLeafNode * node = dynamic_cast<NoneLeafNode *>(reinsert[i]);
00447             for (int j = 0; j < node->childCount(); ++j) {
00448                 insert(node->getNode(j));
00449             }
00450             // clear is needed as the data items are not removed when insert into a new node
00451             node->clear();
00452             delete node;
00453         }
00454     }
00455 }
00456 
00457 template <typename T>
00458 QList<T> KoRTree<T>::intersects(const QRectF& rect) const
00459 {
00460     QMap<int, T> found;
00461     m_root->intersects(rect, found);
00462     return found.values();
00463 }
00464 
00465 template <typename T>
00466 QList<T> KoRTree<T>::contains(const QPointF &point) const
00467 {
00468     QMap<int, T> found;
00469     m_root->contains(point, found);
00470     return found.values();
00471 }
00472 
00473 template <typename T>
00474 QList<QRectF> KoRTree<T>::keys() const
00475 {
00476     QList<QRectF> found;
00477     m_root->keys(found);
00478     return found;
00479 }
00480 
00481 template <typename T>
00482 QList<T> KoRTree<T>::values() const
00483 {
00484     QMap<int, T> found;
00485     m_root->values(found);
00486     return found.values();
00487 }
00488 
00489 #ifdef KOFFICE_RTREE_DEBUG
00490 template <typename T>
00491 void KoRTree<T>::paint(QPainter & p) const
00492 {
00493     if (m_root) {
00494         m_root->paint(p, 0);
00495     }
00496 }
00497 
00498 template <typename T>
00499 void KoRTree<T>::debug() const
00500 {
00501     QString prefix("");
00502     m_root->debug(prefix);
00503 }
00504 #endif
00505 
00506 template <typename T>
00507 QPair< typename KoRTree<T>::Node*, typename KoRTree<T>::Node* > KoRTree<T>::splitNode(typename KoRTree<T>::Node* node)
00508 {
00509     //qDebug() << "KoRTree::splitNode" << node;
00510     Node * n1;
00511     Node * n2;
00512     if (node->isLeaf()) {
00513         n1 = createLeafNode(m_capacity + 1, node->level(), node->parent());
00514         n2 = createLeafNode(m_capacity + 1, node->level(), node->parent());
00515     } else {
00516         n1 = createNoneLeafNode(m_capacity + 1, node->level(), node->parent());
00517         n2 = createNoneLeafNode(m_capacity + 1, node->level(), node->parent());
00518     }
00519     //qDebug() << " n1" << n1 << n1->nodeId();
00520     //qDebug() << " n2" << n2 << n2->nodeId();
00521 
00522     QVector<bool> marker(m_capacity + 1);
00523 
00524     QPair<int, int> seeds(pickSeeds(node));
00525 
00526     n1->move(node, seeds.first);
00527     n2->move(node, seeds.second);
00528 
00529     marker[seeds.first] = true;
00530     marker[seeds.second] = true;
00531 
00532     // There is one more in a node to split than the capacity and as we
00533     // already put the seeds in the new nodes subtract them.
00534     int remaining = m_capacity + 1 - 2;
00535 
00536     while (remaining > 0) {
00537         if (m_minimum - n1->childCount() == remaining) {
00538             for (int i = 0; i < m_capacity + 1; ++i) {
00539                 if (!marker[i]) {
00540                     n1->move(node, i);
00541                     --remaining;
00542                 }
00543             }
00544         } else if (m_minimum - n2->childCount() == remaining) {
00545             for (int i = 0; i < m_capacity + 1; ++i) {
00546                 if (!marker[i]) {
00547                     n2->move(node, i);
00548                     --remaining;
00549                 }
00550             }
00551         } else {
00552             QPair<int, int> next(pickNext(node, marker, n1, n2));
00553 
00554             if (next.first == 0) {
00555                 n1->move(node, next.second);
00556             } else {
00557                 n2->move(node, next.second);
00558             }
00559             --remaining;
00560         }
00561     }
00562     Q_ASSERT(n1->childCount() + n2->childCount() == node->childCount());
00563 
00564     // move the data back to the old node
00565     // this has to be done as the current node is already in the tree.
00566     node->clear();
00567     for (int i = 0; i < n1->childCount(); ++i) {
00568         node->move(n1, i);
00569     }
00570 
00571     //qDebug() << " delete n1" << n1 << n1->nodeId();
00572     // clear is needed as the data items are not removed
00573     n1->clear();
00574     delete n1;
00575     return qMakePair(node, n2);
00576 }
00577 
00578 template <typename T>
00579 QPair<int, int> KoRTree<T>::pickSeeds(Node *node)
00580 {
00581     int s1 = 0;
00582     int s2 = 1;
00583     qreal max = 0;
00584     for (int i = 0; i < m_capacity + 1; ++i) {
00585         for (int j = 0; j < m_capacity + 1; ++j) {
00586             if (i != j) {
00587                 QRectF bb1(node->childBoundingBox(i));
00588                 QRectF bb2(node->childBoundingBox(j));
00589                 QRectF comp(node->childBoundingBox(i).unite(node->childBoundingBox(j)));
00590                 qreal area = comp.width() * comp.height() - bb1.width() * bb1.height() - bb2.width() * bb2.height();
00591                 //qDebug() << " ps" << i << j << area;
00592                 if (area > max) {
00593                     max = area;
00594                     s1 = i;
00595                     s2 = j;
00596                 }
00597             }
00598         }
00599     }
00600     return qMakePair(s1, s2);
00601 }
00602 
00603 template <typename T>
00604 QPair<int, int> KoRTree<T>::pickNext(Node * node, QVector<bool> & marker, Node * group1, Node * group2)
00605 {
00606     //qDebug() << "KoRTree::pickNext" << marker;
00607     qreal max = -1.0;
00608     int select = 0;
00609     int group = 0;
00610     for (int i = 0; i < m_capacity + 1; ++i) {
00611         if (marker[i] == false) {
00612             QRectF bb1 = group1->boundingBox().unite(node->childBoundingBox(i));
00613             QRectF bb2 = group2->boundingBox().unite(node->childBoundingBox(i));
00614             qreal d1 = bb1.width() * bb1.height() - group1->boundingBox().width() * group1->boundingBox().height();
00615             qreal d2 = bb2.width() * bb2.height() - group2->boundingBox().width() * group2->boundingBox().height();
00616             qreal diff = qAbs(d1 - d2);
00617             //qDebug() << " diff" << diff << i << d1 << d2;
00618             if (diff > max) {
00619                 max = diff;
00620                 select = i;
00621                 //qDebug() << "  i =" <<  i;
00622                 if (qAbs(d1) > qAbs(d2)) {
00623                     group = 1;
00624                 } else {
00625                     group = 0;
00626                 }
00627                 //qDebug() << "  group =" << group;
00628             }
00629         }
00630     }
00631     marker[select] = true;
00632     return qMakePair(group, select);
00633 }
00634 
00635 template <typename T>
00636 void KoRTree<T>::adjustTree(Node *node1, Node *node2)
00637 {
00638     //qDebug() << "KoRTree::adjustTree";
00639     if (node1->isRoot()) {
00640         //qDebug() << "  root";
00641         if (node2) {
00642             NoneLeafNode * newRoot = createNoneLeafNode(m_capacity + 1, node1->level() + 1, 0);
00643             newRoot->insert(node1->boundingBox(), node1);
00644             newRoot->insert(node2->boundingBox(), node2);
00645             m_root = newRoot;
00646             //qDebug() << "new root" << m_root->nodeId();
00647         }
00648     } else {
00649         NoneLeafNode * parent = dynamic_cast<NoneLeafNode *>(node1->parent());
00650         if (!parent) {
00651             qFatal("KoRTree::adjustTree: no parent node found!");
00652             return;
00653         }
00654         //QRectF pbbold( parent->boundingBox() );
00655         parent->setChildBoundingBox(node1->place(), node1->boundingBox());
00656         parent->updateBoundingBox();
00657         //qDebug() << "  bb1 =" << node1->boundingBox() << node1->place() << pbbold << "->" << parent->boundingBox() << parent->nodeId();
00658 
00659         if (!node2) {
00660             //qDebug() << "  update";
00661             adjustTree(parent, 0);
00662         } else {
00663             if (parent->childCount() < m_capacity) {
00664                 //qDebug() << "  no split needed";
00665                 parent->insert(node2->boundingBox(), node2);
00666                 adjustTree(parent, 0);
00667             } else {
00668                 //qDebug() << "  split again";
00669                 parent->insert(node2->boundingBox(), node2);
00670                 QPair<Node *, Node *> newNodes = splitNode(parent);
00671                 adjustTree(newNodes.first, newNodes.second);
00672             }
00673         }
00674     }
00675 }
00676 
00677 template <typename T>
00678 void KoRTree<T>::condenseTree(Node *node, QVector<Node*> & reinsert)
00679 {
00680     //qDebug() << "KoRTree::condenseTree begin reinsert.size()" << reinsert.size();
00681     if (!node->isRoot()) {
00682         Node * parent = node->parent();
00683         //qDebug() << " !node->isRoot us" << node->childCount();
00684 
00685         if (node->childCount() < m_minimum) {
00686             //qDebug() << "  remove node";
00687             parent->remove(node->place());
00688             reinsert.push_back(node);
00689         } else {
00690             //qDebug() << "  update BB parent is root" << parent->isRoot();
00691             parent->setChildBoundingBox(node->place(), node->boundingBox());
00692             parent->updateBoundingBox();
00693         }
00694         condenseTree(parent, reinsert);
00695     } else {
00696         //qDebug() << " node->isRoot us" << node->childCount();
00697         if (node->childCount() == 1 && !node->isLeaf()) {
00698             //qDebug() << "  usedSpace = 1";
00699             NoneLeafNode * n = dynamic_cast<NoneLeafNode *>(node);
00700             if (n) {
00701                 Node * kid = n->getNode(0);
00702                 // clear is needed as the data items are not removed
00703                 m_root->clear();
00704                 delete m_root;
00705                 m_root = kid;
00706                 m_root->setParent(0);
00707                 //qDebug() << " new root" << m_root;
00708             } else {
00709                 qFatal("KoRTree::condenseTree cast to NoneLeafNode failed");
00710             }
00711         }
00712     }
00713     //qDebug() << "KoRTree::condenseTree end reinsert.size()" << reinsert.size();
00714 }
00715 
00716 #ifdef KOFFICE_RTREE_DEBUG
00717 template <typename T>
00718 QColor KoRTree<T>::Node::levelColor[] = {
00719     QColor(Qt::green),
00720     QColor(Qt::red),
00721     QColor(Qt::cyan),
00722     QColor(Qt::magenta),
00723     QColor(Qt::yellow),
00724 };
00725 
00726 template <class T>
00727 int KoRTree<T>::Node::nodeIdCnt = 0;
00728 #endif
00729 
00730 template <typename T>
00731 KoRTree<T>::Node::Node(int capacity, int level, Node * parent)
00732         : m_parent(parent)
00733         , m_childBoundingBox(capacity)
00734         , m_counter(0)
00735 #ifdef KOFFICE_RTREE_DEBUG
00736         , m_nodeId(nodeIdCnt++)
00737 #endif
00738         , m_level(level)
00739 {
00740 }
00741 
00742 template <typename T>
00743 void KoRTree<T>::Node::remove(int index)
00744 {
00745     for (int i = index + 1; i < m_counter; ++i) {
00746         m_childBoundingBox[i-1] = m_childBoundingBox[i];
00747     }
00748     --m_counter;
00749     updateBoundingBox();
00750 }
00751 
00752 template <typename T>
00753 void KoRTree<T>::Node::updateBoundingBox()
00754 {
00755     QRectF oldBB = m_boundingBox;
00756     m_boundingBox = QRectF();
00757     for (int i = 0; i < m_counter; ++i) {
00758         m_boundingBox = m_boundingBox.unite(m_childBoundingBox[i]);
00759     }
00760 }
00761 
00762 template <typename T>
00763 void KoRTree<T>::Node::clear()
00764 {
00765     m_counter = 0;
00766     m_boundingBox = QRectF();
00767 }
00768 
00769 #ifdef KOFFICE_RTREE_DEBUG
00770 template <typename T>
00771 void KoRTree<T>::Node::paintRect(QPainter & p, int level) const
00772 {
00773     QColor c(Qt::black);
00774     if (level < levelColorSize) {
00775         c = levelColor[level];
00776     }
00777 
00778     QPen pen(c);;
00779     p.setPen(pen);
00780 
00781     QRectF bbdraw(this->m_boundingBox);
00782     bbdraw.adjust(level * 2, level * 2, -level * 2, -level * 2);
00783     p.drawRect(bbdraw);
00784 }
00785 #endif
00786 
00787 template <typename T>
00788 KoRTree<T>::NoneLeafNode::NoneLeafNode(int capacity, int level, Node * parent)
00789         : Node(capacity, level, parent)
00790         , m_childs(capacity)
00791 {
00792     //qDebug() << "NoneLeafNode::NoneLeafNode()" << this;
00793 }
00794 
00795 template <typename T>
00796 KoRTree<T>::NoneLeafNode::~NoneLeafNode()
00797 {
00798     //qDebug() << "NoneLeafNode::~NoneLeafNode()" << this;
00799     for (int i = 0; i < this->m_counter; ++i) {
00800         delete m_childs[i];
00801     }
00802 }
00803 
00804 template <typename T>
00805 void KoRTree<T>::NoneLeafNode::insert(const QRectF& bb, Node * data)
00806 {
00807     m_childs[this->m_counter] = data;
00808     data->setPlace(this->m_counter);
00809     data->setParent(this);
00810     this->m_childBoundingBox[this->m_counter] = bb;
00811     this->m_boundingBox = this->m_boundingBox.unite(bb);
00812     //qDebug() << "NoneLeafNode::insert" << this->nodeId() << data->nodeId();
00813     ++this->m_counter;
00814 }
00815 
00816 template <typename T>
00817 void KoRTree<T>::NoneLeafNode::remove(int index)
00818 {
00819     for (int i = index + 1; i < this->m_counter; ++i) {
00820         m_childs[i-1] = m_childs[i];
00821         m_childs[i-1]->setPlace(i - 1);
00822     }
00823     Node::remove(index);
00824 }
00825 
00826 template <typename T>
00827 void KoRTree<T>::NoneLeafNode::move(Node * node, int index)
00828 {
00829     //qDebug() << "NoneLeafNode::move" << this << node << index << node->nodeId() << "->" << this->nodeId();
00830     NoneLeafNode * n = dynamic_cast<NoneLeafNode *>(node);
00831     if (n) {
00832         QRectF bb = n->childBoundingBox(index);
00833         insert(bb, n->getNode(index));
00834     }
00835 }
00836 
00837 template <typename T>
00838 typename KoRTree<T>::LeafNode * KoRTree<T>::NoneLeafNode::chooseLeaf(const QRectF& bb)
00839 {
00840     return getLeastEnlargement(bb)->chooseLeaf(bb);
00841 }
00842 
00843 template <typename T>
00844 typename KoRTree<T>::NoneLeafNode * KoRTree<T>::NoneLeafNode::chooseNode(const QRectF& bb, int level)
00845 {
00846     if (this->m_level > level) {
00847         return getLeastEnlargement(bb)->chooseNode(bb, level);
00848     } else {
00849         return this;
00850     }
00851 
00852 }
00853 
00854 template <typename T>
00855 void KoRTree<T>::NoneLeafNode::intersects(const QRectF& rect, QMap<int, T> & result) const
00856 {
00857     for (int i = 0; i < this->m_counter; ++i) {
00858         if (this->m_childBoundingBox[i].intersects(rect)) {
00859             m_childs[i]->intersects(rect, result);
00860         }
00861     }
00862 }
00863 
00864 template <typename T>
00865 void KoRTree<T>::NoneLeafNode::contains(const QPointF & point, QMap<int, T> & result) const
00866 {
00867     for (int i = 0; i < this->m_counter; ++i) {
00868         if (this->m_childBoundingBox[i].contains(point)) {
00869             m_childs[i]->contains(point, result);
00870         }
00871     }
00872 }
00873 
00874 template <typename T>
00875 void KoRTree<T>::NoneLeafNode::keys(QList<QRectF> & result) const
00876 {
00877     for (int i = 0; i < this->m_counter; ++i) {
00878         m_childs[i]->keys(result);
00879     }
00880 }
00881 
00882 template <typename T>
00883 void KoRTree<T>::NoneLeafNode::values(QMap<int, T> & result) const
00884 {
00885     for (int i = 0; i < this->m_counter; ++i) {
00886         m_childs[i]->values(result);
00887     }
00888 }
00889 
00890 template <typename T>
00891 typename KoRTree<T>::Node * KoRTree<T>::NoneLeafNode::getNode(int index) const
00892 {
00893     return m_childs[index];
00894 }
00895 
00896 template <typename T>
00897 typename KoRTree<T>::Node * KoRTree<T>::NoneLeafNode::getLeastEnlargement(const QRectF& bb) const
00898 {
00899     //qDebug() << "NoneLeafNode::getLeastEnlargement";
00900     QVarLengthArray<qreal> area(this->m_counter);
00901     for (int i = 0; i < this->m_counter; ++i) {
00902         QSizeF big(this->m_childBoundingBox[i].unite(bb).size());
00903         area[i] = big.width() * big.height() - this->m_childBoundingBox[i].width() * this->m_childBoundingBox[i].height();
00904     }
00905 
00906     int minIndex = 0;
00907     qreal minArea = area[minIndex];
00908     //qDebug() << " min" << minIndex << minArea;
00909 
00910     for (int i = 1; i < this->m_counter; ++i) {
00911         if (area[i] < minArea) {
00912             minIndex = i;
00913             minArea = area[i];
00914             //qDebug() << " min" << minIndex << minArea;
00915         }
00916     }
00917 
00918     return m_childs[minIndex];
00919 }
00920 
00921 #ifdef KOFFICE_RTREE_DEBUG
00922 template <typename T>
00923 void KoRTree<T>::NoneLeafNode::debug(QString line) const
00924 {
00925     for (int i = 0; i < this->m_counter; ++i) {
00926         qDebug("%s %d %d", qPrintable(line), this->nodeId(), i);
00927         m_childs[i]->debug(line + "       ");
00928     }
00929 }
00930 
00931 template <typename T>
00932 void KoRTree<T>::NoneLeafNode::paint(QPainter & p, int level) const
00933 {
00934     this->paintRect(p, level);
00935     for (int i = 0; i < this->m_counter; ++i) {
00936         m_childs[i]->paint(p, level + 1);
00937     }
00938 
00939 }
00940 #endif
00941 
00942 template <class T>
00943 int KoRTree<T>::LeafNode::dataIdCounter = 0;
00944 
00945 template <typename T>
00946 KoRTree<T>::LeafNode::LeafNode(int capacity, int level, Node * parent)
00947         : Node(capacity, level, parent)
00948         , m_data(capacity)
00949         , m_dataIds(capacity)
00950 {
00951     //qDebug() << "LeafNode::LeafNode" << this;
00952 }
00953 
00954 template <typename T>
00955 KoRTree<T>::LeafNode::~LeafNode()
00956 {
00957     //qDebug() << "LeafNode::~LeafNode" << this;
00958 }
00959 
00960 template <typename T>
00961 void KoRTree<T>::LeafNode::insert(const QRectF& bb, const T& data, int id)
00962 {
00963     m_data[this->m_counter] = data;
00964     m_dataIds[this->m_counter] = id;
00965     this->m_childBoundingBox[this->m_counter] = bb;
00966     this->m_boundingBox = this->m_boundingBox.unite(bb);
00967     ++this->m_counter;
00968 }
00969 
00970 template <typename T>
00971 void KoRTree<T>::LeafNode::remove(int index)
00972 {
00973     for (int i = index + 1; i < this->m_counter; ++i) {
00974         m_data[i-1] = m_data[i];
00975         m_dataIds[i-1] = m_dataIds[i];
00976     }
00977     Node::remove(index);
00978 }
00979 
00980 template <typename T>
00981 void KoRTree<T>::LeafNode::remove(const T& data)
00982 {
00983     int old_counter = this->m_counter;
00984     for (int i = 0; i < this->m_counter; ++i) {
00985         if (m_data[i] == data) {
00986             //qDebug() << "LeafNode::remove id" << i;
00987             remove(i);
00988             break;
00989         }
00990     }
00991     if (old_counter == this->m_counter) {
00992         kWarning(30003) << "LeafNode::remove( const T&data) data not found";
00993     }
00994 }
00995 
00996 template <typename T>
00997 void KoRTree<T>::LeafNode::move(Node * node, int index)
00998 {
00999     LeafNode * n = dynamic_cast<LeafNode*>(node);
01000     if (n) {
01001         //qDebug() << "LeafNode::move" << this << node << index
01002         //         << node->nodeId() << "->" << this->nodeId() << n->childBoundingBox( index );
01003         QRectF bb = n->childBoundingBox(index);
01004         insert(bb, n->getData(index), n->getDataId(index));
01005     }
01006 }
01007 
01008 template <typename T>
01009 typename KoRTree<T>::LeafNode * KoRTree<T>::LeafNode::chooseLeaf(const QRectF& bb)
01010 {
01011     Q_UNUSED(bb);
01012     return this;
01013 }
01014 
01015 template <typename T>
01016 typename KoRTree<T>::NoneLeafNode * KoRTree<T>::LeafNode::chooseNode(const QRectF& bb, int level)
01017 {
01018     Q_UNUSED(bb);
01019     Q_UNUSED(level);
01020     qFatal("LeafNode::chooseNode called. This should not happen!");
01021     return 0;
01022 }
01023 
01024 template <typename T>
01025 void KoRTree<T>::LeafNode::intersects(const QRectF& rect, QMap<int, T> & result) const
01026 {
01027     for (int i = 0; i < this->m_counter; ++i) {
01028         if (this->m_childBoundingBox[i].intersects(rect)) {
01029             result.insert(m_dataIds[i], m_data[i]);
01030         }
01031     }
01032 }
01033 
01034 template <typename T>
01035 void KoRTree<T>::LeafNode::contains(const QPointF & point, QMap<int, T> & result) const
01036 {
01037     for (int i = 0; i < this->m_counter; ++i) {
01038         if (this->m_childBoundingBox[i].contains(point)) {
01039             result.insert(m_dataIds[i], m_data[i]);
01040         }
01041     }
01042 }
01043 
01044 template <typename T>
01045 void KoRTree<T>::LeafNode::keys(QList<QRectF> & result) const
01046 {
01047     for (int i = 0; i < this->m_counter; ++i) {
01048         result.push_back(this->m_childBoundingBox[i]);
01049     }
01050 }
01051 
01052 template <typename T>
01053 void KoRTree<T>::LeafNode::values(QMap<int, T> & result) const
01054 {
01055     for (int i = 0; i < this->m_counter; ++i) {
01056         result.insert(m_dataIds[i], m_data[i]);
01057     }
01058 }
01059 
01060 template <typename T>
01061 const T& KoRTree<T>::LeafNode::getData(int index) const
01062 {
01063     return m_data[ index ];
01064 }
01065 
01066 template <typename T>
01067 int KoRTree<T>::LeafNode::getDataId(int index) const
01068 {
01069     return m_dataIds[ index ];
01070 }
01071 
01072 #ifdef KOFFICE_RTREE_DEBUG
01073 template <typename T>
01074 void KoRTree<T>::LeafNode::debug(QString line) const
01075 {
01076     for (int i = 0; i < this->m_counter; ++i) {
01077         qDebug("%s %d %d %p", qPrintable(line), this->nodeId(), i, &(m_data[i]));
01078         qDebug() << this->m_childBoundingBox[i].toRect();
01079     }
01080 }
01081 
01082 template <typename T>
01083 void KoRTree<T>::LeafNode::paint(QPainter & p, int level) const
01084 {
01085     if (this->m_counter) {
01086         this->paintRect(p, level);
01087     }
01088 }
01089 #endif
01090 
01091 #endif /* KORTREE_H */