F:/KPlato/koffice/libs/kofficecore/KoRTree.h

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

Généré le Wed Nov 22 23:41:04 2006 pour KPlato par  doxygen 1.5.1-p1