Skip to content

Commit

Permalink
Updated memory provider to support feature source (untested yet)
Browse files Browse the repository at this point in the history
  • Loading branch information
wonder-sk committed Dec 3, 2013
1 parent 5386324 commit b99e93c
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 33 deletions.
52 changes: 35 additions & 17 deletions src/providers/memory/qgsmemoryfeatureiterator.cpp
Expand Up @@ -21,12 +21,11 @@
#include "qgsmessagelog.h"


QgsMemoryFeatureIterator::QgsMemoryFeatureIterator( QgsMemoryProvider* p, const QgsFeatureRequest& request )
: QgsAbstractFeatureIterator( request )
, P( p )

QgsMemoryFeatureIterator::QgsMemoryFeatureIterator( QgsMemoryFeatureSource* source, bool ownSource, const QgsFeatureRequest& request )
: QgsAbstractFeatureIteratorFromSource( source, ownSource, request )
, mSelectRectGeom( 0 )
{
P->mActiveIterators << this;

if ( mRequest.filterType() == QgsFeatureRequest::FilterRect && mRequest.flags() & QgsFeatureRequest::ExactIntersect )
{
Expand All @@ -35,17 +34,17 @@ QgsMemoryFeatureIterator::QgsMemoryFeatureIterator( QgsMemoryProvider* p, const

// if there's spatial index, use it!
// (but don't use it when selection rect is not specified)
if ( mRequest.filterType() == QgsFeatureRequest::FilterRect && P->mSpatialIndex )
if ( mRequest.filterType() == QgsFeatureRequest::FilterRect && mSource->mSpatialIndex )
{
mUsingFeatureIdList = true;
mFeatureIdList = P->mSpatialIndex->intersects( mRequest.filterRect() );
mFeatureIdList = mSource->mSpatialIndex->intersects( mRequest.filterRect() );
QgsDebugMsg( "Features returned by spatial index: " + QString::number( mFeatureIdList.count() ) );
}
else if ( mRequest.filterType() == QgsFeatureRequest::FilterFid )
{
mUsingFeatureIdList = true;
QgsFeatureMap::iterator it = P->mFeatures.find( mRequest.filterFid() );
if ( it != P->mFeatures.end() )
QgsFeatureMap::const_iterator it = mSource->mFeatures.find( mRequest.filterFid() );
if ( it != mSource->mFeatures.end() )
mFeatureIdList.append( mRequest.filterFid() );
}
else
Expand Down Expand Up @@ -81,12 +80,12 @@ bool QgsMemoryFeatureIterator::nextFeatureUsingList( QgsFeature& feature )
bool hasFeature = false;

// option 1: we have a list of features to traverse
while ( mFeatureIdListIterator != mFeatureIdList.end() )
while ( mFeatureIdListIterator != mFeatureIdList.constEnd() )
{
if ( mRequest.filterType() == QgsFeatureRequest::FilterRect && mRequest.flags() & QgsFeatureRequest::ExactIntersect )
{
// do exact check in case we're doing intersection
if ( P->mFeatures[*mFeatureIdListIterator].geometry()->intersects( mSelectRectGeom ) )
if ( mSource->mFeatures[*mFeatureIdListIterator].geometry()->intersects( mSelectRectGeom ) )
hasFeature = true;
}
else
Expand All @@ -101,14 +100,14 @@ bool QgsMemoryFeatureIterator::nextFeatureUsingList( QgsFeature& feature )
// copy feature
if ( hasFeature )
{
feature = P->mFeatures[*mFeatureIdListIterator];
feature = mSource->mFeatures[*mFeatureIdListIterator];
mFeatureIdListIterator++;
}
else
close();

if ( hasFeature )
feature.setFields( &P->mFields ); // allow name-based attribute lookups
feature.setFields( &mSource->mFields ); // allow name-based attribute lookups

return hasFeature;
}
Expand All @@ -119,7 +118,7 @@ bool QgsMemoryFeatureIterator::nextFeatureTraverseAll( QgsFeature& feature )
bool hasFeature = false;

// option 2: traversing the whole layer
while ( mSelectIterator != P->mFeatures.end() )
while ( mSelectIterator != mSource->mFeatures.constEnd() )
{
if ( mRequest.filterType() != QgsFeatureRequest::FilterRect )
{
Expand Down Expand Up @@ -154,7 +153,7 @@ bool QgsMemoryFeatureIterator::nextFeatureTraverseAll( QgsFeature& feature )
feature = mSelectIterator.value();
mSelectIterator++;
feature.setValid( true );
feature.setFields( &P->mFields ); // allow name-based attribute lookups
feature.setFields( &mSource->mFields ); // allow name-based attribute lookups
}
else
close();
Expand All @@ -168,9 +167,9 @@ bool QgsMemoryFeatureIterator::rewind()
return false;

if ( mUsingFeatureIdList )
mFeatureIdListIterator = mFeatureIdList.begin();
mFeatureIdListIterator = mFeatureIdList.constBegin();
else
mSelectIterator = P->mFeatures.begin();
mSelectIterator = mSource->mFeatures.constBegin();

return true;
}
Expand All @@ -180,11 +179,30 @@ bool QgsMemoryFeatureIterator::close()
if ( mClosed )
return false;

P->mActiveIterators.remove( this );
iteratorClosed();

delete mSelectRectGeom;
mSelectRectGeom = NULL;

mClosed = true;
return true;
}

// -------------------------

QgsMemoryFeatureSource::QgsMemoryFeatureSource( const QgsMemoryProvider* p )
: mFields( p->mFields )
, mFeatures( p->mFeatures )
, mSpatialIndex( p->mSpatialIndex ? new QgsSpatialIndex( *p->mSpatialIndex ) : 0 ) // just shallow copy
{
}

QgsMemoryFeatureSource::~QgsMemoryFeatureSource()
{
delete mSpatialIndex;
}

QgsFeatureIterator QgsMemoryFeatureSource::getFeatures( const QgsFeatureRequest& request )
{
return QgsFeatureIterator( new QgsMemoryFeatureIterator( this, false, request ) );
}
29 changes: 23 additions & 6 deletions src/providers/memory/qgsmemoryfeatureiterator.h
Expand Up @@ -21,11 +21,30 @@ class QgsMemoryProvider;

typedef QMap<QgsFeatureId, QgsFeature> QgsFeatureMap;

class QgsSpatialIndex;

class QgsMemoryFeatureIterator : public QgsAbstractFeatureIterator

class QgsMemoryFeatureSource : public QgsAbstractFeatureSource
{
public:
QgsMemoryFeatureSource( const QgsMemoryProvider* p );
~QgsMemoryFeatureSource();

virtual QgsFeatureIterator getFeatures( const QgsFeatureRequest& request );

protected:
QgsFields mFields;
QgsFeatureMap mFeatures;
QgsSpatialIndex* mSpatialIndex;

friend class QgsMemoryFeatureIterator;
};


class QgsMemoryFeatureIterator : public QgsAbstractFeatureIteratorFromSource<QgsMemoryFeatureSource>
{
public:
QgsMemoryFeatureIterator( QgsMemoryProvider* p, const QgsFeatureRequest& request );
QgsMemoryFeatureIterator( QgsMemoryFeatureSource* source, bool ownSource, const QgsFeatureRequest& request );

~QgsMemoryFeatureIterator();

Expand All @@ -43,13 +62,11 @@ class QgsMemoryFeatureIterator : public QgsAbstractFeatureIterator
bool nextFeatureUsingList( QgsFeature& feature );
bool nextFeatureTraverseAll( QgsFeature& feature );

QgsMemoryProvider* P;

QgsGeometry* mSelectRectGeom;
QgsFeatureMap::iterator mSelectIterator;
QgsFeatureMap::const_iterator mSelectIterator;
bool mUsingFeatureIdList;
QList<QgsFeatureId> mFeatureIdList;
QList<QgsFeatureId>::iterator mFeatureIdListIterator;
QList<QgsFeatureId>::const_iterator mFeatureIdListIterator;

};

Expand Down
14 changes: 6 additions & 8 deletions src/providers/memory/qgsmemoryprovider.cpp
Expand Up @@ -151,16 +151,14 @@ QgsMemoryProvider::QgsMemoryProvider( QString uri )

QgsMemoryProvider::~QgsMemoryProvider()
{
while ( !mActiveIterators.empty() )
{
QgsMemoryFeatureIterator *it = *mActiveIterators.begin();
QgsDebugMsg( "closing active iterator" );
it->close();
}

delete mSpatialIndex;
}

QgsAbstractFeatureSource* QgsMemoryProvider::featureSource() const
{
return new QgsMemoryFeatureSource( this );
}

QString QgsMemoryProvider::dataSourceUri() const
{
QUrl uri( "memory" );
Expand Down Expand Up @@ -238,7 +236,7 @@ QString QgsMemoryProvider::storageType() const

QgsFeatureIterator QgsMemoryProvider::getFeatures( const QgsFeatureRequest& request )
{
return QgsFeatureIterator( new QgsMemoryFeatureIterator( this, request ) );
return QgsFeatureIterator( new QgsMemoryFeatureIterator( new QgsMemoryFeatureSource( this ), true, request ) );
}


Expand Down
5 changes: 3 additions & 2 deletions src/providers/memory/qgsmemoryprovider.h
Expand Up @@ -34,6 +34,8 @@ class QgsMemoryProvider : public QgsVectorDataProvider

/* Implementation of functions from QgsVectorDataProvider */

virtual QgsAbstractFeatureSource* featureSource() const;

/**
* Returns the permanent storage type for this layer as a friendly name.
*/
Expand Down Expand Up @@ -168,6 +170,5 @@ class QgsMemoryProvider : public QgsVectorDataProvider
// indexing
QgsSpatialIndex* mSpatialIndex;

friend class QgsMemoryFeatureIterator;
QSet< QgsMemoryFeatureIterator *> mActiveIterators;
friend class QgsMemoryFeatureSource;
};

0 comments on commit b99e93c

Please sign in to comment.