25
25
using namespace SpatialIndex ;
26
26
27
27
28
+
28
29
// custom visitor that adds found features to list
29
30
class QgisVisitor : public SpatialIndex ::IVisitor
30
31
{
@@ -47,38 +48,102 @@ class QgisVisitor : public SpatialIndex::IVisitor
47
48
QList<QgsFeatureId>& mList ;
48
49
};
49
50
51
+ class QgsSpatialIndexCopyVisitor : public SpatialIndex ::IVisitor
52
+ {
53
+ public:
54
+ QgsSpatialIndexCopyVisitor ( SpatialIndex::ISpatialIndex* newIndex )
55
+ : mNewIndex ( newIndex ) {}
56
+
57
+ void visitNode ( const INode& n )
58
+ { Q_UNUSED ( n ); }
59
+
60
+ void visitData ( const IData& d )
61
+ {
62
+ SpatialIndex::IShape* shape;
63
+ d.getShape ( &shape );
64
+ mNewIndex ->insertData ( 0 , 0 , *shape, d.getIdentifier () );
65
+ delete shape;
66
+ }
67
+
68
+ void visitData ( std::vector<const IData*>& v )
69
+ { Q_UNUSED ( v ); }
70
+
71
+ private:
72
+ SpatialIndex::ISpatialIndex* mNewIndex ;
73
+ };
74
+
75
+
76
+ /* * Data of spatial index that may be implicitly shared */
77
+ class QgsSpatialIndexData : public QSharedData
78
+ {
79
+ public:
80
+ QgsSpatialIndexData ()
81
+ {
82
+ initTree ();
83
+ }
84
+
85
+ QgsSpatialIndexData ( const QgsSpatialIndexData& other )
86
+ : QSharedData( other )
87
+ {
88
+ initTree ();
89
+
90
+ // copy R-tree data one by one (is there a faster way??)
91
+ double low[] = { DBL_MIN, DBL_MIN };
92
+ double high[] = { DBL_MAX, DBL_MAX };
93
+ SpatialIndex::Region query ( low, high, 2 );
94
+ QgsSpatialIndexCopyVisitor visitor ( mRTree );
95
+ other.mRTree ->intersectsWithQuery ( query, visitor );
96
+ }
97
+
98
+ ~QgsSpatialIndexData ()
99
+ {
100
+ delete mRTree ;
101
+ delete mStorage ;
102
+ }
103
+
104
+ void initTree ()
105
+ {
106
+ // for now only memory manager
107
+ mStorage = StorageManager::createNewMemoryStorageManager ();
108
+
109
+ // R-Tree parameters
110
+ double fillFactor = 0.7 ;
111
+ unsigned long indexCapacity = 10 ;
112
+ unsigned long leafCapacity = 10 ;
113
+ unsigned long dimension = 2 ;
114
+ RTree::RTreeVariant variant = RTree::RV_RSTAR;
115
+
116
+ // create R-tree
117
+ SpatialIndex::id_type indexId;
118
+ mRTree = RTree::createNewRTree ( *mStorage , fillFactor, indexCapacity,
119
+ leafCapacity, dimension, variant, indexId );
120
+ }
121
+
122
+ /* * storage manager */
123
+ SpatialIndex::IStorageManager* mStorage ;
124
+
125
+ /* * R-tree containing spatial index */
126
+ SpatialIndex::ISpatialIndex* mRTree ;
127
+ };
128
+
129
+ // -------------------------------------------------------------------------
130
+
50
131
51
132
QgsSpatialIndex::QgsSpatialIndex ()
52
133
{
53
- // for now only memory manager
54
- mStorageManager = StorageManager::createNewMemoryStorageManager ();
55
-
56
- // create buffer
57
-
58
- unsigned int capacity = 10 ;
59
- bool writeThrough = false ;
60
- mStorage = StorageManager::createNewRandomEvictionsBuffer ( *mStorageManager , capacity, writeThrough );
61
-
62
- // R-Tree parameters
63
- double fillFactor = 0.7 ;
64
- unsigned long indexCapacity = 10 ;
65
- unsigned long leafCapacity = 10 ;
66
- unsigned long dimension = 2 ;
67
- RTree::RTreeVariant variant = RTree::RV_RSTAR;
68
-
69
- // create R-tree
70
- SpatialIndex::id_type indexId;
71
- mRTree = RTree::createNewRTree ( *mStorage , fillFactor, indexCapacity,
72
- leafCapacity, dimension, variant, indexId );
134
+ d = new QgsSpatialIndexData;
135
+ }
136
+
137
+ QgsSpatialIndex::QgsSpatialIndex ( const QgsSpatialIndex& other )
138
+ : d( other.d )
139
+ {
73
140
}
74
141
75
142
QgsSpatialIndex:: ~QgsSpatialIndex ()
76
143
{
77
- delete mRTree ;
78
- delete mStorage ;
79
- delete mStorageManager ;
80
144
}
81
145
146
+
82
147
Region QgsSpatialIndex::rectToRegion ( QgsRectangle rect )
83
148
{
84
149
double pt1[2 ], pt2[2 ];
@@ -89,7 +154,7 @@ Region QgsSpatialIndex::rectToRegion( QgsRectangle rect )
89
154
return Region ( pt1, pt2, 2 );
90
155
}
91
156
92
- bool QgsSpatialIndex::featureInfo ( QgsFeature& f, SpatialIndex::Region& r, QgsFeatureId &id )
157
+ bool QgsSpatialIndex::featureInfo ( const QgsFeature& f, SpatialIndex::Region& r, QgsFeatureId &id )
93
158
{
94
159
QgsGeometry *g = f.geometry ();
95
160
if ( !g )
@@ -100,7 +165,8 @@ bool QgsSpatialIndex::featureInfo( QgsFeature& f, SpatialIndex::Region& r, QgsFe
100
165
return true ;
101
166
}
102
167
103
- bool QgsSpatialIndex::insertFeature ( QgsFeature& f )
168
+
169
+ bool QgsSpatialIndex::insertFeature ( const QgsFeature& f )
104
170
{
105
171
Region r;
106
172
QgsFeatureId id;
@@ -110,7 +176,7 @@ bool QgsSpatialIndex::insertFeature( QgsFeature& f )
110
176
// TODO: handle possible exceptions correctly
111
177
try
112
178
{
113
- mRTree ->insertData ( 0 , 0 , r, FID_TO_NUMBER ( id ) );
179
+ d-> mRTree ->insertData ( 0 , 0 , r, FID_TO_NUMBER ( id ) );
114
180
return true ;
115
181
}
116
182
catch ( Tools::Exception &e )
@@ -131,30 +197,30 @@ bool QgsSpatialIndex::insertFeature( QgsFeature& f )
131
197
return false ;
132
198
}
133
199
134
- bool QgsSpatialIndex::deleteFeature ( QgsFeature& f )
200
+ bool QgsSpatialIndex::deleteFeature ( const QgsFeature& f )
135
201
{
136
202
Region r;
137
203
QgsFeatureId id;
138
204
if ( !featureInfo ( f, r, id ) )
139
205
return false ;
140
206
141
207
// TODO: handle exceptions
142
- return mRTree ->deleteData ( r, FID_TO_NUMBER ( id ) );
208
+ return d-> mRTree ->deleteData ( r, FID_TO_NUMBER ( id ) );
143
209
}
144
210
145
- QList<QgsFeatureId> QgsSpatialIndex::intersects ( QgsRectangle rect )
211
+ QList<QgsFeatureId> QgsSpatialIndex::intersects ( QgsRectangle rect ) const
146
212
{
147
213
QList<QgsFeatureId> list;
148
214
QgisVisitor visitor ( list );
149
215
150
216
Region r = rectToRegion ( rect );
151
217
152
- mRTree ->intersectsWithQuery ( r, visitor );
218
+ d-> mRTree ->intersectsWithQuery ( r, visitor );
153
219
154
220
return list;
155
221
}
156
222
157
- QList<QgsFeatureId> QgsSpatialIndex::nearestNeighbor ( QgsPoint point, int neighbors )
223
+ QList<QgsFeatureId> QgsSpatialIndex::nearestNeighbor ( QgsPoint point, int neighbors ) const
158
224
{
159
225
QList<QgsFeatureId> list;
160
226
QgisVisitor visitor ( list );
@@ -164,7 +230,12 @@ QList<QgsFeatureId> QgsSpatialIndex::nearestNeighbor( QgsPoint point, int neighb
164
230
pt[1 ] = point.y ();
165
231
Point p ( pt, 2 );
166
232
167
- mRTree ->nearestNeighborQuery ( neighbors, p, visitor );
233
+ d-> mRTree ->nearestNeighborQuery ( neighbors, p, visitor );
168
234
169
235
return list;
170
236
}
237
+
238
+ int QgsSpatialIndex::refs () const
239
+ {
240
+ return d->ref ;
241
+ }
0 commit comments