mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-05 00:04:40 -05:00
[vector tile] Fix issue with disappearing features (fixes #36982)
The issue was that renderer/labeling were only keeping "their" required fields, but the final fields may have been extended by the other, making the field indices cached in expressions invalid. The fix is to keep the final QgsFields around and avoid creating those QgsFields on-the-fly from previously requested fields.
This commit is contained in:
parent
60fe81a9b1
commit
b2da49b78b
@ -42,6 +42,15 @@ Sets polygon of the tile
|
||||
QPolygon tilePolygon() const;
|
||||
%Docstring
|
||||
Returns polygon (made out of four corners of the tile) in screen coordinates calculated from render context
|
||||
%End
|
||||
|
||||
void setFields( const QMap<QString, QgsFields> &fields );
|
||||
%Docstring
|
||||
Sets per-layer fields
|
||||
%End
|
||||
QMap<QString, QgsFields> fields() const;
|
||||
%Docstring
|
||||
Returns per-layer fields
|
||||
%End
|
||||
|
||||
QStringList layers() const;
|
||||
|
||||
@ -143,9 +143,9 @@ QMap<QString, QSet<QString> > QgsVectorTileBasicLabelProvider::usedAttributes( c
|
||||
return requiredFields;
|
||||
}
|
||||
|
||||
void QgsVectorTileBasicLabelProvider::setFields( const QMap<QString, QSet<QString> > &requiredFields )
|
||||
void QgsVectorTileBasicLabelProvider::setFields( const QMap<QString, QgsFields> &perLayerFields )
|
||||
{
|
||||
mRequiredFields = requiredFields;
|
||||
mPerLayerFields = perLayerFields;
|
||||
}
|
||||
|
||||
QList<QgsAbstractLabelProvider *> QgsVectorTileBasicLabelProvider::subProviders()
|
||||
@ -167,7 +167,7 @@ bool QgsVectorTileBasicLabelProvider::prepare( QgsRenderContext &context, QSet<Q
|
||||
// populate sub-providers
|
||||
for ( int i = 0; i < mSubProviders.count(); ++i )
|
||||
{
|
||||
QgsFields fields = QgsVectorTileUtils::makeQgisFields( mRequiredFields[mStyles[i].layerName()] );
|
||||
QgsFields fields = mPerLayerFields[mStyles[i].layerName()];
|
||||
|
||||
QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Layer" ) ); // will be deleted by popper
|
||||
scope->setFields( fields );
|
||||
@ -194,7 +194,7 @@ void QgsVectorTileBasicLabelProvider::registerTileFeatures( const QgsVectorTileR
|
||||
if ( !layerStyle.isActive( zoomLevel ) )
|
||||
continue;
|
||||
|
||||
QgsFields fields = QgsVectorTileUtils::makeQgisFields( mRequiredFields[layerStyle.layerName()] );
|
||||
QgsFields fields = mPerLayerFields[layerStyle.layerName()];
|
||||
|
||||
QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Layer" ) ); // will be deleted by popper
|
||||
scope->setFields( fields );
|
||||
|
||||
@ -150,7 +150,7 @@ class QgsVectorTileBasicLabelProvider : public QgsVectorTileLabelProvider
|
||||
// virtual functions from QgsVectorTileLabelProvider
|
||||
void registerTileFeatures( const QgsVectorTileRendererData &tile, QgsRenderContext &context ) override;
|
||||
QMap<QString, QSet<QString> > usedAttributes( const QgsRenderContext &context, int tileZoom ) const override;
|
||||
void setFields( const QMap<QString, QSet<QString>> &requiredFields ) override;
|
||||
void setFields( const QMap<QString, QgsFields> &perLayerFields ) override;
|
||||
|
||||
private:
|
||||
QList<QgsVectorTileBasicLabelingStyle> mStyles;
|
||||
@ -160,7 +160,7 @@ class QgsVectorTileBasicLabelProvider : public QgsVectorTileLabelProvider
|
||||
|
||||
public:
|
||||
//! Names of required fields for each sub-layer (only valid between startRender/stopRender calls)
|
||||
QMap<QString, QSet<QString> > mRequiredFields;
|
||||
QMap<QString, QgsFields> mPerLayerFields;
|
||||
};
|
||||
|
||||
/// @endcond
|
||||
|
||||
@ -151,10 +151,8 @@ void QgsVectorTileBasicRenderer::renderTile( const QgsVectorTileRendererData &ti
|
||||
if ( !layerStyle.isActive( zoomLevel ) )
|
||||
continue;
|
||||
|
||||
QgsFields fields = QgsVectorTileUtils::makeQgisFields( mRequiredFields[layerStyle.layerName()] );
|
||||
|
||||
QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Layer" ) ); // will be deleted by popper
|
||||
scope->setFields( fields );
|
||||
scope->setFields( tile.fields()[layerStyle.layerName()] );
|
||||
QgsExpressionContextScopePopper popper( context.expressionContext(), scope );
|
||||
|
||||
QgsExpression filterExpression( layerStyle.filterExpression() );
|
||||
|
||||
@ -39,8 +39,8 @@ class QgsVectorTileLabelProvider : public QgsVectorLayerLabelProvider
|
||||
//! Returns field names for each sub-layer that are required for labeling
|
||||
virtual QMap<QString, QSet<QString> > usedAttributes( const QgsRenderContext &context, int tileZoom ) const = 0;
|
||||
|
||||
//! Sets required fields
|
||||
virtual void setFields( const QMap<QString, QSet<QString>> &requiredFields ) = 0;
|
||||
//! Sets fields for each sub-layer
|
||||
virtual void setFields( const QMap<QString, QgsFields> &perLayerFields ) = 0;
|
||||
|
||||
//! Registers label features for given tile to the labeling engine
|
||||
virtual void registerTileFeatures( const QgsVectorTileRendererData &tile, QgsRenderContext &context ) = 0;
|
||||
|
||||
@ -137,7 +137,7 @@ bool QgsVectorTileLayerRenderer::render()
|
||||
|
||||
if ( mLabelProvider )
|
||||
{
|
||||
mLabelProvider->setFields( requiredFields );
|
||||
mLabelProvider->setFields( mPerLayerFields );
|
||||
QSet<QString> attributeNames; // we don't need this - already got referenced columns in provider constructor
|
||||
if ( !mLabelProvider->prepare( ctx, attributeNames ) )
|
||||
{
|
||||
@ -197,6 +197,7 @@ void QgsVectorTileLayerRenderer::decodeAndDrawTile( const QgsVectorTileRawData &
|
||||
QgsCoordinateTransform ct = ctx.coordinateTransform();
|
||||
|
||||
QgsVectorTileRendererData tile( rawTile.id );
|
||||
tile.setFields( mPerLayerFields );
|
||||
tile.setFeatures( decoder.layerFeatures( mPerLayerFields, ct ) );
|
||||
tile.setTilePolygon( QgsVectorTileUtils::tilePolygon( rawTile.id, ct, mTileMatrix, ctx.mapToPixel() ) );
|
||||
|
||||
|
||||
@ -48,6 +48,11 @@ class CORE_EXPORT QgsVectorTileRendererData
|
||||
//! Returns polygon (made out of four corners of the tile) in screen coordinates calculated from render context
|
||||
QPolygon tilePolygon() const { return mTilePolygon; }
|
||||
|
||||
//! Sets per-layer fields
|
||||
void setFields( const QMap<QString, QgsFields> &fields ) { mFields = fields; }
|
||||
//! Returns per-layer fields
|
||||
QMap<QString, QgsFields> fields() const { return mFields; }
|
||||
|
||||
//! Sets features of the tile
|
||||
void setFeatures( const QgsVectorTileFeatures &features ) SIP_SKIP { mFeatures = features; }
|
||||
//! Returns features of the tile grouped by sub-layer names
|
||||
@ -60,6 +65,8 @@ class CORE_EXPORT QgsVectorTileRendererData
|
||||
private:
|
||||
//! Position of the tile in the tile matrix set
|
||||
QgsTileXYZ mId;
|
||||
//! Per-layer fields
|
||||
QMap<QString, QgsFields> mFields;
|
||||
//! Features of the tile grouped into sub-layers
|
||||
QgsVectorTileFeatures mFeatures;
|
||||
//! Polygon (made out of four corners of the tile) in screen coordinates calculated from render context
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user