Quantum GIS API Documentation
1.8
|
00001 /*************************************************************************** 00002 qgsspatialindex.cpp - wrapper class for spatial index library 00003 ---------------------- 00004 begin : December 2006 00005 copyright : (C) 2006 by Martin Dobias 00006 email : wonder.sk at gmail dot com 00007 *************************************************************************** 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 ***************************************************************************/ 00015 00016 #include "qgsspatialindex.h" 00017 00018 #include "qgsgeometry.h" 00019 #include "qgsfeature.h" 00020 #include "qgsrectangle.h" 00021 #include "qgslogger.h" 00022 00023 #include "SpatialIndex.h" 00024 00025 using namespace SpatialIndex; 00026 00027 00028 // custom visitor that adds found features to list 00029 class QgisVisitor : public SpatialIndex::IVisitor 00030 { 00031 public: 00032 QgisVisitor( QList<QgsFeatureId> & list ) 00033 : mList( list ) {} 00034 00035 void visitNode( const INode& n ) 00036 { Q_UNUSED( n ); } 00037 00038 void visitData( const IData& d ) 00039 { 00040 mList.append( d.getIdentifier() ); 00041 } 00042 00043 void visitData( std::vector<const IData*>& v ) 00044 { Q_UNUSED( v ); } 00045 00046 private: 00047 QList<QgsFeatureId>& mList; 00048 }; 00049 00050 00051 QgsSpatialIndex::QgsSpatialIndex() 00052 { 00053 // for now only memory manager 00054 mStorageManager = StorageManager::createNewMemoryStorageManager(); 00055 00056 // create buffer 00057 00058 unsigned int capacity = 10; 00059 bool writeThrough = false; 00060 mStorage = StorageManager::createNewRandomEvictionsBuffer( *mStorageManager, capacity, writeThrough ); 00061 00062 // R-Tree parameters 00063 double fillFactor = 0.7; 00064 unsigned long indexCapacity = 10; 00065 unsigned long leafCapacity = 10; 00066 unsigned long dimension = 2; 00067 RTree::RTreeVariant variant = RTree::RV_RSTAR; 00068 00069 // create R-tree 00070 SpatialIndex::id_type indexId; 00071 mRTree = RTree::createNewRTree( *mStorage, fillFactor, indexCapacity, 00072 leafCapacity, dimension, variant, indexId ); 00073 } 00074 00075 QgsSpatialIndex:: ~QgsSpatialIndex() 00076 { 00077 delete mRTree; 00078 delete mStorage; 00079 delete mStorageManager; 00080 } 00081 00082 Region QgsSpatialIndex::rectToRegion( QgsRectangle rect ) 00083 { 00084 double pt1[2], pt2[2]; 00085 pt1[0] = rect.xMinimum(); 00086 pt1[1] = rect.yMinimum(); 00087 pt2[0] = rect.xMaximum(); 00088 pt2[1] = rect.yMaximum(); 00089 return Region( pt1, pt2, 2 ); 00090 } 00091 00092 bool QgsSpatialIndex::featureInfo( QgsFeature& f, Region& r, QgsFeatureId &id ) 00093 { 00094 QgsGeometry *g = f.geometry(); 00095 if ( !g ) 00096 return false; 00097 00098 id = f.id(); 00099 r = rectToRegion( g->boundingBox() ); 00100 return true; 00101 } 00102 00103 bool QgsSpatialIndex::insertFeature( QgsFeature& f ) 00104 { 00105 Region r; 00106 QgsFeatureId id; 00107 if ( !featureInfo( f, r, id ) ) 00108 return false; 00109 00110 // TODO: handle possible exceptions correctly 00111 try 00112 { 00113 mRTree->insertData( 0, 0, r, FID_TO_NUMBER( id ) ); 00114 } 00115 catch ( Tools::Exception &e ) 00116 { 00117 Q_UNUSED( e ); 00118 QgsDebugMsg( QString( "Tools::Exception caught: " ).arg( e.what().c_str() ) ); 00119 } 00120 catch ( const std::exception &e ) 00121 { 00122 Q_UNUSED( e ); 00123 QgsDebugMsg( QString( "std::exception caught: " ).arg( e.what() ) ); 00124 } 00125 catch ( ... ) 00126 { 00127 QgsDebugMsg( "unknown spatial index exception caught" ); 00128 } 00129 00130 return true; 00131 } 00132 00133 bool QgsSpatialIndex::deleteFeature( QgsFeature& f ) 00134 { 00135 Region r; 00136 QgsFeatureId id; 00137 if ( !featureInfo( f, r, id ) ) 00138 return false; 00139 00140 // TODO: handle exceptions 00141 return mRTree->deleteData( r, FID_TO_NUMBER( id ) ); 00142 } 00143 00144 QList<QgsFeatureId> QgsSpatialIndex::intersects( QgsRectangle rect ) 00145 { 00146 QList<QgsFeatureId> list; 00147 QgisVisitor visitor( list ); 00148 00149 Region r = rectToRegion( rect ); 00150 00151 mRTree->intersectsWithQuery( r, visitor ); 00152 00153 return list; 00154 } 00155 00156 QList<QgsFeatureId> QgsSpatialIndex::nearestNeighbor( QgsPoint point, int neighbors ) 00157 { 00158 QList<QgsFeatureId> list; 00159 QgisVisitor visitor( list ); 00160 00161 double pt[2]; 00162 pt[0] = point.x(); 00163 pt[1] = point.y(); 00164 Point p( pt, 2 ); 00165 00166 mRTree->nearestNeighborQuery( neighbors, p, visitor ); 00167 00168 return list; 00169 }