2525using namespace SpatialIndex ;
2626
2727
28+
2829// custom visitor that adds found features to list
2930class QgisVisitor : public SpatialIndex ::IVisitor
3031{
@@ -47,38 +48,102 @@ class QgisVisitor : public SpatialIndex::IVisitor
4748 QList<QgsFeatureId>& mList ;
4849};
4950
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+
50131
51132QgsSpatialIndex::QgsSpatialIndex ()
52133{
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+ {
73140}
74141
75142QgsSpatialIndex:: ~QgsSpatialIndex ()
76143{
77- delete mRTree ;
78- delete mStorage ;
79- delete mStorageManager ;
80144}
81145
146+
82147Region QgsSpatialIndex::rectToRegion ( QgsRectangle rect )
83148{
84149 double pt1[2 ], pt2[2 ];
@@ -89,7 +154,7 @@ Region QgsSpatialIndex::rectToRegion( QgsRectangle rect )
89154 return Region ( pt1, pt2, 2 );
90155}
91156
92- bool QgsSpatialIndex::featureInfo ( QgsFeature& f, SpatialIndex::Region& r, QgsFeatureId &id )
157+ bool QgsSpatialIndex::featureInfo ( const QgsFeature& f, SpatialIndex::Region& r, QgsFeatureId &id )
93158{
94159 QgsGeometry *g = f.geometry ();
95160 if ( !g )
@@ -100,7 +165,8 @@ bool QgsSpatialIndex::featureInfo( QgsFeature& f, SpatialIndex::Region& r, QgsFe
100165 return true ;
101166}
102167
103- bool QgsSpatialIndex::insertFeature ( QgsFeature& f )
168+
169+ bool QgsSpatialIndex::insertFeature ( const QgsFeature& f )
104170{
105171 Region r;
106172 QgsFeatureId id;
@@ -110,7 +176,7 @@ bool QgsSpatialIndex::insertFeature( QgsFeature& f )
110176 // TODO: handle possible exceptions correctly
111177 try
112178 {
113- mRTree ->insertData ( 0 , 0 , r, FID_TO_NUMBER ( id ) );
179+ d-> mRTree ->insertData ( 0 , 0 , r, FID_TO_NUMBER ( id ) );
114180 return true ;
115181 }
116182 catch ( Tools::Exception &e )
@@ -131,30 +197,30 @@ bool QgsSpatialIndex::insertFeature( QgsFeature& f )
131197 return false ;
132198}
133199
134- bool QgsSpatialIndex::deleteFeature ( QgsFeature& f )
200+ bool QgsSpatialIndex::deleteFeature ( const QgsFeature& f )
135201{
136202 Region r;
137203 QgsFeatureId id;
138204 if ( !featureInfo ( f, r, id ) )
139205 return false ;
140206
141207 // TODO: handle exceptions
142- return mRTree ->deleteData ( r, FID_TO_NUMBER ( id ) );
208+ return d-> mRTree ->deleteData ( r, FID_TO_NUMBER ( id ) );
143209}
144210
145- QList<QgsFeatureId> QgsSpatialIndex::intersects ( QgsRectangle rect )
211+ QList<QgsFeatureId> QgsSpatialIndex::intersects ( QgsRectangle rect ) const
146212{
147213 QList<QgsFeatureId> list;
148214 QgisVisitor visitor ( list );
149215
150216 Region r = rectToRegion ( rect );
151217
152- mRTree ->intersectsWithQuery ( r, visitor );
218+ d-> mRTree ->intersectsWithQuery ( r, visitor );
153219
154220 return list;
155221}
156222
157- QList<QgsFeatureId> QgsSpatialIndex::nearestNeighbor ( QgsPoint point, int neighbors )
223+ QList<QgsFeatureId> QgsSpatialIndex::nearestNeighbor ( QgsPoint point, int neighbors ) const
158224{
159225 QList<QgsFeatureId> list;
160226 QgisVisitor visitor ( list );
@@ -164,7 +230,12 @@ QList<QgsFeatureId> QgsSpatialIndex::nearestNeighbor( QgsPoint point, int neighb
164230 pt[1 ] = point.y ();
165231 Point p ( pt, 2 );
166232
167- mRTree ->nearestNeighborQuery ( neighbors, p, visitor );
233+ d-> mRTree ->nearestNeighborQuery ( neighbors, p, visitor );
168234
169235 return list;
170236}
237+
238+ int QgsSpatialIndex::refs () const
239+ {
240+ return d->ref ;
241+ }
0 commit comments