QGIS API Documentation
4.3.0-Master (16eddb2670e)
Toggle main menu visibility
Loading...
Searching...
No Matches
src
core
qgsgenericspatialindex.h
Go to the documentation of this file.
1
/***************************************************************************
2
qgsgenericspatialindex.h
3
------------------------
4
Date : December 2019
5
Copyright : (C) 2019 by Nyall Dawson
6
Email : nyall dot dawson at gmail dot com
7
***************************************************************************
8
* *
9
* This program is free software; you can redistribute it and/or modify *
10
* it under the terms of the GNU General Public License as published by *
11
* the Free Software Foundation; either version 2 of the License, or *
12
* (at your option) any later version. *
13
* *
14
***************************************************************************/
15
16
#ifndef QGSGENERICSPATIALINDEX_H
17
#define QGSGENERICSPATIALINDEX_H
18
19
#include <memory>
20
21
#include "qgis_core.h"
22
#include "
qgslogger.h
"
23
#include "
qgsspatialindexutils.h
"
24
25
#include <QMutex>
26
#include <QString>
27
28
#define SIP_NO_FILE
29
30
using namespace
Qt::StringLiterals;
31
32
33
#include <functional>
34
#include <spatialindex/SpatialIndex.h>
35
36
class
QgsRectangle
;
37
47
template
<
typename
T>
class
QgsGenericSpatialIndex
48
{
49
public
:
53
QgsGenericSpatialIndex
()
54
{
55
mStorageManager.reset( SpatialIndex::StorageManager::createNewMemoryStorageManager() );
56
mRTree = createSpatialIndex( *mStorageManager );
57
}
58
65
bool
insert
( T *data,
const
QgsRectangle
&bounds )
66
{
67
const
SpatialIndex::Region r(
QgsSpatialIndexUtils::rectangleToRegion
( bounds ) );
68
69
const
QMutexLocker locker( &mMutex );
70
71
const
qint64
id
= mNextId++;
72
mIdToData.insert(
id
, data );
73
mDataToId.insert( data,
id
);
74
try
75
{
76
mRTree->insertData( 0,
nullptr
, r,
static_cast<
qint64
>
(
id
) );
77
return
true
;
78
}
79
catch
( Tools::Exception &e )
80
{
81
Q_UNUSED( e )
82
QgsDebugError
( u
"Tools::Exception caught when inserting data to QgsGenericSpatialIndex: %1"
_s.arg( e.what().c_str() ) );
83
}
84
catch
(
const
std::exception &e )
85
{
86
Q_UNUSED( e )
87
QgsDebugError
( u
"std::exception caught when inserting data to QgsGenericSpatialIndex: %1"
_s.arg( e.what() ) );
88
}
89
catch
( ... )
90
{
91
QgsDebugError
( u
"unknown spatial index exception caught when inserting data to QgsGenericSpatialIndex"
_s );
92
}
93
94
return
false
;
95
}
96
103
bool
remove
( T *data,
const
QgsRectangle
&bounds )
104
{
105
const
SpatialIndex::Region r =
QgsSpatialIndexUtils::rectangleToRegion
( bounds );
106
107
const
QMutexLocker locker( &mMutex );
108
109
const
qint64
id
= mDataToId.value( data, 0 );
110
if
(
id
== 0 )
111
return
false
;
112
113
// TODO: handle exceptions
114
const
bool
res = mRTree->deleteData( r,
id
);
115
mDataToId.remove( data );
116
mIdToData.remove(
id
);
117
return
res;
118
}
119
125
bool
intersects
(
const
QgsRectangle
&bounds,
const
std::function<
bool
( T *data )> &callback )
const
126
{
127
GenericIndexVisitor<T> visitor( callback, mIdToData );
128
const
SpatialIndex::Region r =
QgsSpatialIndexUtils::rectangleToRegion
( bounds );
129
130
const
QMutexLocker locker( &mMutex );
131
try
132
{
133
mRTree->intersectsWithQuery( r, visitor );
134
}
135
catch
( Tools::Exception &e )
136
{
137
Q_UNUSED( e )
138
QgsDebugError
( u
"Tools::Exception caught in QgsGenericSpatialIndex::intersects: %1"
_s.arg( e.what().c_str() ) );
139
}
140
catch
(
const
std::exception &e )
141
{
142
Q_UNUSED( e )
143
QgsDebugError
( u
"std::exception caught in QgsGenericSpatialIndex::intersects: %1"
_s.arg( e.what() ) );
144
}
145
catch
( ... )
146
{
147
QgsDebugError
( u
"unknown spatial index exception caught in QgsGenericSpatialIndex::intersects"
_s );
148
}
149
150
return
true
;
151
}
152
156
bool
isEmpty
()
const
157
{
158
const
QMutexLocker locker( &mMutex );
159
return
mIdToData.isEmpty();
160
}
161
162
private
:
163
std::unique_ptr< SpatialIndex::ISpatialIndex > createSpatialIndex( SpatialIndex::IStorageManager &storageManager )
164
{
165
// R-Tree parameters
166
constexpr
double
fillFactor = 0.7;
167
constexpr
unsigned
long
indexCapacity = 10;
168
constexpr
unsigned
long
leafCapacity = 10;
169
constexpr
unsigned
long
dimension = 2;
170
constexpr
SpatialIndex::RTree::RTreeVariant variant = SpatialIndex::RTree::RV_RSTAR;
171
172
// create R-tree
173
SpatialIndex::id_type indexId;
174
return
std::unique_ptr< SpatialIndex::ISpatialIndex >( SpatialIndex::RTree::createNewRTree( storageManager, fillFactor, indexCapacity, leafCapacity, dimension, variant, indexId ) );
175
}
176
177
std::unique_ptr< SpatialIndex::IStorageManager > mStorageManager;
178
std::unique_ptr< SpatialIndex::ISpatialIndex > mRTree;
179
180
mutable
QMutex mMutex;
181
182
qint64 mNextId = 1;
183
QHash< qint64, T * > mIdToData;
184
QHash< T *, qint64 > mDataToId;
185
186
template
<
typename
TT>
class
GenericIndexVisitor :
public
SpatialIndex::IVisitor
187
{
188
public
:
189
explicit
GenericIndexVisitor(
const
std::function<
bool
( TT *data )> &callback,
const
QHash< qint64, TT * > &data )
190
: mCallback( callback )
191
, mData( data )
192
{}
193
194
void
visitNode(
const
SpatialIndex::INode &n )
override
{ Q_UNUSED( n ) }
195
196
void
visitData(
const
SpatialIndex::IData &d )
override
197
{
198
const
qint64
id
= d.getIdentifier();
199
T *data = mData.value(
id
);
200
mCallback( data );
201
}
202
203
void
visitData( std::vector<const SpatialIndex::IData *> &v )
override
{ Q_UNUSED( v ) }
204
205
private
:
206
const
std::function< bool( TT *data )> &mCallback;
207
QHash< qint64, TT * > mData;
208
};
209
};
210
211
#endif
// QGSGENERICSPATIALINDEX_H
QgsGenericSpatialIndex::intersects
bool intersects(const QgsRectangle &bounds, const std::function< bool(T *data)> &callback) const
Performs an intersection check against the index, for data intersecting the specified bounds.
Definition
qgsgenericspatialindex.h:125
QgsGenericSpatialIndex::QgsGenericSpatialIndex
QgsGenericSpatialIndex()
Constructor for QgsGenericSpatialIndex.
Definition
qgsgenericspatialindex.h:53
QgsGenericSpatialIndex::isEmpty
bool isEmpty() const
Returns true if the index contains no items.
Definition
qgsgenericspatialindex.h:156
QgsGenericSpatialIndex::insert
bool insert(T *data, const QgsRectangle &bounds)
Inserts new data into the spatial index, with the specified bounds.
Definition
qgsgenericspatialindex.h:65
QgsGenericSpatialIndex::remove
bool remove(T *data, const QgsRectangle &bounds)
Removes existing data from the spatial index, with the specified bounds.
Definition
qgsgenericspatialindex.h:103
QgsRectangle
A rectangle specified with double values.
Definition
qgsrectangle.h:47
QgsSpatialIndexUtils::rectangleToRegion
static SpatialIndex::Region rectangleToRegion(const QgsRectangle &rectangle)
Converts a QGIS rectangle to a SpatialIndex region.
Definition
qgsspatialindexutils.cpp:22
qgslogger.h
QgsDebugError
#define QgsDebugError(str)
Definition
qgslogger.h:71
qgsspatialindexutils.h
Generated on
for QGIS API Documentation by
1.17.0