File indexing completed on 2024-04-28 16:21:29

0001 /* This file is part of the KDE project
0002    Copyright 2010 Marijn Kruisselbrink <mkruisselbrink@kde.org>
0003    Copyright 2006 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License as published by the Free Software Foundation; either
0008    version 2 of the License, or (at your option) any later version.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018    Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #ifndef KSPREAD_RTREE
0022 #define KSPREAD_RTREE
0023 
0024 #include <QRect>
0025 #include <QVector>
0026 
0027 #include <KoRTree.h>
0028 
0029 #include "SheetsDebug.h"
0030 #include "calligra_sheets_limits.h"
0031 
0032 #include <algorithm>
0033 
0034 // Use dynamic_cast instead of cached root node
0035 // this is much slower but it is here so it is easy to check that still all works.
0036 //#define DYNAMIC_CAST
0037 
0038 namespace Calligra
0039 {
0040 namespace Sheets
0041 {
0042 
0043 /**
0044  * \class RTree
0045  * \brief An R-Tree template
0046  * \ingroup Storage
0047  *
0048  * An R-Tree template extended by special needs of Calligra Sheets:
0049  * \li adjusts the rectangles on insertion to avoid unwanted overlapping
0050  * (caused by different intersection/containment behaviour of QRectF and QRect)
0051  * \li checks for sane rectangle dimensions
0052  * \li provides insertion and deletion of columns and rows
0053  *
0054  * \author Stefan Nikolaus <stefan.nikolaus@kdemail.net>
0055  */
0056 template<typename T>
0057 class RTree : public KoRTree<T>
0058 {
0059 public:
0060     /**
0061      * Column/row insertion mode.
0062      */
0063     enum InsertMode {
0064         /// default insertion mode
0065         DefaultInsertMode = 0,
0066         /**
0067          * Shifts the rectangles, starting from the column/row preceding the
0068          * insertion position.
0069          * Thus, the inserted columns/rows carry the same data as the previous
0070          * column/row.
0071          */
0072         CopyPrevious = DefaultInsertMode,
0073         /**
0074          * Shifts the rectangles, starting from the column/row at the insertion
0075          * position.
0076          * Thus, the inserted columns/rows carry the same data as the current
0077          * column/row.
0078          */
0079         CopyCurrent,
0080         /**
0081          * Splits the rectangles at the insertion column/row position.
0082          * Thus, the inserted columns/rows do not carry any data.
0083          */
0084         CopyNone
0085     };
0086 
0087     /**
0088      * Constructs an empty R-Tree.
0089      */
0090     RTree();
0091 
0092     /**
0093      * Destroys the whole R-Tree.
0094      */
0095     ~RTree() override;
0096 
0097     /**
0098      * @brief Insert data item into the tree
0099      *
0100      * This will insert a data item into the tree. If necessary the tree will
0101      * adjust itself.
0102      *
0103      * \note Reimplemented for Calligra Sheets, because of the QRectF behaviour differs from
0104      * the one of QRect. Intersection or containment for boundary lines or points is
0105      * not the same, e.g. QRectF(1, 1, 1, 1) intersects QRectF(2, 1, 1, 1) while for
0106      * QRect it does not. Therefore, this method subtracts 0.1 from the width and
0107      * height of \p rect .
0108      *
0109      * @param data
0110      * @param rect
0111      */
0112     void insert(const QRectF& rect, const T& data) override;
0113 
0114     void load(const QList<QPair<QRegion, T> >& data);
0115 
0116     void remove(const QRectF& rect, const T& data, int id = -1);
0117 
0118     /**
0119      * Finds all data items at the location \p point .
0120      *
0121      * \param point where the objects have to be in
0122      *
0123      * \return objects at the location
0124      */
0125     virtual QList<T> contains(const QPointF& point) const;
0126 
0127     /**
0128      * Finds all data items that cover \p rect completely.
0129      *
0130      * \param rect where the objects have to be in
0131      *
0132      * \return objects containing the rect
0133      */
0134     virtual QList<T> contains(const QRectF& rect) const;
0135 
0136     /**
0137      * @brief Find all data items which intersects rect
0138      *
0139      * \note Reimplemented for Calligra Sheets, because of the QRectF behaviour differs from
0140      * the one of QRect. Intersection or containment for boundary lines or points is
0141      * not the same, e.g. QRectF(1, 1, 1, 1) intersects QRectF(2, 1, 1, 1) while for
0142      * QRect it does not. Therefore, this method subtracts 0.1 from the width and
0143      * height of \p rect .
0144      *
0145      * @param rect where the objects have to be in
0146      *
0147      * @return objects intersecting the rect
0148      */
0149     QList<T> intersects(const QRectF& rect) const override;
0150 
0151     virtual QMap<int, QPair<QRectF, T> > intersectingPairs(const QRectF& rect) const;
0152 
0153     /**
0154      * Inserts \p number rows at the position \p position .
0155      * It extends or shifts rectangles, respectively.
0156      * \return the removed rectangle/data pairs
0157      */
0158     virtual QList< QPair<QRectF, T> > insertRows(int position, int number, InsertMode mode = DefaultInsertMode);
0159 
0160     /**
0161      * Inserts \p number columns at the position \p position .
0162      * It extends or shifts rectangles, respectively.
0163      * \return the removed rectangle/data pairs
0164      */
0165     virtual QList< QPair<QRectF, T> > insertColumns(int position, int number, InsertMode mode = DefaultInsertMode);
0166 
0167     /**
0168      * Deletes \p number rows at the position \p position .
0169      * It shrinks or shifts rectangles, respectively.
0170      * \return the removed rectangle/data pairs
0171      */
0172     virtual QList< QPair<QRectF, T> > removeRows(int position, int number);
0173 
0174     /**
0175      * Deletes \p number columns at the position \p position .
0176      * It shrinks or shifts rectangles, respectively.
0177      * \return the removed rectangle/data pairs
0178      */
0179     virtual QList< QPair<QRectF, T> > removeColumns(int position, int number);
0180 
0181     /**
0182      * Shifts the rows right of \p rect to the right by the width of \p rect .
0183      * It extends or shifts rectangles, respectively.
0184      * \return the former rectangle/data pairs
0185      */
0186     virtual QList< QPair<QRectF, T> > insertShiftRight(const QRect& rect, InsertMode mode = DefaultInsertMode);
0187 
0188     /**
0189      * Shifts the columns at the bottom of \p rect to the bottom by the height of \p rect .
0190      * It extends or shifts rectangles, respectively.
0191      * \return the former rectangle/data pairs
0192      */
0193     virtual QList< QPair<QRectF, T> > insertShiftDown(const QRect& rect, InsertMode mode = DefaultInsertMode);
0194 
0195     /**
0196      * Shifts the rows left of \p rect to the left by the width of \p rect .
0197      * It shrinks or shifts rectangles, respectively.
0198      * \return the former rectangle/data pairs
0199      */
0200     virtual QList< QPair<QRectF, T> > removeShiftLeft(const QRect& rect);
0201 
0202     /**
0203      * Shifts the columns on top of \p rect to the top by the height of \p rect .
0204      * It shrinks or shifts rectangles, respectively.
0205      * \return the former rectangle/data pairs
0206      */
0207     virtual QList< QPair<QRectF, T> > removeShiftUp(const QRect& rect);
0208 
0209     /**
0210      * Assignment.
0211      */
0212     void operator=(const RTree& other);
0213 
0214     /**
0215      * Returns the bounding box for the entire tree.
0216      */
0217     QRectF boundingBox() const { return KoRTree<T>::m_root->boundingBox(); }
0218 
0219     void clear() override {
0220         KoRTree<T>::clear();
0221         m_castRoot = dynamic_cast<Node*>(this->m_root);
0222     }
0223 
0224 protected:
0225     class Node;
0226     class NonLeafNode;
0227     class LeafNode;
0228 
0229     // factory methods
0230     LeafNode* createLeafNode(int capacity, int level, typename KoRTree<T>::Node * parent) override {
0231         return new LeafNode(capacity, level, dynamic_cast<Node*>(parent));
0232     }
0233     NonLeafNode* createNonLeafNode(int capacity, int level, typename KoRTree<T>::Node * parent) override {
0234         return new NonLeafNode(capacity, level, dynamic_cast<Node*>(parent));
0235     }
0236 
0237     void adjustTree(typename KoRTree<T>::Node *node1, typename KoRTree<T>::Node *node2) override {
0238         KoRTree<T>::adjustTree(node1, node2);
0239         m_castRoot = dynamic_cast<Node*>(this->m_root);
0240     }
0241 
0242     void condenseTree(typename KoRTree<T>::Node * node, QVector<typename KoRTree<T>::Node *> & reinsert) override {
0243         KoRTree<T>::condenseTree(node, reinsert);
0244         m_castRoot = dynamic_cast<Node*>(this->m_root);
0245     }
0246 
0247 private:
0248     // disable copy constructor
0249     RTree(const RTree& other);
0250 
0251     struct LoadData {
0252         QRect rect;
0253         const T* data;
0254         qreal value;
0255         LoadData(const QRect& r, const T* d, qreal v)
0256             : rect(r), data(d), value(v)
0257         {}
0258     };
0259     struct LoadDataIndexCompare {
0260         const QList<LoadData>& m_data;
0261         LoadDataIndexCompare(const QList<LoadData>& data) : m_data(data) {}
0262         bool operator()(int a, int b) {
0263             return m_data[a].value < m_data[b].value;
0264         }
0265     };
0266     struct NodeLoadDataIndexCompare {
0267         const QList<QPair<Node*, qreal> >& m_data;
0268         NodeLoadDataIndexCompare(const QList<QPair<Node*, qreal> >& data) : m_data(data) {}
0269         bool operator()(int a, int b) {
0270             return m_data[a].second < m_data[b].second;
0271         }
0272     };
0273 
0274     Node* m_castRoot;
0275 };
0276 
0277 /**
0278  * Abstract base class for nodes and leaves.
0279  */
0280 template<typename T>
0281 class RTree<T>::Node : virtual public KoRTree<T>::Node
0282 {
0283 public:
0284     Node(int capacity, int level, Node * parent)
0285             : KoRTree<T>::Node(capacity, level, parent) {}
0286     ~Node() override {}
0287 
0288     void remove(int index) override {
0289         KoRTree<T>::Node::remove(index);
0290     }
0291     virtual void remove(const QRectF& rect, const T& data, int id = -1) = 0;
0292     void contains(const QPointF & point, QMap<int, T> & result) const override = 0;
0293     virtual void contains(const QRectF& rect, QMap<int, T>& result) const = 0;
0294     virtual void intersectingPairs(const QRectF& rect, QMap<int, QPair<QRectF, T> >& result) const = 0;
0295     virtual QMap< int, QPair<QRectF, T> > insertRows(int position, int number, InsertMode mode) = 0;
0296     virtual QMap< int, QPair<QRectF, T> > insertColumns(int position, int number, InsertMode mode) = 0;
0297     virtual QMap< int, QPair<QRectF, T> > removeRows(int position, int number) = 0;
0298     virtual QMap< int, QPair<QRectF, T> > removeColumns(int position, int number) = 0;
0299     const QRectF& childBoundingBox(int index) const override {
0300         return KoRTree<T>::Node::childBoundingBox(index);
0301     }
0302     QVector<QRectF> childBoundingBox() const {
0303         return this->m_childBoundingBox;
0304     }
0305 private:
0306     // disable copy constructor
0307     Node(const Node& other);
0308 };
0309 
0310 /**
0311  * An R-Tree leaf.
0312  */
0313 template<typename T>
0314 class RTree<T>::LeafNode : public RTree<T>::Node, public KoRTree<T>::LeafNode
0315 {
0316 public:
0317     LeafNode(int capacity, int level, RTree<T>::Node * parent)
0318             : KoRTree<T>::Node(capacity, level, parent)
0319             , RTree<T>::Node(capacity, level, parent)
0320             , KoRTree<T>::LeafNode(capacity, level, parent) {}
0321     ~LeafNode() override {}
0322 
0323     void remove(int index) override {
0324         KoRTree<T>::LeafNode::remove(index);
0325     }
0326     void remove(const T& data) override {
0327         KoRTree<T>::LeafNode::remove(data);
0328     }
0329     void remove(const QRectF& rect, const T& data, int id = -1) override;
0330     void contains(const QPointF & point, QMap<int, T> & result) const override {
0331         KoRTree<T>::LeafNode::contains(point, result);
0332     }
0333     void contains(const QRectF& rect, QMap<int, T>& result) const override;
0334     void intersectingPairs(const QRectF& rect, QMap<int, QPair<QRectF, T> >& result) const override;
0335     QMap< int, QPair<QRectF, T> > insertRows(int position, int number, InsertMode mode) override;
0336     QMap< int, QPair<QRectF, T> > insertColumns(int position, int number, InsertMode mode) override;
0337     QMap< int, QPair<QRectF, T> > removeRows(int position, int number) override;
0338     QMap< int, QPair<QRectF, T> > removeColumns(int position, int number) override;
0339     virtual void operator=(const LeafNode& other);
0340 private:
0341     // disable copy constructor
0342     LeafNode(const LeafNode& other);
0343 };
0344 
0345 /**
0346  * An R-Tree node.
0347  */
0348 template<typename T>
0349 class RTree<T>::NonLeafNode : public RTree<T>::Node, public KoRTree<T>::NonLeafNode
0350 {
0351 public:
0352     NonLeafNode(int capacity, int level, RTree<T>::Node * parent)
0353             : KoRTree<T>::Node(capacity, level, parent)
0354             , RTree<T>::Node(capacity, level, parent)
0355             , KoRTree<T>::NonLeafNode(capacity, level, parent) {}
0356     ~NonLeafNode() override {}
0357 
0358     void remove(int index) override {
0359         KoRTree<T>::NonLeafNode::remove(index);
0360     }
0361     void remove(const QRectF& rect, const T& data, int id = -1) override;
0362     void contains(const QPointF & point, QMap<int, T> & result) const override {
0363         KoRTree<T>::NonLeafNode::contains(point, result);
0364     }
0365     void contains(const QRectF& rect, QMap<int, T>& result) const override;
0366     void intersectingPairs(const QRectF& rect, QMap<int, QPair<QRectF, T> >& result) const override;
0367     QMap< int, QPair<QRectF, T> > insertRows(int position, int number, InsertMode mode) override;
0368     QMap< int, QPair<QRectF, T> > insertColumns(int position, int number, InsertMode mode) override;
0369     QMap< int, QPair<QRectF, T> > removeRows(int position, int number) override;
0370     QMap< int, QPair<QRectF, T> > removeColumns(int position, int number) override;
0371     virtual void operator=(const NonLeafNode& other);
0372 private:
0373     // disable copy constructor
0374     NonLeafNode(const NonLeafNode& other);
0375 };
0376 
0377 
0378 /////////////////////////////////////////////////////////////////////////////
0379 // RTree definition
0380 //
0381 template<typename T>
0382 RTree<T>::RTree()
0383         : KoRTree<T>(8, 4)
0384 {
0385     delete this->m_root;
0386     this->m_root = new LeafNode(this->m_capacity + 1, 0, 0);
0387     m_castRoot = dynamic_cast<Node*>(this->m_root);
0388 }
0389 
0390 template<typename T>
0391 RTree<T>::~RTree()
0392 {
0393 }
0394 
0395 template<typename T>
0396 void RTree<T>::insert(const QRectF& rect, const T& data)
0397 {
0398     Q_ASSERT(rect.x()      - (int)rect.x()      == 0.0);
0399     Q_ASSERT(rect.y()      - (int)rect.y()      == 0.0);
0400     Q_ASSERT(rect.height() - (int)rect.height() == 0.0);
0401     Q_ASSERT(rect.width()  - (int)rect.width()  == 0.0);
0402     KoRTree<T>::insert(rect.normalized().adjusted(0, 0, -0.1, -0.1), data);
0403 }
0404 
0405 static inline qreal calcLoadingRectValue(const QRectF& r)
0406 {
0407     QPointF center = r.center();
0408     // TODO: better value would be hilbert value of center of rect
0409     return center.x();
0410 }
0411 
0412 template<typename T>
0413 void RTree<T>::load(const QList<QPair<QRegion, T> >& data)
0414 {
0415     // clear current tree
0416     clear();
0417 
0418     // make rect->data mapping
0419     typedef QPair<QRegion, T> DataRegion;
0420     
0421     QList<LoadData> rectData;
0422     QVector<int> indices;
0423     foreach (const DataRegion& dataRegion, data) {
0424         foreach (const QRect& rect, dataRegion.first.rects()) {
0425             qreal h = calcLoadingRectValue(rect);
0426             rectData.append(LoadData(rect, &dataRegion.second, h));
0427             indices.append(indices.size());
0428         }
0429     }
0430 
0431     std::sort(indices.begin(), indices.end(), LoadDataIndexCompare(rectData));
0432 
0433     QList<QPair<Node*, qreal> > nodes;
0434     // create LeafNodes
0435     for (int i = 0; i < indices.size(); i += KoRTree<T>::m_capacity) {
0436         LeafNode* n = createLeafNode(KoRTree<T>::m_capacity + 1, 0, 0);
0437         for (int j = 0; j < KoRTree<T>::m_capacity && i+j < indices.size(); j++) {
0438             const LoadData& d = rectData[indices[i+j]];
0439             n->insert(QRectF(d.rect).normalized().adjusted(0, 0, -0.1, -0.1), *d.data, LeafNode::dataIdCounter + indices[i+j]);
0440         }
0441         n->updateBoundingBox();
0442         nodes.append(qMakePair<Node*, qreal>(n, calcLoadingRectValue(n->boundingBox())));
0443     }
0444     LeafNode::dataIdCounter += indices.size();
0445 
0446     while (nodes.size() > 1) {
0447         indices.resize(nodes.size());
0448         for (int i = 0; i < indices.size(); i++) indices[i] = i;
0449 
0450         std::sort(indices.begin(), indices.end(), NodeLoadDataIndexCompare(nodes));
0451 
0452         QList<QPair<Node*, qreal> > newNodes;
0453 
0454         for (int i = 0; i < indices.size(); i += KoRTree<T>::m_capacity) {
0455             NonLeafNode* n = createNonLeafNode(KoRTree<T>::m_capacity + 1, 0, 0);
0456             for (int j = 0; j < KoRTree<T>::m_capacity && i+j < indices.size(); j++) {
0457                 Node* oldNode = nodes[indices[i+j]].first;
0458                 n->insert(oldNode->boundingBox(), oldNode);
0459             }
0460             n->updateBoundingBox();
0461             newNodes.append(qMakePair<Node*, qreal>(n, calcLoadingRectValue(n->boundingBox())));
0462         }
0463         nodes = newNodes;
0464     }
0465 
0466     if (!nodes.isEmpty()) {
0467         // set root node
0468         delete KoRTree<T>::m_root;
0469         KoRTree<T>::m_root = nodes.first().first;
0470         m_castRoot = dynamic_cast<Node*>(this->m_root);
0471     }
0472 }
0473 
0474 template<typename T>
0475 void RTree<T>::remove(const QRectF& rect, const T& data, int id)
0476 {
0477     Q_ASSERT(rect.x()      - (int)rect.x()      == 0.0);
0478     Q_ASSERT(rect.y()      - (int)rect.y()      == 0.0);
0479     Q_ASSERT(rect.height() - (int)rect.height() == 0.0);
0480     Q_ASSERT(rect.width()  - (int)rect.width()  == 0.0);
0481 #ifdef DYNAMIC_CAST
0482     dynamic_cast<Node*>(this->m_root)->remove(rect.normalized().adjusted(0, 0, -0.1, -0.1), data, id);
0483 #else
0484     m_castRoot->remove(rect.normalized().adjusted(0, 0, -0.1, -0.1), data, id);
0485 #endif
0486 }
0487 
0488 template<typename T>
0489 QList<T> RTree<T>::contains(const QPointF& point) const
0490 {
0491     return KoRTree<T>::contains(point);
0492 }
0493 
0494 template<typename T>
0495 QList<T> RTree<T>::contains(const QRectF& rect) const
0496 {
0497     Q_ASSERT(rect.x()      - (int)rect.x()      == 0.0);
0498     Q_ASSERT(rect.y()      - (int)rect.y()      == 0.0);
0499     Q_ASSERT(rect.height() - (int)rect.height() == 0.0);
0500     Q_ASSERT(rect.width()  - (int)rect.width()  == 0.0);
0501     QMap<int, T> result;
0502 #ifdef DYNAMIC_CAST
0503     dynamic_cast<Node*>(this->m_root)->contains(rect.normalized().adjusted(0, 0, -0.1, -0.1), result);
0504 #else
0505     m_castRoot->contains(rect.normalized().adjusted(0, 0, -0.1, -0.1), result);
0506 #endif
0507     return result.values();
0508 }
0509 
0510 template<typename T>
0511 QList<T> RTree<T>::intersects(const QRectF& rect) const
0512 {
0513     Q_ASSERT(rect.x()      - (int)rect.x()      == 0.0);
0514     Q_ASSERT(rect.y()      - (int)rect.y()      == 0.0);
0515     Q_ASSERT(rect.height() - (int)rect.height() == 0.0);
0516     Q_ASSERT(rect.width()  - (int)rect.width()  == 0.0);
0517     return KoRTree<T>::intersects(rect.normalized().adjusted(0, 0, -0.1, -0.1));
0518 }
0519 
0520 template<typename T>
0521 QMap<int, QPair<QRectF, T> > RTree<T>::intersectingPairs(const QRectF& rect) const
0522 {
0523     Q_ASSERT(rect.x()      - (int)rect.x()      == 0.0);
0524     Q_ASSERT(rect.y()      - (int)rect.y()      == 0.0);
0525     Q_ASSERT(rect.height() - (int)rect.height() == 0.0);
0526     Q_ASSERT(rect.width()  - (int)rect.width()  == 0.0);
0527     QMap<int, QPair<QRectF, T> > result;
0528 #ifdef DYNAMIC_CAST
0529     dynamic_cast<Node*>(this->m_root)->intersectingPairs(rect.normalized().adjusted(0, 0, -0.1, -0.1), result);
0530 #else
0531     m_castRoot->intersectingPairs(rect.normalized().adjusted(0, 0, -0.1, -0.1), result);
0532 #endif
0533     return result;
0534 }
0535 
0536 template<typename T>
0537 QList< QPair<QRectF, T> > RTree<T>::insertRows(int position, int number, InsertMode mode)
0538 {
0539     Q_ASSERT(position >= 1);
0540     Q_ASSERT(position <= KS_rowMax);
0541     if (position < 1 || position > KS_rowMax)
0542         return QList< QPair<QRectF, T> >();
0543 #ifdef DYNAMIC_CAST
0544     return dynamic_cast<Node*>(this->m_root)->insertRows(position, number, mode).values();
0545 #else
0546     return m_castRoot->insertRows(position, number, mode).values();
0547 #endif
0548 }
0549 
0550 template<typename T>
0551 QList< QPair<QRectF, T> > RTree<T>::insertColumns(int position, int number, InsertMode mode)
0552 {
0553     Q_ASSERT(position >= 1);
0554     Q_ASSERT(position <= KS_colMax);
0555     if (position < 1 || position > KS_colMax)
0556         return QList< QPair<QRectF, T> >();
0557 #ifdef DYNAMIC_CAST
0558     return dynamic_cast<Node*>(this->m_root)->insertColumns(position, number, mode).values();
0559 #else
0560     return m_castRoot->insertColumns(position, number, mode).values();
0561 #endif
0562 }
0563 
0564 template<typename T>
0565 QList< QPair<QRectF, T> > RTree<T>::removeRows(int position, int number)
0566 {
0567     Q_ASSERT(position >= 1);
0568     Q_ASSERT(position <= KS_rowMax);
0569     if (position < 1 || position > KS_rowMax)
0570         return QList< QPair<QRectF, T> >();
0571 #ifdef DYNAMIC_CAST
0572     return dynamic_cast<Node*>(this->m_root)->removeRows(position, number).values();
0573 #else
0574     return m_castRoot->removeRows(position, number).values();
0575 #endif
0576 }
0577 
0578 template<typename T>
0579 QList< QPair<QRectF, T> > RTree<T>::removeColumns(int position, int number)
0580 {
0581     Q_ASSERT(position >= 1);
0582     Q_ASSERT(position <= KS_colMax);
0583     if (position < 1 || position > KS_colMax)
0584         return QList< QPair<QRectF, T> >();
0585 #ifdef DYNAMIC_CAST
0586     return dynamic_cast<Node*>(this->m_root)->removeColumns(position, number).values();
0587 #else
0588     return m_castRoot->removeColumns(position, number).values();
0589 #endif
0590 }
0591 
0592 template<typename T>
0593 QList< QPair<QRectF, T> > RTree<T>::insertShiftRight(const QRect& r, InsertMode mode)
0594 {
0595     const QRect rect(r.normalized());
0596     if (rect.left() < 1 || rect.left() > KS_colMax)
0597         return QList< QPair<QRectF, T> >();
0598     const QRect boundingRect = QRect(rect.topLeft(), QPoint(KS_colMax, rect.bottom()));
0599     const QList< QPair<QRectF, T> > oldPairs = intersectingPairs(boundingRect).values();
0600     if (oldPairs.isEmpty())
0601         return QList< QPair<QRectF, T> >();
0602     // insert default data at the bounding rectangle
0603     insert(boundingRect, T());
0604     // fill the inserted rectangle
0605     if (mode != CopyNone) {
0606         const int offset = (mode == CopyPrevious) ? 1 : 0;
0607         const QRect copyRect = QRect(rect.left() - offset, rect.top(), 1, rect.height());
0608         const QList< QPair<QRectF, T> > copyPairs = intersectingPairs(copyRect).values();
0609         for (int i = 0; i < copyPairs.count(); ++i) {
0610             insert((copyPairs[i].first.toRect() & copyRect).adjusted(offset, 0, rect.width() + offset - 1, 0), copyPairs[i].second);
0611         }
0612     }
0613     // insert the data at the shifted rectangles
0614     for (int i = 0; i < oldPairs.count(); ++i) {
0615         const QRect shiftedRect = oldPairs[i].first.toRect().adjusted(rect.width(), 0, rect.width(), 0);
0616         insert(shiftedRect & boundingRect, oldPairs[i].second);
0617     }
0618     return oldPairs;
0619 }
0620 
0621 template<typename T>
0622 QList< QPair<QRectF, T> > RTree<T>::insertShiftDown(const QRect& r, InsertMode mode)
0623 {
0624     Q_UNUSED(mode);
0625     const QRect rect(r.normalized());
0626     if (rect.top() < 1 || rect.top() > KS_rowMax)
0627         return QList< QPair<QRectF, T> >();
0628     const QRect boundingRect = QRect(rect.topLeft(), QPoint(rect.right(), KS_rowMax));
0629     const QList< QPair<QRectF, T> > oldPairs = intersectingPairs(boundingRect).values();
0630     if (oldPairs.isEmpty())
0631         return QList< QPair<QRectF, T> >();
0632     // insert default data at the bounding rectangle
0633     insert(boundingRect, T());
0634     // fill the inserted rectangle
0635     if (mode != CopyNone) {
0636         const int offset = (mode == CopyPrevious) ? 1 : 0;
0637         const QRect copyRect = QRect(rect.left(), rect.top() - offset, rect.width(), 1);
0638         const QList< QPair<QRectF, T> > copyPairs = intersectingPairs(copyRect).values();
0639         for (int i = 0; i < copyPairs.count(); ++i) {
0640             insert((copyPairs[i].first.toRect() & copyRect).adjusted(0, offset, 0, rect.height() + offset - 1), copyPairs[i].second);
0641         }
0642     }
0643     // insert the data at the shifted rectangles
0644     for (int i = 0; i < oldPairs.count(); ++i) {
0645         const QRect shiftedRect = oldPairs[i].first.toRect().adjusted(0, rect.height(), 0, rect.height());
0646         insert(shiftedRect & boundingRect, oldPairs[i].second);
0647     }
0648     return oldPairs;
0649 }
0650 
0651 template<typename T>
0652 QList< QPair<QRectF, T> > RTree<T>::removeShiftLeft(const QRect& r)
0653 {
0654     const QRect rect(r.normalized());
0655     if (rect.left() < 1 || rect.left() > KS_colMax)
0656         return QList< QPair<QRectF, T> >();
0657     const QRect boundingRect = QRect(rect.topLeft(), QPoint(KS_colMax, rect.bottom()));
0658     const QList< QPair<QRectF, T> > oldPairs = intersectingPairs(boundingRect).values();
0659     if (oldPairs.isEmpty())
0660         return QList< QPair<QRectF, T> >();
0661     // insert default data at the bounding rectangle
0662     insert(boundingRect, T());
0663     // insert the data at the shifted rectangles
0664     for (int i = 0; i < oldPairs.count(); ++i) {
0665         const QRect shiftedRect = oldPairs[i].first.toRect().adjusted(-rect.width(), 0, -rect.width(), 0);
0666         insert(shiftedRect & boundingRect, oldPairs[i].second);
0667     }
0668     return oldPairs;
0669 }
0670 
0671 template<typename T>
0672 QList< QPair<QRectF, T> > RTree<T>::removeShiftUp(const QRect& r)
0673 {
0674     const QRect rect(r.normalized());
0675     if (rect.top() < 1 || rect.top() > KS_rowMax)
0676         return QList< QPair<QRectF, T> >();
0677     const QRect boundingRect = QRect(rect.topLeft(), QPoint(rect.right(), KS_rowMax));
0678     const QList< QPair<QRectF, T> > oldPairs = intersectingPairs(boundingRect).values();
0679     if (oldPairs.isEmpty())
0680         return QList< QPair<QRectF, T> >();
0681     // insert default data at the bounding rectangle
0682     insert(boundingRect, T());
0683     // insert the data at the shifted rectangles
0684     for (int i = 0; i < oldPairs.count(); ++i) {
0685         const QRect shiftedRect = oldPairs[i].first.toRect().adjusted(0, -rect.height(), 0, -rect.height());
0686         insert(shiftedRect & boundingRect, oldPairs[i].second);
0687     }
0688     return oldPairs;
0689 }
0690 
0691 template<typename T>
0692 void RTree<T>::operator=(const RTree<T>& other)
0693 {
0694     this->m_capacity = other.m_capacity;
0695     this->m_minimum = other.m_minimum;
0696     delete this->m_root;
0697     if (other.m_root->isLeaf()) {
0698         this->m_root = new LeafNode(this->m_capacity + 1, 0, 0);
0699         *dynamic_cast<LeafNode*>(this->m_root) = *dynamic_cast<LeafNode*>(other.m_root);
0700     } else {
0701         this->m_root = new NonLeafNode(this->m_capacity + 1, 0, 0);
0702         *dynamic_cast<NonLeafNode*>(this->m_root) = *dynamic_cast<NonLeafNode*>(other.m_root);
0703     }
0704     m_castRoot = dynamic_cast<Node*>(this->m_root);
0705 }
0706 
0707 /////////////////////////////////////////////////////////////////////////////
0708 // RTree<T>::LeafNode definition
0709 //
0710 template<typename T>
0711 void RTree<T>::LeafNode::remove(const QRectF& rect, const T& data, int id)
0712 {
0713     for (int i = 0; i < this->m_counter; ++i) {
0714         if (this->m_childBoundingBox[i] == rect && this->m_data[i] == data && (id == -1 || this->m_dataIds[i] == id)) {
0715             //qDebug() << "LeafNode::remove id" << i;
0716             KoRTree<T>::LeafNode::remove(i);
0717             break;
0718         }
0719     }
0720 }
0721 
0722 template<typename T>
0723 void RTree<T>::LeafNode::contains(const QRectF& rect, QMap<int, T>& result) const
0724 {
0725     for (int i = 0; i < this->m_counter; ++i) {
0726         if (this->m_childBoundingBox[i].contains(rect)) {
0727             result.insert(this->m_dataIds[i], this->m_data[i]);
0728         }
0729     }
0730 }
0731 
0732 template<typename T>
0733 void RTree<T>::LeafNode::intersectingPairs(const QRectF& rect, QMap<int, QPair<QRectF, T> >& result) const
0734 {
0735     for (int i = 0; i < this->m_counter; ++i) {
0736         if (this->m_childBoundingBox[i].intersects(rect)) {
0737             QRectF rect = this->m_childBoundingBox[i].adjusted(0, 0, 0.1, 0.1);
0738             result.insert(this->m_dataIds[i], qMakePair(rect, this->m_data[i]));
0739         }
0740     }
0741 }
0742 
0743 template<typename T>
0744 QMap< int, QPair<QRectF, T> > RTree<T>::LeafNode::insertRows(int position, int number, InsertMode mode)
0745 {
0746     if (position - (mode == CopyPrevious ? 1 : 0) > this->m_boundingBox.bottom())
0747         return QMap< int, QPair<QRectF, T> >();
0748 
0749     QMap< int, QPair<QRectF, T> > result;
0750 
0751     int shift = 0, endShift = number;
0752     // Don't process complete columns.
0753     if (this->m_boundingBox.top() != 1 || this->m_boundingBox.bottom() != KS_rowMax) {
0754         if (mode == CopyNone)
0755             shift = 0;
0756         else if (position - (mode == CopyPrevious ? 1 : 0) < this->m_boundingBox.top())
0757             shift = number;
0758         if (position - (mode == CopyPrevious ? 1 : 0) < this->m_boundingBox.toRect().bottom())
0759             endShift = number;
0760         else
0761             endShift = 0;
0762         this->m_boundingBox.adjust(0, shift, 0, endShift);
0763     }
0764 
0765     for (int i = 0; i < this->childCount(); ++i) {
0766         // Don't process complete columns.
0767         if (this->m_childBoundingBox[i].top() == 1 && this->m_childBoundingBox[i].bottom() == KS_rowMax)
0768             continue;
0769 
0770         if (mode == CopyNone)
0771             shift = 0;
0772         else if (position - (mode == CopyPrevious ? 1 : 0) < this->m_childBoundingBox[i].top())
0773             shift = number;
0774         else
0775             shift = 0;
0776 
0777         if (position - (mode == CopyPrevious ? 1 : 0) < this->m_childBoundingBox[i].toRect().bottom())
0778             endShift = number;
0779         else
0780             endShift = 0;
0781         this->m_childBoundingBox[i].adjust(0, shift, 0, endShift);
0782     }
0783 
0784     return QMap< int, QPair<QRectF, T> >(); // FIXME
0785 }
0786 
0787 template<typename T>
0788 QMap< int, QPair<QRectF, T> > RTree<T>::LeafNode::insertColumns(int position, int number, InsertMode mode)
0789 {
0790     if (position - (mode == CopyPrevious ? 1 : 0) > this->m_boundingBox.right())
0791         return QMap< int, QPair<QRectF, T> >();
0792 
0793     QMap< int, QPair<QRectF, T> > result;
0794 
0795     int shift = 0;
0796     // Don't process complete rows.
0797     if (this->m_boundingBox.left() != 1 || this->m_boundingBox.right() != KS_colMax) {
0798         if (mode == CopyNone)
0799             shift = 0;
0800         else if (position - (mode == CopyPrevious ? 1 : 0) < this->m_boundingBox.left())
0801             shift = number;
0802         this->m_boundingBox.adjust(shift, 0, number, 0);
0803     }
0804 
0805     for (int i = 0; i < this->childCount(); ++i) {
0806         // Don't process complete rows.
0807         if (this->m_childBoundingBox[i].left() == 1 && this->m_childBoundingBox[i].right() == KS_rowMax)
0808             continue;
0809 
0810         if (mode == CopyNone)
0811             shift = 0;
0812         else if (position - (mode == CopyPrevious ? 1 : 0) < this->m_childBoundingBox[i].left())
0813             shift = number;
0814         else
0815             shift = 0;
0816         this->m_childBoundingBox[i].adjust(shift, 0, number, 0);
0817     }
0818 
0819     return QMap< int, QPair<QRectF, T> >(); // FIXME
0820 }
0821 
0822 template<typename T>
0823 QMap< int, QPair<QRectF, T> > RTree<T>::LeafNode::removeRows(int position, int number)
0824 {
0825     if (position > this->m_boundingBox.bottom())
0826         return QMap< int, QPair<QRectF, T> >();
0827 
0828     QMap< int, QPair<QRectF, T> > removedPairs;
0829 
0830     QRect rect = this->m_boundingBox.toRect();
0831     int shift = 0;
0832     int cut = 0;
0833     // Don't process complete columns.
0834     if (this->m_boundingBox.top() != 1 || this->m_boundingBox.bottom() != KS_rowMax) {
0835         if (position < rect.top()) {
0836             shift = qMin(rect.top() - position, number);
0837             cut = qMax(0, position + number - rect.top());
0838         } else {
0839             shift = 0;
0840             cut = qMin(number, rect.bottom() - position + 1);
0841         }
0842         this->m_boundingBox.adjust(0, -shift, 0, -shift - cut);
0843     }
0844 
0845     for (int i = 0; i < this->childCount(); ++i) {
0846         // Don't process complete columns.
0847         if (this->m_childBoundingBox[i].top() == 1 && this->m_childBoundingBox[i].bottom() == KS_rowMax)
0848             continue;
0849 
0850         const QRectF oldRect(this->m_childBoundingBox[ i ]);
0851         rect = this->m_childBoundingBox[i].toRect();
0852         if (position < rect.top()) {
0853             shift = qMin(rect.top() - position, number);
0854             cut = qMax(0, position + number - rect.top());
0855         } else {
0856             shift = 0;
0857             cut = qMin(number, rect.bottom() - position + 1);
0858         }
0859         this->m_childBoundingBox[i].adjust(0, -shift, 0, -shift - cut);
0860 
0861         if (this->m_childBoundingBox[ i ].isEmpty()) {
0862             removedPairs.insert(this->m_dataIds[i], qMakePair(oldRect, this->m_data[i]));
0863             KoRTree<T>::LeafNode::remove(i--);
0864         }
0865     }
0866     return removedPairs;
0867 }
0868 
0869 template<typename T>
0870 QMap< int, QPair<QRectF, T> > RTree<T>::LeafNode::removeColumns(int position, int number)
0871 {
0872     if (position > this->m_boundingBox.right())
0873         return QMap< int, QPair<QRectF, T> >();
0874 
0875     QMap< int, QPair<QRectF, T> > removedPairs;
0876 
0877     QRect rect = this->m_boundingBox.toRect();
0878     int shift = 0;
0879     int cut = 0;
0880     // Don't process complete rows.
0881     if (this->m_boundingBox.left() != 1 || this->m_boundingBox.right() != KS_colMax) {
0882         if (position < rect.left()) {
0883             shift = qMin(rect.left() - position, number);
0884             cut = qMax(0, position + number - rect.left());
0885         } else {
0886             shift = 0;
0887             cut = qMin(number, rect.right() - position + 1);
0888         }
0889         this->m_boundingBox.adjust(-shift, 0, -shift - cut, 0);
0890     }
0891 
0892     for (int i = 0; i < this->childCount(); ++i) {
0893         // Don't process complete rows.
0894         if (this->m_childBoundingBox[i].left() == 1 && this->m_childBoundingBox[i].right() == KS_rowMax)
0895             continue;
0896 
0897         const QRectF oldRect(this->m_childBoundingBox[ i ]);
0898         rect = this->m_childBoundingBox[i].toRect();
0899         if (position < rect.left()) {
0900             shift = qMin(rect.left() - position, number);
0901             cut = qMax(0, position + number - rect.left());
0902         } else {
0903             shift = 0;
0904             cut = qMin(number, rect.right() - position + 1);
0905         }
0906         this->m_childBoundingBox[i].adjust(-shift, 0, -shift - cut, 0);
0907 
0908         if (this->m_childBoundingBox[ i ].isEmpty()) {
0909             removedPairs.insert(this->m_dataIds[i], qMakePair(oldRect, this->m_data[i]));
0910             KoRTree<T>::LeafNode::remove(i--);
0911         }
0912     }
0913     return removedPairs;
0914 }
0915 
0916 template<typename T>
0917 void RTree<T>::LeafNode::operator=(const LeafNode& other)
0918 {
0919     // leave alone the m_parent
0920     this->m_boundingBox = other.m_boundingBox;
0921     this->m_childBoundingBox = other.m_childBoundingBox;
0922     this->m_counter = other.m_counter;
0923     this->m_place = other.m_place;
0924 #ifdef CALLIGRA_RTREE_DEBUG
0925     this->m_nodeId = other.m_nodeId;
0926 #endif
0927     this->m_level = other.m_level;
0928     this->m_data = other.m_data;
0929     this->m_dataIds = other.m_dataIds;
0930 }
0931 
0932 /////////////////////////////////////////////////////////////////////////////
0933 // RTree<T>::NonLeafNode definition
0934 //
0935 template<typename T>
0936 void RTree<T>::NonLeafNode::remove(const QRectF& rect, const T& data, int id)
0937 {
0938     for (int i = 0; i < this->m_counter; ++i) {
0939         if (this->m_childBoundingBox[i].contains(rect)) {
0940             dynamic_cast<Node*>(this->m_childs[i])->remove(rect, data, id);
0941         }
0942     }
0943 }
0944 
0945 template<typename T>
0946 void RTree<T>::NonLeafNode::contains(const QRectF& rect, QMap<int, T>& result) const
0947 {
0948     for (int i = 0; i < this->m_counter; ++i) {
0949         if (this->m_childBoundingBox[i].intersects(rect)) {
0950             this->m_childs[i]->intersects(rect, result);
0951         }
0952     }
0953 }
0954 
0955 template<typename T>
0956 void RTree<T>::NonLeafNode::intersectingPairs(const QRectF& rect, QMap<int, QPair<QRectF, T> >& result) const
0957 {
0958     for (int i = 0; i < this->m_counter; ++i) {
0959         if (this->m_childBoundingBox[i].intersects(rect)) {
0960             dynamic_cast<Node*>(this->m_childs[i])->intersectingPairs(rect, result);
0961         }
0962     }
0963 }
0964 
0965 template<typename T>
0966 QMap< int, QPair<QRectF, T> > RTree<T>::NonLeafNode::insertRows(int position, int number, InsertMode mode)
0967 {
0968     if (position - (mode == CopyPrevious ? 1 : 0) > this->m_boundingBox.bottom())
0969         return QMap< int, QPair<QRectF, T> >();
0970 
0971     QMap< int, QPair<QRectF, T> > result;
0972 
0973     for (int i = 0; i < this->childCount(); ++i) {
0974         this->m_childBoundingBox[i].adjust(0, (position < this->m_childBoundingBox[i].top()) ? number : 0, 0, number);
0975         result.unite(dynamic_cast<Node*>(this->m_childs[i])->insertRows(position, number, mode));
0976     }
0977 
0978     // position < m_rect.top() ? shift : extend
0979     this->m_boundingBox.adjust(0, (position < this->m_boundingBox.top()) ? number : 0, 0, number);
0980     return QMap< int, QPair<QRectF, T> >(); // FIXME
0981 }
0982 
0983 template<typename T>
0984 QMap< int, QPair<QRectF, T> > RTree<T>::NonLeafNode::insertColumns(int position, int number, InsertMode mode)
0985 {
0986     if (position - (mode == CopyPrevious ? 1 : 0) > this->m_boundingBox.right())
0987         return QMap< int, QPair<QRectF, T> >();
0988 
0989     QMap< int, QPair<QRectF, T> > result;
0990 
0991     for (int i = 0; i < this->childCount(); ++i) {
0992         this->m_childBoundingBox[i].adjust((position < this->m_childBoundingBox[i].left()) ? number : 0, 0, number, 0);
0993         result.unite(dynamic_cast<Node*>(this->m_childs[i])->insertColumns(position, number, mode));
0994     }
0995 
0996     // position < m_rect.left() ? shift : extend
0997     this->m_boundingBox.adjust((position < this->m_boundingBox.left()) ? number : 0, 0, number, 0);
0998     return QMap< int, QPair<QRectF, T> >(); // FIXME
0999 }
1000 
1001 template<typename T>
1002 QMap< int, QPair<QRectF, T> > RTree<T>::NonLeafNode::removeRows(int position, int number)
1003 {
1004     if (position > this->m_boundingBox.bottom())
1005         return QMap< int, QPair<QRectF, T> >();
1006 
1007     QMap< int, QPair<QRectF, T> > removedPairs;
1008 
1009     QRect rect = this->m_boundingBox.toRect();
1010     int shift = 0;
1011     int cut = 0;
1012     if (position < rect.top()) {
1013         shift = qMin(rect.top() - position, number);
1014         cut = qMax(0, position + number - rect.top());
1015     } else {
1016         shift = 0;
1017         cut = qMin(number, rect.bottom() - position + 1);
1018     }
1019     this->m_boundingBox.adjust(0, -shift, 0, -shift - cut);
1020 
1021     for (int i = 0; i < this->childCount(); ++i) {
1022         rect = this->m_childBoundingBox[i].toRect();
1023         if (position < rect.top()) {
1024             shift = qMin(rect.top() - position, number);
1025             cut = qMax(0, position + number - rect.top());
1026         } else {
1027             shift = 0;
1028             cut = qMin(number, rect.bottom() - position + 1);
1029         }
1030         this->m_childBoundingBox[i].adjust(0, -shift, 0, -shift - cut);
1031 
1032         removedPairs.unite(dynamic_cast<Node*>(this->m_childs[i])->removeRows(position, number));
1033         if (this->m_childBoundingBox[ i ].isEmpty()) {
1034             delete this->m_childs[i];
1035             KoRTree<T>::NonLeafNode::remove(i--);
1036         }
1037     }
1038     return removedPairs;
1039 }
1040 
1041 template<typename T>
1042 QMap< int, QPair<QRectF, T> > RTree<T>::NonLeafNode::removeColumns(int position, int number)
1043 {
1044     if (position > this->m_boundingBox.right())
1045         return QMap< int, QPair<QRectF, T> >();
1046 
1047     QMap< int, QPair<QRectF, T> > removedPairs;
1048 
1049     QRect rect = this->m_boundingBox.toRect();
1050     int shift = 0;
1051     int cut = 0;
1052     if (position < rect.left()) {
1053         shift = qMin(rect.left() - position, number);
1054         cut = qMax(0, position + number - rect.left());
1055     } else {
1056         shift = 0;
1057         cut = qMin(number, rect.right() - position + 1);
1058     }
1059     this->m_boundingBox.adjust(-shift, 0, -shift - cut, 0);
1060 
1061     for (int i = 0; i < this->childCount(); ++i) {
1062         rect = this->m_childBoundingBox[i].toRect();
1063         if (position < rect.left()) {
1064             shift = qMin(rect.left() - position, number);
1065             cut = qMax(0, position + number - rect.left());
1066         } else {
1067             shift = 0;
1068             cut = qMin(number, rect.right() - position + 1);
1069         }
1070         this->m_childBoundingBox[i].adjust(-shift, 0, -shift - cut, 0);
1071 
1072         removedPairs.unite(dynamic_cast<Node*>(this->m_childs[i])->removeColumns(position, number));
1073         if (this->m_childBoundingBox[ i ].isEmpty()) {
1074             delete this->m_childs[i];
1075             KoRTree<T>::NonLeafNode::remove(i--);
1076         }
1077     }
1078     return removedPairs;
1079 }
1080 
1081 template<typename T>
1082 void RTree<T>::NonLeafNode::operator=(const NonLeafNode& other)
1083 {
1084     // leave alone the m_parent
1085     this->m_boundingBox = other.m_boundingBox;
1086     this->m_childBoundingBox = other.childBoundingBox();
1087     this->m_counter = other.m_counter;
1088     this->m_place = other.m_place;
1089 #ifdef CALLIGRA_RTREE_DEBUG
1090     this->m_nodeId = other.m_nodeId;
1091 #endif
1092     this->m_level = other.m_level;
1093     for (int i = 0; i < other.m_counter; ++i) {
1094         if (other.m_childs[i]->isLeaf()) {
1095             LeafNode* child = dynamic_cast<LeafNode*>(other.m_childs[i]);
1096             this->m_childs[i] = new LeafNode(child->childBoundingBox().size(), child->level(), this);
1097             *dynamic_cast<LeafNode*>(this->m_childs[i]) = *child;
1098         } else {
1099             NonLeafNode* child = dynamic_cast<NonLeafNode*>(other.m_childs[i]);
1100             this->m_childs[i] = new NonLeafNode(child->childBoundingBox().size(), child->level(), this);
1101             *dynamic_cast<NonLeafNode*>(this->m_childs[i]) = *child;
1102         }
1103     }
1104 }
1105 
1106 } // namespace Sheets
1107 } // namespace Calligra
1108 
1109 #endif // KSPREAD_RTREE