18#include <QVarLengthArray>
24#ifdef CALLIGRA_RTREE_DEBUG
63 virtual void insert(
const QRectF& bb,
const T& data);
133#ifdef CALLIGRA_RTREE_DEBUG
139 void paint(QPainter &
p)
const;
154#ifdef CALLIGRA_RTREE_DEBUG
155 static int nodeIdCnt;
168 virtual void contains(
const QPointF & point, QMap<int, T> & result)
const = 0;
169 virtual void contained(
const QRectF & point, QMap<int, T> & result)
const = 0;
172 virtual void values(QMap<int, T> & result)
const = 0;
219#ifdef CALLIGRA_RTREE_DEBUG
220 virtual int nodeId()
const {
224 virtual void paint(QPainter &
p,
int level)
const = 0;
225 virtual void debug(QString line)
const = 0;
228#define levelColorSize 5
229 static QColor levelColor[levelColorSize];
230 virtual void paintRect(QPainter &
p,
int level)
const;
239#ifdef CALLIGRA_RTREE_DEBUG
259 void contains(
const QPointF & point, QMap<int, T> & result)
const override;
260 void contained(
const QRectF & point, QMap<int, T> & result)
const override;
263 void values(QMap<int, T> & result)
const override;
267#ifdef CALLIGRA_RTREE_DEBUG
268 virtual void paint(QPainter &
p,
int level)
const;
269 virtual void debug(QString line)
const;
285 virtual void insert(
const QRectF& bb,
const T& data,
int id);
294 void contains(
const QPointF & point, QMap<int, T> & result)
const override;
295 void contained(
const QRectF & point, QMap<int, T> & result)
const override;
298 void values(QMap<int, T> & result)
const override;
307#ifdef CALLIGRA_RTREE_DEBUG
308 virtual void debug(QString line)
const;
309 virtual void paint(QPainter &
p,
int level)
const;
318 return new LeafNode(capacity, level, parent);
343 : m_capacity(capacity)
345 , m_root(createLeafNode(m_capacity + 1, 0, 0))
347 if (minimum > capacity / 2)
348 qFatal(
"KoRTree::KoRTree minimum can be maximal capacity/2");
364 insertHelper(bb, data, LeafNode::dataIdCounter++);
370 QRectF nbb(bb.normalized());
373 qWarning() <<
"KoRTree::insert boundingBox isNull setting size to" << nbb.size();
375 nbb.setWidth(0.0001);
376 nbb.setHeight(0.0001);
381 if ( nbb.width() == 0 ) {
382 nbb.setWidth(0.0001);
384 if ( nbb.height() == 0 ) {
385 nbb.setHeight(0.0001);
393 leaf->
insert(nbb, data,
id);
394 m_leafMap[data] = leaf;
397 leaf->
insert(nbb, data,
id);
398 m_leafMap[data] = leaf;
399 QPair<Node *, Node *> newNodes = splitNode(leaf);
404 l =
dynamic_cast<LeafNode *
>(newNodes.second);
409 adjustTree(newNodes.first, newNodes.second);
416 if (node->
level() == m_root->level()) {
417 adjustTree(m_root, node);
422 newParent->
insert(bb, node);
424 QPair<Node *, Node *> newNodes(node, 0);
426 newNodes = splitNode(newParent);
428 adjustTree(newNodes.first, newNodes.second);
435 return m_leafMap[data];
449 m_leafMap.remove(data);
460 condenseTree(leaf, reinsert);
462 for (
int i = 0; i < reinsert.size(); ++i) {
463 if (reinsert[i]->isLeaf()) {
466 for (
int j = 0; j < leaf->
childCount(); ++j) {
475 for (
int j = 0; j < node->
childCount(); ++j) {
489 m_root->intersects(
rect, found);
490 return found.values();
497 m_root->contains(point, found);
498 return found.values();
505 m_root->contained(
rect, found);
506 return found.values();
522 m_root->values(found);
523 return found.values();
526#ifdef CALLIGRA_RTREE_DEBUG
539 m_root->debug(prefix);
550 n1 = createLeafNode(m_capacity + 1, node->
level(), node->
parent());
551 n2 = createLeafNode(m_capacity + 1, node->
level(), node->
parent());
553 n1 = createNonLeafNode(m_capacity + 1, node->
level(), node->
parent());
554 n2 = createNonLeafNode(m_capacity + 1, node->
level(), node->
parent());
561 QPair<int, int> seeds(pickSeeds(node));
563 n1->
move(node, seeds.first);
564 n2->
move(node, seeds.second);
566 marker[seeds.first] =
true;
567 marker[seeds.second] =
true;
571 int remaining = m_capacity + 1 - 2;
573 while (remaining > 0) {
574 if (m_minimum - n1->
childCount() == remaining) {
575 for (
int i = 0; i < m_capacity + 1; ++i) {
581 }
else if (m_minimum - n2->
childCount() == remaining) {
582 for (
int i = 0; i < m_capacity + 1; ++i) {
589 QPair<int, int> next(pickNext(node, marker, n1, n2));
591 if (next.first == 0) {
592 n1->
move(node, next.second);
594 n2->
move(node, next.second);
612 return qMakePair(node, n2);
621 for (
int i = 0; i < m_capacity + 1; ++i) {
622 for (
int j = i+1; j < m_capacity + 1; ++j) {
627 qreal area = comp.width() * comp.height() - bb1.width() * bb1.height() - bb2.width() * bb2.height();
637 return qMakePair(
s1,
s2);
647 for (
int i = 0; i < m_capacity + 1; ++i) {
648 if (marker[i] ==
false) {
653 qreal diff = qAbs(d1 - d2);
659 if (qAbs(d1) > qAbs(d2)) {
668 marker[select] =
true;
669 return qMakePair(group, select);
679 NonLeafNode * newRoot = createNonLeafNode(m_capacity + 1, node1->
level() + 1, 0);
688 qFatal(
"KoRTree::adjustTree: no parent node found!");
693 parent->updateBoundingBox();
698 adjustTree(parent, 0);
700 if (parent->childCount() < m_capacity) {
703 adjustTree(parent, 0);
707 QPair<Node *, Node *> newNodes = splitNode(parent);
708 adjustTree(newNodes.first, newNodes.second);
724 parent->remove(node->
place());
725 reinsert.push_back(node);
737 parent->updateBoundingBox();
739 condenseTree(parent, reinsert);
754 qFatal(
"KoRTree::condenseTree cast to NonLeafNode failed");
761#ifdef CALLIGRA_RTREE_DEBUG
778 , m_childBoundingBox(capacity)
781#ifdef CALLIGRA_RTREE_DEBUG
782 , m_nodeId(nodeIdCnt++)
791 for (
int i = index + 1; i < m_counter; ++i) {
792 m_childBoundingBox[i-1] = m_childBoundingBox[i];
801 m_boundingBox = QRectF();
802 for (
int i = 0; i < m_counter; ++i) {
803 m_boundingBox = m_boundingBox.united(m_childBoundingBox[i]);
811 m_boundingBox = QRectF();
814#ifdef CALLIGRA_RTREE_DEBUG
819 if (level < levelColorSize) {
820 c = levelColor[level];
826 QRectF bbdraw(this->m_boundingBox);
827 bbdraw.adjust(level * 2, level * 2, -level * 2, -level * 2);
834 :
Node(capacity, level, parent)
844 for (
int i = 0; i < this->m_counter; ++i) {
852 m_childs[this->m_counter] = data;
855 this->m_childBoundingBox[this->m_counter] = bb;
856 this->m_boundingBox = this->m_boundingBox.united(bb);
864 for (
int i = index + 1; i < this->m_counter; ++i) {
865 m_childs[i-1] = m_childs[i];
866 m_childs[i-1]->setPlace(i - 1);
885 return getLeastEnlargement(bb)->
chooseLeaf(bb);
891 if (this->m_level > level) {
892 return getLeastEnlargement(bb)->
chooseNode(bb, level);
902 for (
int i = 0; i < this->m_counter; ++i) {
912 for (
int i = 0; i < this->m_counter; ++i) {
913 if (this->m_childBoundingBox[i].
contains(point)) {
914 m_childs[i]->contains(point, result);
922 for (
int i = 0; i < this->m_counter; ++i) {
924 m_childs[i]->contained(
rect, result);
932 for (
int i = 0; i < this->m_counter; ++i) {
933 m_childs[i]->keys(result);
940 for (
int i = 0; i < this->m_counter; ++i) {
941 m_childs[i]->values(result);
948 return m_childs[index];
955 QVarLengthArray<qreal> area(this->m_counter);
956 for (
int i = 0; i < this->m_counter; ++i) {
957 QSizeF big(this->m_childBoundingBox[i].united(bb).size());
958 area[i] = big.width() * big.height() - this->m_childBoundingBox[i].width() * this->m_childBoundingBox[i].height();
962 qreal minArea = area[minIndex];
965 for (
int i = 1; i < this->m_counter; ++i) {
966 if (area[i] < minArea) {
973 return m_childs[minIndex];
976#ifdef CALLIGRA_RTREE_DEBUG
980 for (
int i = 0; i < this->m_counter; ++i) {
981 qDebug(
"%s %d %d", qPrintable(line), this->nodeId(), i);
982 m_childs[i]->debug(line +
" ");
989 this->paintRect(
p, level);
990 for (
int i = 0; i < this->m_counter; ++i) {
991 m_childs[i]->paint(
p, level + 1);
1000template <
typename T>
1002 :
Node(capacity, level, parent)
1004 , m_dataIds(capacity)
1009template <
typename T>
1015template <
typename T>
1018 m_data[this->m_counter] = data;
1019 m_dataIds[this->m_counter] = id;
1020 this->m_childBoundingBox[this->m_counter] = bb;
1021 this->m_boundingBox = this->m_boundingBox.united(bb);
1025template <
typename T>
1028 for (
int i = index + 1; i < this->m_counter; ++i) {
1029 m_data[i-1] = m_data[i];
1030 m_dataIds[i-1] = m_dataIds[i];
1035template <
typename T>
1038 int old_counter = this->m_counter;
1039 for (
int i = 0; i < this->m_counter; ++i) {
1040 if (m_data[i] == data) {
1046 if (old_counter == this->m_counter) {
1047 qWarning() <<
"LeafNode::remove( const T&data) data not found";
1051template <
typename T>
1063template <
typename T>
1070template <
typename T>
1075 qFatal(
"LeafNode::chooseNode called. This should not happen!");
1079template <
typename T>
1082 for (
int i = 0; i < this->m_counter; ++i) {
1084 result.insert(m_dataIds[i], m_data[i]);
1089template <
typename T>
1092 for (
int i = 0; i < this->m_counter; ++i) {
1093 if (this->m_childBoundingBox[i].
contains(point)) {
1094 result.insert(m_dataIds[i], m_data[i]);
1099template <
typename T>
1102 for (
int i = 0; i < this->m_counter; ++i) {
1103 if (
rect.contains(this->m_childBoundingBox[i])) {
1104 result.insert(m_dataIds[i], m_data[i]);
1109template <
typename T>
1112 for (
int i = 0; i < this->m_counter; ++i) {
1113 result.push_back(this->m_childBoundingBox[i]);
1117template <
typename T>
1120 for (
int i = 0; i < this->m_counter; ++i) {
1121 result.insert(m_dataIds[i], m_data[i]);
1125template <
typename T>
1128 return m_data[ index ];
1131template <
typename T>
1134 return m_dataIds[ index ];
1137#ifdef CALLIGRA_RTREE_DEBUG
1138template <
typename T>
1141 for (
int i = 0; i < this->m_counter; ++i) {
1142 qDebug(
"%s %d %d %p", qPrintable(line), this->nodeId(), i, &(m_data[i]));
1143 debugFlake << this->m_childBoundingBox[i].toRect();
1147template <
typename T>
1150 if (this->m_counter) {
1151 this->paintRect(
p, level);
void values(QMap< int, T > &result) const override
virtual void insert(const QRectF &bb, const T &data, int id)
void contained(const QRectF &point, QMap< int, T > &result) const override
void intersects(const QRectF &rect, QMap< int, T > &result) const override
virtual int getDataId(int index) const
bool isLeaf() const override
LeafNode * chooseLeaf(const QRectF &bb) override
void keys(QList< QRectF > &result) const override
virtual const T & getData(int index) const
void move(Node *node, int index) override
void remove(int index) override
LeafNode(int capacity, int level, Node *parent)
NonLeafNode * chooseNode(const QRectF &bb, int level) override
void contains(const QPointF &point, QMap< int, T > &result) const override
virtual const QRectF & childBoundingBox(int index) const
virtual void keys(QList< QRectF > &result) const =0
virtual void updateBoundingBox()
virtual bool isLeaf() const
virtual bool isRoot() const
virtual int place() const
virtual void intersects(const QRectF &rect, QMap< int, T > &result) const =0
virtual const QRectF & boundingBox() const
virtual void contains(const QPointF &point, QMap< int, T > &result) const =0
virtual void setPlace(int place)
Node(int capacity, int level, Node *parent)
virtual int childCount() const
virtual void contained(const QRectF &point, QMap< int, T > &result) const =0
virtual NonLeafNode * chooseNode(const QRectF &bb, int level)=0
virtual void setParent(Node *parent)
virtual LeafNode * chooseLeaf(const QRectF &bb)=0
virtual void move(Node *node, int index)=0
virtual int level() const
virtual Node * parent() const
virtual void values(QMap< int, T > &result) const =0
virtual void setChildBoundingBox(int index, const QRectF &rect)
QVector< QRectF > m_childBoundingBox
virtual void setLevel(int level)
virtual void remove(int index)
void contained(const QRectF &point, QMap< int, T > &result) const override
virtual void insert(const QRectF &bb, Node *data)
void remove(int index) override
void intersects(const QRectF &rect, QMap< int, T > &result) const override
NonLeafNode * chooseNode(const QRectF &bb, int level) override
void move(Node *node, int index) override
LeafNode * chooseLeaf(const QRectF &bb) override
NonLeafNode(int capacity, int level, Node *parent)
void values(QMap< int, T > &result) const override
void keys(QList< QRectF > &result) const override
virtual Node * getNode(int index) const
QVector< Node * > m_childs
virtual Node * getLeastEnlargement(const QRectF &bb) const
void contains(const QPointF &point, QMap< int, T > &result) const override
The KoRTree class is a template class that provides a R-tree.
virtual LeafNode * createLeafNode(int capacity, int level, Node *parent)
virtual void condenseTree(Node *node, QVector< Node * > &reinsert)
void remove(const T &data)
Remove a data item from the tree.
bool contains(const T &data)
Show if a shape is a part of the tree.
QPair< int, int > pickSeeds(Node *node)
QList< QRectF > keys() const
Find all data rectangles The order is NOT guaranteed to be the same as that used by values().
void insertHelper(const QRectF &bb, const T &data, int id)
QList< T > contains(const QPointF &point) const
Find all data item which contain the point The items are sorted by insertion time in ascending order.
virtual ~KoRTree()
Destructor.
KoRTree(int capacity, int minimum)
Constructor.
virtual void insert(const QRectF &bb, const T &data)
Insert data item into the tree.
QList< T > contained(const QRectF &point) const
Find all data item which contain the point The items are sorted by insertion time in ascending order.
virtual QList< T > intersects(const QRectF &rect) const
Find all data items which intersects rect The items are sorted by insertion time in ascending order.
QList< T > values() const
Find all data items The order is NOT guaranteed to be the same as that used by keys().
QPair< int, int > pickNext(Node *node, QVector< bool > &marker, Node *group1, Node *group2)
virtual NonLeafNode * createNonLeafNode(int capacity, int level, Node *parent)
virtual void adjustTree(Node *node1, Node *node2)
QPair< Node *, Node * > splitNode(Node *node)
QMap< T, LeafNode * > m_leafMap
bool remove()
remove removes this node from its parent image.
#define KIS_SAFE_ASSERT_RECOVER(cond)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)