Quantum GIS API Documentation
1.7.4
|
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 /* $Id$ */ 00016 00017 #include "qgsspatialindex.h" 00018 00019 #include "qgsgeometry.h" 00020 #include "qgsfeature.h" 00021 #include "qgsrectangle.h" 00022 #include "qgslogger.h" 00023 00024 #include "SpatialIndex.h" 00025 00026 using namespace SpatialIndex; 00027 00028 00029 // custom visitor that adds found features to list 00030 class QgisVisitor : public SpatialIndex::IVisitor 00031 { 00032 public: 00033 QgisVisitor( QList<int> & list ) 00034 : mList( list ) {} 00035 00036 void visitNode( const INode& 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 00045 private: 00046 QList<int>& mList; 00047 }; 00048 00049 00050 QgsSpatialIndex::QgsSpatialIndex() 00051 { 00052 // for now only memory manager 00053 mStorageManager = StorageManager::createNewMemoryStorageManager(); 00054 00055 // create buffer 00056 00057 unsigned int capacity = 10; 00058 bool writeThrough = false; 00059 mStorage = StorageManager::createNewRandomEvictionsBuffer( *mStorageManager, capacity, writeThrough ); 00060 00061 // R-Tree parameters 00062 double fillFactor = 0.7; 00063 unsigned long indexCapacity = 10; 00064 unsigned long leafCapacity = 10; 00065 unsigned long dimension = 2; 00066 RTree::RTreeVariant variant = RTree::RV_RSTAR; 00067 00068 // create R-tree 00069 long indexId; 00070 mRTree = RTree::createNewRTree( *mStorage, fillFactor, indexCapacity, 00071 leafCapacity, dimension, variant, indexId ); 00072 } 00073 00074 QgsSpatialIndex:: ~QgsSpatialIndex() 00075 { 00076 delete mRTree; 00077 delete mStorage; 00078 delete mStorageManager; 00079 } 00080 00081 Tools::Geometry::Region QgsSpatialIndex::rectToRegion( QgsRectangle rect ) 00082 { 00083 double pt1[2], pt2[2]; 00084 pt1[0] = rect.xMinimum(); 00085 pt1[1] = rect.yMinimum(); 00086 pt2[0] = rect.xMaximum(); 00087 pt2[1] = rect.yMaximum(); 00088 return Tools::Geometry::Region( pt1, pt2, 2 ); 00089 } 00090 00091 bool QgsSpatialIndex::featureInfo( QgsFeature& f, Tools::Geometry::Region& r, long& id ) 00092 { 00093 QgsGeometry *g = f.geometry(); 00094 if ( !g ) 00095 return false; 00096 00097 id = f.id(); 00098 r = rectToRegion( g->boundingBox() ); 00099 return true; 00100 } 00101 00102 bool QgsSpatialIndex::insertFeature( QgsFeature& f ) 00103 { 00104 Tools::Geometry::Region r; 00105 long id; 00106 if ( !featureInfo( f, r, id ) ) 00107 return false; 00108 00109 // TODO: handle possible exceptions correctly 00110 try 00111 { 00112 mRTree->insertData( 0, 0, r, id ); 00113 } 00114 catch ( Tools::Exception &e ) 00115 { 00116 Q_UNUSED( e ); 00117 QgsDebugMsg( QString( "Tools::Exception caught: " ).arg( e.what().c_str() ) ); 00118 } 00119 catch ( const std::exception &e ) 00120 { 00121 Q_UNUSED( e ); 00122 QgsDebugMsg( QString( "std::exception caught: " ).arg( e.what() ) ); 00123 } 00124 catch ( ... ) 00125 { 00126 QgsDebugMsg( "unknown spatial index exception caught" ); 00127 } 00128 00129 return true; 00130 } 00131 00132 bool QgsSpatialIndex::deleteFeature( QgsFeature& f ) 00133 { 00134 Tools::Geometry::Region r; 00135 long id; 00136 if ( !featureInfo( f, r, id ) ) 00137 return false; 00138 00139 // TODO: handle exceptions 00140 return mRTree->deleteData( r, id ); 00141 } 00142 00143 QList<int> QgsSpatialIndex::intersects( QgsRectangle rect ) 00144 { 00145 QList<int> list; 00146 QgisVisitor visitor( list ); 00147 00148 Tools::Geometry::Region r = rectToRegion( rect ); 00149 00150 mRTree->intersectsWithQuery( r, visitor ); 00151 00152 return list; 00153 } 00154 00155 QList<int> QgsSpatialIndex::nearestNeighbor( QgsPoint point, int neighbors ) 00156 { 00157 QList<int> list; 00158 QgisVisitor visitor( list ); 00159 00160 double pt[2]; 00161 pt[0] = point.x(); 00162 pt[1] = point.y(); 00163 Tools::Geometry::Point p( pt, 2 ); 00164 00165 mRTree->nearestNeighborQuery( neighbors, p, visitor ); 00166 00167 return list; 00168 }