[QGIS Commit] r8652 - trunk/qgis/src/providers/memory
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Mon Jun 16 20:20:19 EDT 2008
Author: wonder
Date: 2008-06-16 20:20:19 -0400 (Mon, 16 Jun 2008)
New Revision: 8652
Modified:
trunk/qgis/src/providers/memory/CMakeLists.txt
trunk/qgis/src/providers/memory/memoryprovider.cpp
trunk/qgis/src/providers/memory/memoryprovider.h
Log:
Polishing and optimizations in memory provider:
- possibility to use spatial index
- more effective getNextFeature (wheter using spatial index or not)
Modified: trunk/qgis/src/providers/memory/CMakeLists.txt
===================================================================
--- trunk/qgis/src/providers/memory/CMakeLists.txt 2008-06-17 00:15:08 UTC (rev 8651)
+++ trunk/qgis/src/providers/memory/CMakeLists.txt 2008-06-17 00:20:19 UTC (rev 8652)
@@ -3,7 +3,7 @@
INCLUDE_DIRECTORIES(
.
- ../../core
+ ../../core ../../core/spatialindex
${GEOS_INCLUDE_DIR}
)
Modified: trunk/qgis/src/providers/memory/memoryprovider.cpp
===================================================================
--- trunk/qgis/src/providers/memory/memoryprovider.cpp 2008-06-17 00:15:08 UTC (rev 8651)
+++ trunk/qgis/src/providers/memory/memoryprovider.cpp 2008-06-17 00:20:19 UTC (rev 8652)
@@ -19,6 +19,7 @@
#include "qgsfield.h"
#include "qgsgeometry.h"
#include "qgslogger.h"
+#include "qgsspatialindex.h"
#include "qgsspatialrefsys.h"
@@ -26,7 +27,9 @@
static const QString TEXT_PROVIDER_DESCRIPTION = "Memory provider";
QgsMemoryProvider::QgsMemoryProvider(QString uri)
- : QgsVectorDataProvider(uri)
+ : QgsVectorDataProvider(uri),
+ mSpatialIndex(NULL),
+ mSelectRectGeom(NULL)
{
if (uri == "Point")
mWkbType = QGis::WKBPoint;
@@ -48,6 +51,8 @@
QgsMemoryProvider::~QgsMemoryProvider()
{
+ delete mSpatialIndex;
+ delete mSelectRectGeom;
}
QString QgsMemoryProvider::storageType() const
@@ -58,23 +63,63 @@
bool QgsMemoryProvider::getNextFeature(QgsFeature& feature)
{
bool hasFeature = FALSE;
+
+ // option 1: using spatial index
+ if (mSelectUsingSpatialIndex)
+ {
+ while (mSelectSI_Iterator != mSelectSI_Features.end())
+ {
+ // do exact check in case we're doing intersection
+ if (mSelectUseIntersect)
+ {
+ if (mFeatures[*mSelectSI_Iterator].geometry()->intersects(mSelectRectGeom))
+ hasFeature = TRUE;
+ }
+ else
+ hasFeature = TRUE;
+
+ if (hasFeature)
+ break;
+
+ mSelectSI_Iterator++;
+ }
+
+ // copy feature
+ if (hasFeature)
+ {
+ feature = mFeatures[*mSelectSI_Iterator];
+ mSelectSI_Iterator++;
+ }
+ return hasFeature;
+ }
+
+ // option 2: not using spatial index
while (mSelectIterator != mFeatures.end())
{
if (mSelectRect.isEmpty())
{
+ // selection rect empty => using all features
hasFeature = TRUE;
- break;
}
else
{
- // TODO: could use some less accurate test when not using mSelectUseIntersect (e.g. spatial index)
- if (mSelectIterator->geometry()->intersects(mSelectRect))
+ if (mSelectUseIntersect)
{
- hasFeature = TRUE;
- break;
+ // using exact test when checking for intersection
+ if (mSelectIterator->geometry()->intersects(mSelectRectGeom))
+ hasFeature = TRUE;
}
+ else
+ {
+ // check just bounding box against rect when not using intersection
+ if (mSelectIterator->geometry()->boundingBox().intersects(mSelectRect))
+ hasFeature = TRUE;
+ }
}
+ if (hasFeature)
+ break;
+
mSelectIterator++;
}
@@ -88,6 +133,7 @@
return hasFeature;
}
+
bool QgsMemoryProvider::getFeatureAtId(int featureId,
QgsFeature& feature,
bool fetchGeometry,
@@ -110,15 +156,34 @@
{
mSelectAttrs = fetchAttributes;
mSelectRect = rect;
+ delete mSelectRectGeom;
+ mSelectRectGeom = QgsGeometry::fromRect(rect);
mSelectGeometry = fetchGeometry;
mSelectUseIntersect = useIntersect;
+ // if there's spatial index, use it!
+ // (but don't use it when selection rect is not specified)
+ if (mSpatialIndex && !mSelectRect.isEmpty())
+ {
+ mSelectUsingSpatialIndex = TRUE;
+ mSelectSI_Features = mSpatialIndex->intersects(rect);
+ QgsDebugMsg("Features returned by spatial index: "+QString::number(mSelectSI_Features.count()));
+ }
+ else
+ {
+ mSelectUsingSpatialIndex = FALSE;
+ mSelectSI_Features.clear();
+ }
+
reset();
}
void QgsMemoryProvider::reset()
{
- mSelectIterator = mFeatures.begin();
+ if (mSelectUsingSpatialIndex)
+ mSelectSI_Iterator = mSelectSI_Features.begin();
+ else
+ mSelectIterator = mFeatures.begin();
}
@@ -166,10 +231,17 @@
for (QgsFeatureList::iterator it = flist.begin(); it != flist.end(); ++it)
{
mFeatures[mNextFeatureId] = *it;
- mFeatures[mNextFeatureId].setFeatureId(mNextFeatureId);
+ QgsFeature& newfeat = mFeatures[mNextFeatureId];
+ newfeat.setFeatureId(mNextFeatureId);
+
+ // update spatial index
+ if (mSpatialIndex)
+ mSpatialIndex->insertFeature(newfeat);
+
mNextFeatureId++;
}
+
updateExtent();
return TRUE;
@@ -178,7 +250,19 @@
bool QgsMemoryProvider::deleteFeatures(const QgsFeatureIds & id)
{
for (QgsFeatureIds::const_iterator it = id.begin(); it != id.end(); ++it)
- mFeatures.remove(*it);
+ {
+ QgsFeatureMap::iterator fit = mFeatures.find(*it);
+
+ // check whether such feature exists
+ if (fit == mFeatures.end())
+ continue;
+
+ // update spatial index
+ if (mSpatialIndex)
+ mSpatialIndex->deleteFeature(*fit);
+
+ mFeatures.erase(fit);
+ }
updateExtent();
@@ -230,15 +314,32 @@
{
// TODO: change geometries
+ // TODO: update spatial index
+
updateExtent();
return FALSE;
}
+bool QgsMemoryProvider::createSpatialIndex()
+{
+ if (!mSpatialIndex)
+ {
+ mSpatialIndex = new QgsSpatialIndex();
+
+ // add existing features to index
+ for (QgsFeatureMap::iterator it = mFeatures.begin(); it != mFeatures.end(); ++it)
+ {
+ mSpatialIndex->insertFeature(*it);
+ }
+ }
+ return TRUE;
+}
+
int QgsMemoryProvider::capabilities() const
{
return AddFeatures | DeleteFeatures | ChangeGeometries |
- ChangeAttributeValues | AddAttributes | DeleteAttributes |
+ ChangeAttributeValues | AddAttributes | DeleteAttributes | CreateSpatialIndex |
SelectAtId | SelectGeometryAtId | RandomSelectGeometryAtId | SequentialSelectGeometryAtId;
}
Modified: trunk/qgis/src/providers/memory/memoryprovider.h
===================================================================
--- trunk/qgis/src/providers/memory/memoryprovider.h 2008-06-17 00:15:08 UTC (rev 8651)
+++ trunk/qgis/src/providers/memory/memoryprovider.h 2008-06-17 00:20:19 UTC (rev 8652)
@@ -18,6 +18,7 @@
typedef QMap<int, QgsFeature> QgsFeatureMap;
+class QgsSpatialIndex;
class QgsMemoryProvider : public QgsVectorDataProvider
{
@@ -138,6 +139,12 @@
*/
virtual bool changeGeometryValues(QgsGeometryMap & geometry_map);
+ /**
+ * Creates a spatial index
+ * @return true in case of success
+ */
+ virtual bool createSpatialIndex();
+
/** Returns a bitmask containing the supported capabilities
Note, some capabilities may change depending on whether
a spatial filter is active on this provider, so it may
@@ -188,6 +195,14 @@
// selection
QgsAttributeList mSelectAttrs;
QgsRect mSelectRect;
+ QgsGeometry* mSelectRectGeom;
bool mSelectGeometry, mSelectUseIntersect;
QgsFeatureMap::iterator mSelectIterator;
+ bool mSelectUsingSpatialIndex;
+ QList<int> mSelectSI_Features;
+ QList<int>::iterator mSelectSI_Iterator;
+
+ // indexing
+ QgsSpatialIndex* mSpatialIndex;
+
};
More information about the QGIS-commit
mailing list