-
-
Notifications
You must be signed in to change notification settings - Fork 3k
/
qgsafsshareddata.cpp
121 lines (108 loc) · 4.44 KB
/
qgsafsshareddata.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/***************************************************************************
qgsafsshareddata.cpp
---------------------
begin : June 2017
copyright : (C) 2017 by Sandro Mani
email : manisandro at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsafsshareddata.h"
#include "qgsarcgisrestutils.h"
#include "qgslogger.h"
void QgsAfsSharedData::clearCache()
{
QMutexLocker locker( &mMutex );
mCache.clear();
}
bool QgsAfsSharedData::getFeature( QgsFeatureId id, QgsFeature &f, bool fetchGeometry, const QList<int> & /*fetchAttributes*/, const QgsRectangle &filterRect )
{
QMutexLocker locker( &mMutex );
// If cached, return cached feature
QMap<QgsFeatureId, QgsFeature>::const_iterator it = mCache.constFind( id );
if ( it != mCache.constEnd() )
{
f = it.value();
return filterRect.isNull() || f.geometry().intersects( filterRect );
}
// Determine attributes to fetch
/*QStringList fetchAttribNames;
foreach ( int idx, fetchAttributes )
fetchAttribNames.append( mFields.at( idx ).name() );
*/
// When fetching from server, fetch all attributes and geometry by default so that we can cache them
QStringList fetchAttribNames;
QList<int> fetchAttribIdx;
fetchAttribIdx.reserve( mFields.size() );
for ( int idx = 0, n = mFields.size(); idx < n; ++idx )
{
fetchAttribNames.append( mFields.at( idx ).name() );
fetchAttribIdx.append( idx );
}
fetchGeometry = true;
// Fetch 100 features at the time
int startId = ( id / 100 ) * 100;
int stopId = std::min( startId + 100, mObjectIds.length() );
QList<quint32> objectIds;
objectIds.reserve( stopId );
for ( int i = startId; i < stopId; ++i )
{
objectIds.append( mObjectIds[i] );
}
// Query
QString errorTitle, errorMessage;
QVariantMap queryData = QgsArcGisRestUtils::getObjects(
mDataSource.param( QStringLiteral( "url" ) ), objectIds, mDataSource.param( QStringLiteral( "crs" ) ), fetchGeometry,
fetchAttribNames, QgsWkbTypes::hasM( mGeometryType ), QgsWkbTypes::hasZ( mGeometryType ),
filterRect, errorTitle, errorMessage );
if ( queryData.isEmpty() )
{
// const_cast<QgsAfsProvider *>( this )->pushError( errorTitle + ": " + errorMessage );
QgsDebugMsg( "Query returned empty result" );
return false;
}
QVariantList featuresData = queryData[QStringLiteral( "features" )].toList();
if ( featuresData.isEmpty() )
{
QgsDebugMsg( "Query returned no features" );
return false;
}
for ( int i = 0, n = featuresData.size(); i < n; ++i )
{
QVariantMap featureData = featuresData[i].toMap();
QgsFeature feature;
// Set FID
feature.setId( startId + i );
// Set attributes
if ( !fetchAttribIdx.isEmpty() )
{
QVariantMap attributesData = featureData[QStringLiteral( "attributes" )].toMap();
feature.setFields( mFields );
QgsAttributes attributes( mFields.size() );
foreach ( int idx, fetchAttribIdx )
{
attributes[idx] = attributesData[mFields.at( idx ).name()];
}
feature.setAttributes( attributes );
}
// Set geometry
if ( fetchGeometry )
{
QVariantMap geometryData = featureData[QStringLiteral( "geometry" )].toMap();
QgsAbstractGeometry *geometry = QgsArcGisRestUtils::parseEsriGeoJSON( geometryData, queryData[QStringLiteral( "geometryType" )].toString(),
QgsWkbTypes::hasM( mGeometryType ), QgsWkbTypes::hasZ( mGeometryType ) );
// Above might return 0, which is OK since in theory empty geometries are allowed
feature.setGeometry( QgsGeometry( geometry ) );
}
feature.setValid( true );
mCache.insert( feature.id(), feature );
}
f = mCache[id];
Q_ASSERT( f.isValid() );
return filterRect.isNull() || ( f.hasGeometry() && f.geometry().intersects( filterRect ) );
}