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