QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgsvectortilebasiclabeling.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectortilebasiclabeling.cpp
3  --------------------------------------
4  Date : April 2020
5  Copyright : (C) 2020 by Martin Dobias
6  Email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
17 
19 #include "qgslogger.h"
20 #include "qgsvectortilelayer.h"
21 #include "qgsvectortilerenderer.h"
22 #include "qgsvectortileutils.h"
23 
24 
25 
26 void QgsVectorTileBasicLabelingStyle::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
27 {
28  elem.setAttribute( QStringLiteral( "name" ), mStyleName );
29  elem.setAttribute( QStringLiteral( "layer" ), mLayerName );
30  elem.setAttribute( QStringLiteral( "geometry" ), mGeometryType );
31  elem.setAttribute( QStringLiteral( "enabled" ), mEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
32  elem.setAttribute( QStringLiteral( "expression" ), mExpression );
33  elem.setAttribute( QStringLiteral( "min-zoom" ), mMinZoomLevel );
34  elem.setAttribute( QStringLiteral( "max-zoom" ), mMaxZoomLevel );
35 
36  QDomDocument doc = elem.ownerDocument();
37  QDomElement elemLabelSettings = mLabelSettings.writeXml( doc, context );
38  elem.appendChild( elemLabelSettings );
39 }
40 
41 void QgsVectorTileBasicLabelingStyle::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
42 {
43  mStyleName = elem.attribute( QStringLiteral( "name" ) );
44  mLayerName = elem.attribute( QStringLiteral( "layer" ) );
45  mGeometryType = static_cast<QgsWkbTypes::GeometryType>( elem.attribute( QStringLiteral( "geometry" ) ).toInt() );
46  mEnabled = elem.attribute( QStringLiteral( "enabled" ) ).toInt();
47  mExpression = elem.attribute( QStringLiteral( "expression" ) );
48  mMinZoomLevel = elem.attribute( QStringLiteral( "min-zoom" ) ).toInt();
49  mMaxZoomLevel = elem.attribute( QStringLiteral( "max-zoom" ) ).toInt();
50 
51  QDomElement elemLabelSettings = elem.firstChildElement( QStringLiteral( "settings" ) );
52  mLabelSettings.readXml( elemLabelSettings, context );
53 }
54 
55 
56 //
57 
58 
60 {
61 }
62 
64 {
65  return QStringLiteral( "basic" );
66 }
67 
69 {
71  l->mStyles = mStyles;
72  return l;
73 }
74 
76 {
77  return new QgsVectorTileBasicLabelProvider( layer, mStyles );
78 }
79 
80 void QgsVectorTileBasicLabeling::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
81 {
82  QDomDocument doc = elem.ownerDocument();
83  QDomElement elemStyles = doc.createElement( QStringLiteral( "styles" ) );
84  for ( const QgsVectorTileBasicLabelingStyle &layerStyle : mStyles )
85  {
86  QDomElement elemStyle = doc.createElement( QStringLiteral( "style" ) );
87  layerStyle.writeXml( elemStyle, context );
88  elemStyles.appendChild( elemStyle );
89  }
90  elem.appendChild( elemStyles );
91 }
92 
93 void QgsVectorTileBasicLabeling::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
94 {
95  mStyles.clear();
96 
97  QDomElement elemStyles = elem.firstChildElement( QStringLiteral( "styles" ) );
98  QDomElement elemStyle = elemStyles.firstChildElement( QStringLiteral( "style" ) );
99  while ( !elemStyle.isNull() )
100  {
102  layerStyle.readXml( elemStyle, context );
103  mStyles.append( layerStyle );
104  elemStyle = elemStyle.nextSiblingElement( QStringLiteral( "style" ) );
105  }
106 }
107 
108 
109 //
110 
111 
112 QgsVectorTileBasicLabelProvider::QgsVectorTileBasicLabelProvider( QgsVectorTileLayer *layer, const QList<QgsVectorTileBasicLabelingStyle> &styles )
113  : QgsVectorTileLabelProvider( layer )
114  , mStyles( styles )
115 {
116 
117  for ( int i = 0; i < mStyles.count(); ++i )
118  {
119  const QgsVectorTileBasicLabelingStyle &style = mStyles[i];
120  //QgsFields fields = QgsVectorTileUtils::makeQgisFields( mRequiredFields[style.layerName()] );
121  QString providerId = QString::number( i );
122  QgsPalLayerSettings labelSettings = style.labelSettings();
123  mSubProviders.append( new QgsVectorLayerLabelProvider( style.geometryType(), QgsFields(), layer->crs(), providerId, &labelSettings, layer ) );
124  }
125 }
126 
127 QMap<QString, QSet<QString> > QgsVectorTileBasicLabelProvider::usedAttributes( const QgsRenderContext &context, int tileZoom ) const
128 {
129  QMap<QString, QSet<QString> > requiredFields;
130  for ( const QgsVectorTileBasicLabelingStyle &layerStyle : qgis::as_const( mStyles ) )
131  {
132  if ( !layerStyle.isActive( tileZoom ) )
133  continue;
134 
135  if ( !layerStyle.filterExpression().isEmpty() )
136  {
137  QgsExpression expr( layerStyle.filterExpression() );
138  requiredFields[layerStyle.layerName()].unite( expr.referencedColumns() );
139  }
140 
141  requiredFields[layerStyle.layerName()].unite( layerStyle.labelSettings().referencedFields( context ) );
142  }
143  return requiredFields;
144 }
145 
146 void QgsVectorTileBasicLabelProvider::setFields( const QMap<QString, QgsFields> &perLayerFields )
147 {
148  mPerLayerFields = perLayerFields;
149 }
150 
151 QList<QgsAbstractLabelProvider *> QgsVectorTileBasicLabelProvider::subProviders()
152 {
153  QList<QgsAbstractLabelProvider *> lst;
154  for ( QgsVectorLayerLabelProvider *subprovider : qgis::as_const( mSubProviders ) )
155  {
156  if ( subprovider ) // sub-providers that failed to initialize are set to null
157  lst << subprovider;
158  }
159  return lst;
160 }
161 
162 bool QgsVectorTileBasicLabelProvider::prepare( QgsRenderContext &context, QSet<QString> &attributeNames )
163 {
164  for ( QgsVectorLayerLabelProvider *provider : qgis::as_const( mSubProviders ) )
165  provider->setEngine( mEngine );
166 
167  // populate sub-providers
168  for ( int i = 0; i < mSubProviders.count(); ++i )
169  {
170  QgsFields fields = mPerLayerFields[mStyles[i].layerName()];
171 
172  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Layer" ) ); // will be deleted by popper
173  scope->setFields( fields );
174  QgsExpressionContextScopePopper popper( context.expressionContext(), scope );
175 
176  mSubProviders[i]->setFields( fields );
177  if ( !mSubProviders[i]->prepare( context, attributeNames ) )
178  {
179  QgsDebugMsg( QStringLiteral( "Failed to prepare labeling for style index" ) + QString::number( i ) );
180  mSubProviders[i] = nullptr;
181  }
182  }
183  return true;
184 }
185 
187 {
188  const QgsVectorTileFeatures tileData = tile.features();
189  int zoomLevel = tile.id().zoomLevel();
190 
191  for ( int i = 0; i < mStyles.count(); ++i )
192  {
193  const QgsVectorTileBasicLabelingStyle &layerStyle = mStyles.at( i );
194  if ( !layerStyle.isActive( zoomLevel ) )
195  continue;
196 
197  QgsFields fields = mPerLayerFields[layerStyle.layerName()];
198 
199  QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Layer" ) ); // will be deleted by popper
200  scope->setFields( fields );
201  QgsExpressionContextScopePopper popper( context.expressionContext(), scope );
202 
203  QgsExpression filterExpression( layerStyle.filterExpression() );
204  filterExpression.prepare( &context.expressionContext() );
205 
206  QgsVectorLayerLabelProvider *subProvider = mSubProviders[i];
207  if ( !subProvider )
208  continue; // sub-providers that failed to initialize are set to null
209 
210  if ( layerStyle.layerName().isEmpty() )
211  {
212  // matching all layers
213  for ( QString layerName : tileData.keys() )
214  {
215  for ( const QgsFeature &f : tileData[layerName] )
216  {
217  scope->setFeature( f );
218  if ( filterExpression.isValid() && !filterExpression.evaluate( &context.expressionContext() ).toBool() )
219  continue;
220 
221  if ( QgsWkbTypes::geometryType( f.geometry().wkbType() ) == layerStyle.geometryType() )
222  subProvider->registerFeature( f, context );
223  }
224  }
225  }
226  else if ( tileData.contains( layerStyle.layerName() ) )
227  {
228  // matching one particular layer
229  for ( const QgsFeature &f : tileData[layerStyle.layerName()] )
230  {
231  scope->setFeature( f );
232  if ( filterExpression.isValid() && !filterExpression.evaluate( &context.expressionContext() ).toBool() )
233  continue;
234 
235  if ( QgsWkbTypes::geometryType( f.geometry().wkbType() ) == layerStyle.geometryType() )
236  subProvider->registerFeature( f, context );
237  }
238  }
239  }
240 }
QgsMapLayer::crs
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:88
QgsExpressionContextScope::setFeature
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the scope.
Definition: qgsexpressioncontext.h:317
qgsexpressioncontextutils.h
qgsvectortilerenderer.h
QgsPalLayerSettings::readXml
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Read settings from a DOM element.
Definition: qgspallabeling.cpp:910
QgsExpressionContextScopePopper
Definition: qgsexpressioncontextutils.h:354
QgsVectorTileLayer
Definition: qgsvectortilelayer.h:83
QgsRenderContext::expressionContext
QgsExpressionContext & expressionContext()
Gets the expression context.
Definition: qgsrendercontext.h:580
QgsVectorTileBasicLabelingStyle::isActive
bool isActive(int zoomLevel) const
Returns whether the style is active at given zoom level (also checks "enabled" flag)
Definition: qgsvectortilebasiclabeling.h:76
QgsReadWriteContext
Definition: qgsreadwritecontext.h:34
QgsExpression::referencedColumns
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
Definition: qgsexpression.cpp:217
QgsVectorTileBasicLabelProvider::registerTileFeatures
void registerTileFeatures(const QgsVectorTileRendererData &tile, QgsRenderContext &context) override
Registers label features for given tile to the labeling engine.
Definition: qgsvectortilebasiclabeling.cpp:186
QgsPalLayerSettings
Definition: qgspallabeling.h:205
QgsVectorTileBasicLabeling::QgsVectorTileBasicLabeling
QgsVectorTileBasicLabeling()
Definition: qgsvectortilebasiclabeling.cpp:59
QgsVectorTileBasicLabelingStyle
Definition: qgsvectortilebasiclabeling.h:31
QgsFields
Definition: qgsfields.h:44
QgsVectorTileLabelProvider
Definition: qgsvectortilelabeling.h:33
QgsExpression::isValid
bool isValid() const
Checks if this expression is valid.
Definition: qgsexpression.cpp:197
QgsVectorTileBasicLabeling::type
QString type() const override
Unique type string of the labeling configuration implementation.
Definition: qgsvectortilebasiclabeling.cpp:63
QgsRenderContext
Definition: qgsrendercontext.h:57
QgsVectorTileBasicLabeling
Definition: qgsvectortilebasiclabeling.h:107
QgsVectorTileBasicLabelingStyle::geometryType
QgsWkbTypes::GeometryType geometryType() const
Returns type of the geometry that will be used (point / line / polygon)
Definition: qgsvectortilebasiclabeling.h:53
QgsVectorTileRendererData
Definition: qgsvectortilerenderer.h:37
QgsExpressionContextScope::setFields
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the scope.
Definition: qgsexpressioncontext.cpp:195
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsVectorLayerLabelProvider
The QgsVectorLayerLabelProvider class implements a label provider for vector layers....
Definition: qgsvectorlayerlabelprovider.h:40
QgsVectorTileBasicLabelingStyle::filterExpression
QString filterExpression() const
Returns filter expression (empty filter means that all features match)
Definition: qgsvectortilebasiclabeling.h:58
QgsVectorTileRendererData::id
QgsTileXYZ id() const
Returns coordinates of the tile.
Definition: qgsvectortilerenderer.h:44
QgsVectorTileBasicLabelProvider
Definition: qgsvectortilebasiclabeling.h:141
qgsvectortilelayer.h
QgsVectorTileBasicLabeling::readXml
void readXml(const QDomElement &elem, const QgsReadWriteContext &context) override
Reads labeling properties from given XML element.
Definition: qgsvectortilebasiclabeling.cpp:93
QgsVectorTileBasicLabelProvider::subProviders
QList< QgsAbstractLabelProvider * > subProviders() override
Returns list of child providers - useful if the provider needs to put labels into more layers with di...
Definition: qgsvectortilebasiclabeling.cpp:151
QgsVectorTileBasicLabelProvider::QgsVectorTileBasicLabelProvider
QgsVectorTileBasicLabelProvider(QgsVectorTileLayer *layer, const QList< QgsVectorTileBasicLabelingStyle > &styles)
Constructs a label provider for the given vector tile layer and using styling from QgsVectorTileBasic...
Definition: qgsvectortilebasiclabeling.cpp:112
QgsVectorTileBasicLabelingStyle::readXml
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Reads object content from given DOM element.
Definition: qgsvectortilebasiclabeling.cpp:41
QgsWkbTypes::geometryType
static GeometryType geometryType(Type type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:937
QgsVectorTileBasicLabelProvider::setFields
void setFields(const QMap< QString, QgsFields > &perLayerFields) override
Sets fields for each sub-layer.
Definition: qgsvectortilebasiclabeling.cpp:146
QgsExpression::prepare
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
Definition: qgsexpression.cpp:323
QgsTileXYZ::zoomLevel
int zoomLevel() const
Returns tile's zoom level (Z)
Definition: qgstiles.h:59
QgsAbstractLabelProvider::mEngine
const QgsLabelingEngine * mEngine
Associated labeling engine.
Definition: qgslabelingengine.h:156
QgsAbstractLabelProvider::providerId
QString providerId() const
Returns provider ID - useful in case there is more than one label provider within a layer (e....
Definition: qgslabelingengine.h:137
QgsExpression::evaluate
QVariant evaluate()
Evaluate the feature and return the result.
Definition: qgsexpression.cpp:346
QgsVectorTileBasicLabelProvider::mPerLayerFields
QMap< QString, QgsFields > mPerLayerFields
Names of required fields for each sub-layer (only valid between startRender/stopRender calls)
Definition: qgsvectortilebasiclabeling.h:163
QgsExpressionContextScope
Single scope for storing variables and functions for use within a QgsExpressionContext....
Definition: qgsexpressioncontext.h:111
QgsPalLayerSettings::writeXml
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Write settings into a DOM element.
Definition: qgspallabeling.cpp:1148
QgsVectorTileBasicLabeling::provider
QgsVectorTileLabelProvider * provider(QgsVectorTileLayer *layer) const override SIP_SKIP
Factory for label provider implementation.
Definition: qgsvectortilebasiclabeling.cpp:75
QgsWkbTypes::GeometryType
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:139
QgsVectorTileBasicLabeling::writeXml
void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const override
Writes labeling properties to given XML element.
Definition: qgsvectortilebasiclabeling.cpp:80
QgsVectorLayerLabelProvider::registerFeature
virtual void registerFeature(const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry=QgsGeometry(), const QgsSymbol *symbol=nullptr)
Register a feature for labeling as one or more QgsLabelFeature objects stored into mLabels.
Definition: qgsvectorlayerlabelprovider.cpp:190
QgsVectorTileBasicLabelingStyle::writeXml
void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const
Writes object content to given DOM element.
Definition: qgsvectortilebasiclabeling.cpp:26
QgsAbstractLabelProvider::layer
QgsMapLayer * layer() const
Returns the associated layer, or nullptr if no layer is associated with the provider.
Definition: qgslabelingengine.h:130
QgsVectorTileLabeling
Definition: qgsvectortilelabeling.h:57
QgsVectorTileBasicLabelingStyle::labelSettings
QgsPalLayerSettings labelSettings() const
Returns labeling configuration of this style.
Definition: qgsvectortilebasiclabeling.h:38
QgsFeature
Definition: qgsfeature.h:55
QgsVectorTileBasicLabelProvider::usedAttributes
QMap< QString, QSet< QString > > usedAttributes(const QgsRenderContext &context, int tileZoom) const override
Returns field names for each sub-layer that are required for labeling.
Definition: qgsvectortilebasiclabeling.cpp:127
QgsVectorTileRendererData::features
QgsVectorTileFeatures features() const
Returns features of the tile grouped by sub-layer names.
Definition: qgsvectortilerenderer.h:59
QgsVectorTileFeatures
QMap< QString, QVector< QgsFeature > > QgsVectorTileFeatures
Features of a vector tile, grouped by sub-layer names (key of the map)
Definition: qgsvectortilerenderer.h:25
qgslogger.h
QgsVectorLayerLabelProvider::QgsVectorLayerLabelProvider
QgsVectorLayerLabelProvider(QgsVectorLayer *layer, const QString &providerId, bool withFeatureLoop, const QgsPalLayerSettings *settings, const QString &layerName=QString())
Convenience constructor to initialize the provider from given vector layer.
Definition: qgsvectorlayerlabelprovider.cpp:46
QgsVectorTileBasicLabeling::clone
QgsVectorTileLabeling * clone() const override SIP_FACTORY
Returns a new copy of the object.
Definition: qgsvectortilebasiclabeling.cpp:68
qgsvectortileutils.h
QgsExpression
Definition: qgsexpression.h:113
qgsvectortilebasiclabeling.h
QgsVectorTileBasicLabelProvider::prepare
bool prepare(QgsRenderContext &context, QSet< QString > &attributeNames) override
Prepare for registration of features.
Definition: qgsvectortilebasiclabeling.cpp:162
QgsVectorTileBasicLabelingStyle::layerName
QString layerName() const
Returns name of the sub-layer to render (empty layer means that all layers match)
Definition: qgsvectortilebasiclabeling.h:48