Skip to content

Commit

Permalink
[afs] Use a hash for quick object id to feature id lookups instead
Browse files Browse the repository at this point in the history
of QList::indexOf

Speeds up feature retrieval for large layers
  • Loading branch information
nyalldawson committed Sep 28, 2022
1 parent 8343da3 commit 3801204
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 9 deletions.
1 change: 0 additions & 1 deletion src/core/providers/arcgis/qgsarcgisrestquery.cpp
Expand Up @@ -21,7 +21,6 @@
#include "qgsapplication.h"
#include "qgsmessagelog.h"
#include "qgsauthmanager.h"
#include "qgscoordinatetransform.h"
#include "qgsvariantutils.h"

#include <QUrl>
Expand Down
28 changes: 20 additions & 8 deletions src/providers/arcgisrest/qgsafsshareddata.cpp
Expand Up @@ -75,6 +75,7 @@ void QgsAfsSharedData::clearCache()

mCache.clear();
mObjectIds.clear();
mObjectIdToFeatureId.clear();
mDeletedFeatureIds.clear();
QString error;
getObjectIds( error );
Expand Down Expand Up @@ -120,9 +121,12 @@ bool QgsAfsSharedData::getObjectIds( QString &errorMessage )
}
const QVariantList objectIds = objectIdData.value( QStringLiteral( "objectIds" ) ).toList();
mObjectIds.reserve( mObjectIds.size() + objectIds.size() );
mObjectIdToFeatureId.reserve( mObjectIdToFeatureId.size() + objectIds.size() );
for ( const QVariant &objectId : objectIds )
{
mObjectIds.append( objectId.toInt() );
const int objectIdInt = objectId.toInt();
mObjectIdToFeatureId.insert( objectIdInt, mObjectIds.size() );
mObjectIds.append( objectIdInt );
}
return true;
}
Expand All @@ -133,6 +137,12 @@ quint32 QgsAfsSharedData::featureIdToObjectId( QgsFeatureId id )
return mObjectIds.value( id, -1 );
}

QgsFeatureId QgsAfsSharedData::objectIdToFeatureId( quint32 oid ) const
{
// lock must already be obtained by caller!
return mObjectIdToFeatureId.value( oid, -1 );
}

bool QgsAfsSharedData::getFeature( QgsFeatureId id, QgsFeature &f, const QgsRectangle &filterRect, QgsFeedback *feedback )
{
QgsReadWriteLocker locker( mReadWriteLock, QgsReadWriteLocker::Read );
Expand Down Expand Up @@ -214,7 +224,7 @@ bool QgsAfsSharedData::getFeature( QgsFeatureId id, QgsFeature &f, const QgsRect
{
const QVariantMap featureData = featuresData[i].toMap();
QgsFeature feature;
int featureId = startId + i;
QgsFeatureId featureId = startId + i;

// Set attributes
const QVariantMap attributesData = featureData[QStringLiteral( "attributes" )].toMap();
Expand All @@ -240,7 +250,7 @@ bool QgsAfsSharedData::getFeature( QgsFeatureId id, QgsFeature &f, const QgsRect
attributes[idx] = attribute;
if ( mFields.at( idx ).name() == mObjectIdFieldName )
{
featureId = mObjectIds.indexOf( attributesData[mFields.at( idx ).name()].toInt() );
featureId = objectIdToFeatureId( attributesData[mFields.at( idx ).name()].toInt() );
}
}
feature.setAttributes( attributes );
Expand Down Expand Up @@ -276,14 +286,14 @@ QgsFeatureIds QgsAfsSharedData::getFeatureIdsInExtent( const QgsRectangle &exten
QString errorText;

const QString authcfg = mDataSource.authConfigId();
const QList<quint32> featuresInRect = QgsArcGisRestQueryUtils::getObjectIdsByExtent( mDataSource.param( QStringLiteral( "url" ) ),
extent, errorTitle, errorText, authcfg, mDataSource.httpHeaders(), feedback, mDataSource.sql() );
const QList<quint32> objectIdsInRect = QgsArcGisRestQueryUtils::getObjectIdsByExtent( mDataSource.param( QStringLiteral( "url" ) ),
extent, errorTitle, errorText, authcfg, mDataSource.httpHeaders(), feedback, mDataSource.sql() );

QgsReadWriteLocker locker( mReadWriteLock, QgsReadWriteLocker::Read );
QgsFeatureIds ids;
for ( const quint32 id : featuresInRect )
for ( const quint32 objectId : objectIdsInRect )
{
const int featureId = mObjectIds.indexOf( id );
const QgsFeatureId featureId = objectIdToFeatureId( objectId );
if ( featureId >= 0 )
ids.insert( featureId );
}
Expand Down Expand Up @@ -369,7 +379,9 @@ bool QgsAfsSharedData::addFeatures( QgsFeatureList &features, QString &errorMess
const QVariantMap resultMap = result.toMap();
const long long objectId = resultMap.value( QStringLiteral( "objectId" ) ).toLongLong();

features[i].setId( mObjectIds.size() );
const QgsFeatureId newId = mObjectIds.size();
features[i].setId( newId );
mObjectIdToFeatureId.insert( objectId, newId );
mObjectIds.append( objectId );

i++;
Expand Down
5 changes: 5 additions & 0 deletions src/providers/arcgisrest/qgsafsshareddata.h
Expand Up @@ -51,6 +51,9 @@ class QgsAfsSharedData : public QObject

quint32 featureIdToObjectId( QgsFeatureId id );

// lock must already be obtained by caller!
QgsFeatureId objectIdToFeatureId( quint32 oid ) const;

bool getFeature( QgsFeatureId id, QgsFeature &f, const QgsRectangle &filterRect = QgsRectangle(), QgsFeedback *feedback = nullptr );
QgsFeatureIds getFeatureIdsInExtent( const QgsRectangle &extent, QgsFeedback *feedback );

Expand Down Expand Up @@ -80,6 +83,8 @@ class QgsAfsSharedData : public QObject
int mObjectIdFieldIdx = -1;

QList<quint32> mObjectIds;
QHash<quint32, QgsFeatureId> mObjectIdToFeatureId;

QSet<QgsFeatureId> mDeletedFeatureIds;
QMap<QgsFeatureId, QgsFeature> mCache;
QgsCoordinateReferenceSystem mSourceCRS;
Expand Down

0 comments on commit 3801204

Please sign in to comment.