Quantum GIS API Documentation  1.8
src/core/qgsspatialindex.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines