QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsspatialindex.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsspatialindex.cpp - wrapper class for spatial index library
3  ----------------------
4  begin : December 2006
5  copyright : (C) 2006 by Martin Dobias
6  email : wonder.sk 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 #include "qgsspatialindex.h"
17 
18 #include "qgsgeometry.h"
19 #include "qgsfeature.h"
20 #include "qgsrectangle.h"
21 #include "qgslogger.h"
22 
23 #include "SpatialIndex.h"
24 
25 using namespace SpatialIndex;
26 
27 
28 // custom visitor that adds found features to list
29 class QgisVisitor : public SpatialIndex::IVisitor
30 {
31  public:
32  QgisVisitor( QList<QgsFeatureId> & list )
33  : mList( list ) {}
34 
35  void visitNode( const INode& n )
36  { Q_UNUSED( n ); }
37 
38  void visitData( const IData& d )
39  {
40  mList.append( d.getIdentifier() );
41  }
42 
43  void visitData( std::vector<const IData*>& v )
44  { Q_UNUSED( v ); }
45 
46  private:
47  QList<QgsFeatureId>& mList;
48 };
49 
50 
52 {
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 );
73 }
74 
76 {
77  delete mRTree;
78  delete mStorage;
79  delete mStorageManager;
80 }
81 
83 {
84  double pt1[2], pt2[2];
85  pt1[0] = rect.xMinimum();
86  pt1[1] = rect.yMinimum();
87  pt2[0] = rect.xMaximum();
88  pt2[1] = rect.yMaximum();
89  return Region( pt1, pt2, 2 );
90 }
91 
92 bool QgsSpatialIndex::featureInfo( QgsFeature& f, SpatialIndex::Region& r, QgsFeatureId &id )
93 {
94  QgsGeometry *g = f.geometry();
95  if ( !g )
96  return false;
97 
98  id = f.id();
99  r = rectToRegion( g->boundingBox() );
100  return true;
101 }
102 
104 {
105  Region r;
106  QgsFeatureId id;
107  if ( !featureInfo( f, r, id ) )
108  return false;
109 
110  // TODO: handle possible exceptions correctly
111  try
112  {
113  mRTree->insertData( 0, 0, r, FID_TO_NUMBER( id ) );
114  return true;
115  }
116  catch ( Tools::Exception &e )
117  {
118  Q_UNUSED( e );
119  QgsDebugMsg( QString( "Tools::Exception caught: " ).arg( e.what().c_str() ) );
120  }
121  catch ( const std::exception &e )
122  {
123  Q_UNUSED( e );
124  QgsDebugMsg( QString( "std::exception caught: " ).arg( e.what() ) );
125  }
126  catch ( ... )
127  {
128  QgsDebugMsg( "unknown spatial index exception caught" );
129  }
130 
131  return false;
132 }
133 
135 {
136  Region r;
137  QgsFeatureId id;
138  if ( !featureInfo( f, r, id ) )
139  return false;
140 
141  // TODO: handle exceptions
142  return mRTree->deleteData( r, FID_TO_NUMBER( id ) );
143 }
144 
145 QList<QgsFeatureId> QgsSpatialIndex::intersects( QgsRectangle rect )
146 {
147  QList<QgsFeatureId> list;
148  QgisVisitor visitor( list );
149 
150  Region r = rectToRegion( rect );
151 
152  mRTree->intersectsWithQuery( r, visitor );
153 
154  return list;
155 }
156 
157 QList<QgsFeatureId> QgsSpatialIndex::nearestNeighbor( QgsPoint point, int neighbors )
158 {
159  QList<QgsFeatureId> list;
160  QgisVisitor visitor( list );
161 
162  double pt[2];
163  pt[0] = point.x();
164  pt[1] = point.y();
165  Point p( pt, 2 );
166 
167  mRTree->nearestNeighborQuery( neighbors, p, visitor );
168 
169  return list;
170 }