QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsvectortilelayer.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsvectortilelayer.cpp
3 --------------------------------------
4 Date : March 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
16#include "qgsvectortilelayer.h"
17
18#include "qgslogger.h"
23#include "qgsvectortileloader.h"
24#include "qgsvectortileutils.h"
27#include "qgsdatasourceuri.h"
31#include "qgsjsonutils.h"
32#include "qgspainting.h"
33#include "qgsmaplayerfactory.h"
34#include "qgsselectioncontext.h"
35#include "qgsgeometryengine.h"
37#include "qgsthreadingutils.h"
38#include "qgsproviderregistry.h"
40
41#include <QUrl>
42#include <QUrlQuery>
43
44QgsVectorTileLayer::QgsVectorTileLayer( const QString &uri, const QString &baseName, const LayerOptions &options )
45 : QgsMapLayer( Qgis::LayerType::VectorTile, baseName )
46 , mTransformContext( options.transformContext )
47{
48 mDataSource = uri;
49
50 if ( !uri.isEmpty() )
51 setValid( loadDataSource() );
52
53 // set a default renderer
57
58 connect( this, &QgsVectorTileLayer::selectionChanged, this, [this] { triggerRepaint(); } );
59}
60
61void QgsVectorTileLayer::setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &, const QgsDataProvider::ProviderOptions &, QgsDataProvider::ReadFlags )
62{
64
65 mDataSource = dataSource;
66 mLayerName = baseName;
67 mDataProvider.reset();
68
69 setValid( loadDataSource() );
70}
71
72bool QgsVectorTileLayer::loadDataSource()
73{
75
76 QgsDataSourceUri dsUri;
78
79 setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3857" ) ) );
80
81 const QgsDataProvider::ProviderOptions providerOptions { mTransformContext };
83
84 mSourceType = dsUri.param( QStringLiteral( "type" ) );
85 QString providerKey;
86 if ( mSourceType == QLatin1String( "xyz" ) && dsUri.param( QStringLiteral( "serviceType" ) ) == QLatin1String( "arcgis" ) )
87 {
88 providerKey = QStringLiteral( "arcgisvectortileservice" );
89 }
90 else if ( mSourceType == QLatin1String( "xyz" ) )
91 {
92 providerKey = QStringLiteral( "xyzvectortiles" );
93 }
94 else if ( mSourceType == QLatin1String( "mbtiles" ) )
95 {
96 providerKey = QStringLiteral( "mbtilesvectortiles" );
97 }
98 else if ( mSourceType == QLatin1String( "vtpk" ) )
99 {
100 providerKey = QStringLiteral( "vtpkvectortiles" );
101 }
102 else
103 {
104 QgsDebugError( QStringLiteral( "Unknown source type: " ) + mSourceType );
105 return false;
106 }
107
108 mDataProvider.reset( qobject_cast<QgsVectorTileDataProvider *>( QgsProviderRegistry::instance()->createProvider( providerKey, mDataSource, providerOptions, flags ) ) );
109 mProviderKey = mDataProvider->name();
110
111 if ( mDataProvider )
112 {
113 mMatrixSet = qgis::down_cast< QgsVectorTileDataProvider * >( mDataProvider.get() )->tileMatrixSet();
114 setCrs( mDataProvider->crs() );
115 setExtent( mDataProvider->extent() );
116 }
117
118 return mDataProvider && mDataProvider->isValid();
119}
120
122
124{
126
127 const QgsVectorTileLayer::LayerOptions options( mTransformContext );
128 QgsVectorTileLayer *layer = new QgsVectorTileLayer( source(), name(), options );
129 layer->setRenderer( renderer() ? renderer()->clone() : nullptr );
130 return layer;
131}
132
134{
136
137 return mDataProvider.get();
138}
139
141{
143
144 return mDataProvider.get();
145}
146
148{
150
151 return new QgsVectorTileLayerRenderer( this, rendererContext );
152}
153
154bool QgsVectorTileLayer::readXml( const QDomNode &layerNode, QgsReadWriteContext &context )
155{
157
158 setValid( loadDataSource() );
159
160 if ( !mDataProvider || !( qobject_cast< QgsVectorTileDataProvider * >( mDataProvider.get() )->providerFlags() & Qgis::VectorTileProviderFlag::AlwaysUseTileMatrixSetFromProvider ) )
161 {
162 const QDomElement matrixSetElement = layerNode.firstChildElement( QStringLiteral( "matrixSet" ) );
163 if ( !matrixSetElement.isNull() )
164 {
165 mMatrixSet.readXml( matrixSetElement, context );
166 }
167 }
168 setCrs( mMatrixSet.crs() );
169
170 QString errorMsg;
171 if ( !readSymbology( layerNode, errorMsg, context ) )
172 return false;
173
174 readStyleManager( layerNode );
175 return true;
176}
177
178bool QgsVectorTileLayer::writeXml( QDomNode &layerNode, QDomDocument &doc, const QgsReadWriteContext &context ) const
179{
181
182 QDomElement mapLayerNode = layerNode.toElement();
183 mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( Qgis::LayerType::VectorTile ) );
184
185 if ( !mDataProvider || !( qobject_cast< QgsVectorTileDataProvider * >( mDataProvider.get() )->providerFlags() & Qgis::VectorTileProviderFlag::AlwaysUseTileMatrixSetFromProvider ) )
186 {
187 mapLayerNode.appendChild( mMatrixSet.writeXml( doc, context ) );
188 }
189
190 // add provider node
191 if ( mDataProvider )
192 {
193 QDomElement provider = doc.createElement( QStringLiteral( "provider" ) );
194 const QDomText providerText = doc.createTextNode( providerType() );
195 provider.appendChild( providerText );
196 mapLayerNode.appendChild( provider );
197 }
198
199 writeStyleManager( layerNode, doc );
200
201 QString errorMsg;
202 return writeSymbology( layerNode, doc, errorMsg, context );
203}
204
205bool QgsVectorTileLayer::readSymbology( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
206{
208
209 const QDomElement elem = node.toElement();
210
211 readCommonStyle( elem, context, categories );
212
213 const QDomElement elemRenderer = elem.firstChildElement( QStringLiteral( "renderer" ) );
214 if ( elemRenderer.isNull() )
215 {
216 errorMessage = tr( "Missing <renderer> tag" );
217 return false;
218 }
219 const QString rendererType = elemRenderer.attribute( QStringLiteral( "type" ) );
220
221 if ( categories.testFlag( Symbology ) )
222 {
223 QgsVectorTileRenderer *r = nullptr;
224 if ( rendererType == QLatin1String( "basic" ) )
226 else
227 {
228 errorMessage = tr( "Unknown renderer type: " ) + rendererType;
229 return false;
230 }
231
232 r->readXml( elemRenderer, context );
233 setRenderer( r );
234 }
235
236 if ( categories.testFlag( Labeling ) )
237 {
238 setLabeling( nullptr );
239 const QDomElement elemLabeling = elem.firstChildElement( QStringLiteral( "labeling" ) );
240 if ( !elemLabeling.isNull() )
241 {
242 const QString labelingType = elemLabeling.attribute( QStringLiteral( "type" ) );
244 if ( labelingType == QLatin1String( "basic" ) )
246 else
247 {
248 errorMessage = tr( "Unknown labeling type: " ) + rendererType;
249 }
250
251 if ( elemLabeling.hasAttribute( QStringLiteral( "labelsEnabled" ) ) )
252 mLabelsEnabled = elemLabeling.attribute( QStringLiteral( "labelsEnabled" ) ).toInt();
253 else
254 mLabelsEnabled = true;
255
256 if ( labeling )
257 {
258 labeling->readXml( elemLabeling, context );
260 }
261 }
262 }
263
264 if ( categories.testFlag( Symbology ) )
265 {
266 // get and set the blend mode if it exists
267 const QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
268 if ( !blendModeNode.isNull() )
269 {
270 const QDomElement e = blendModeNode.toElement();
271 setBlendMode( QgsPainting::getCompositionMode( static_cast< Qgis::BlendMode >( e.text().toInt() ) ) );
272 }
273 }
274
275 // get and set the layer transparency
276 if ( categories.testFlag( Rendering ) )
277 {
278 const QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
279 if ( !layerOpacityNode.isNull() )
280 {
281 const QDomElement e = layerOpacityNode.toElement();
282 setOpacity( e.text().toDouble() );
283 }
284 }
285
286 return true;
287}
288
289bool QgsVectorTileLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
290{
292
293 Q_UNUSED( errorMessage )
294 QDomElement elem = node.toElement();
295
296 writeCommonStyle( elem, doc, context, categories );
297
298 if ( mRenderer )
299 {
300 QDomElement elemRenderer = doc.createElement( QStringLiteral( "renderer" ) );
301 elemRenderer.setAttribute( QStringLiteral( "type" ), mRenderer->type() );
302 if ( categories.testFlag( Symbology ) )
303 {
304 mRenderer->writeXml( elemRenderer, context );
305 }
306 elem.appendChild( elemRenderer );
307 }
308
309 if ( mLabeling && categories.testFlag( Labeling ) )
310 {
311 QDomElement elemLabeling = doc.createElement( QStringLiteral( "labeling" ) );
312 elemLabeling.setAttribute( QStringLiteral( "type" ), mLabeling->type() );
313 elemLabeling.setAttribute( QStringLiteral( "labelsEnabled" ), mLabelsEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
314 mLabeling->writeXml( elemLabeling, context );
315 elem.appendChild( elemLabeling );
316 }
317
318 if ( categories.testFlag( Symbology ) )
319 {
320 // add the blend mode field
321 QDomElement blendModeElem = doc.createElement( QStringLiteral( "blendMode" ) );
322 const QDomText blendModeText = doc.createTextNode( QString::number( static_cast< int >( QgsPainting::getBlendModeEnum( blendMode() ) ) ) );
323 blendModeElem.appendChild( blendModeText );
324 node.appendChild( blendModeElem );
325 }
326
327 // add the layer opacity
328 if ( categories.testFlag( Rendering ) )
329 {
330 QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
331 const QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
332 layerOpacityElem.appendChild( layerOpacityText );
333 node.appendChild( layerOpacityElem );
334 }
335
336 return true;
337}
338
340{
342
343 if ( mDataProvider )
344 mDataProvider->setTransformContext( transformContext );
345
346 mTransformContext = transformContext;
348}
349
350QString QgsVectorTileLayer::loadDefaultStyle( bool &resultFlag )
351{
353
354 QString error;
355 QStringList warnings;
356 resultFlag = loadDefaultStyle( error, warnings );
357 return error;
358}
359
361{
363
365 if ( mSourceType == QLatin1String( "xyz" ) )
366 {
367 // always consider xyz vector tiles as basemap layers
369 }
370 else
371 {
372 // TODO when should we consider mbtiles layers as basemap layers? potentially if their extent is "large"?
373 }
374
375 return res;
376}
377
378bool QgsVectorTileLayer::loadDefaultStyle( QString &error, QStringList &warnings )
379{
381
382 return loadDefaultStyleAndSubLayersPrivate( error, warnings, nullptr );
383}
384
385bool QgsVectorTileLayer::loadDefaultStyleAndSubLayers( QString &error, QStringList &warnings, QList<QgsMapLayer *> &subLayers )
386{
388
389 return loadDefaultStyleAndSubLayersPrivate( error, warnings, &subLayers );
390}
391
392bool QgsVectorTileLayer::loadDefaultStyleAndSubLayersPrivate( QString &error, QStringList &warnings, QList<QgsMapLayer *> *subLayers )
393{
395 QgsVectorTileDataProvider *vtProvider = qgis::down_cast< QgsVectorTileDataProvider *> ( mDataProvider.get() );
396 if ( !vtProvider )
397 return false;
398
399 QgsDataSourceUri dsUri;
400 dsUri.setEncodedUri( mDataSource );
401
402 QVariantMap styleDefinition;
404 QString styleUrl;
405 if ( !dsUri.param( QStringLiteral( "styleUrl" ) ).isEmpty() )
406 {
407 styleUrl = dsUri.param( QStringLiteral( "styleUrl" ) );
408 }
409 else
410 {
411 styleUrl = vtProvider->styleUrl();
412 }
413
414 styleDefinition = vtProvider->styleDefinition();
415 const QVariantMap spriteDefinition = vtProvider->spriteDefinition();
416 if ( !spriteDefinition.isEmpty() )
417 {
418 const QImage spriteImage = vtProvider->spriteImage();
419 context.setSprites( spriteImage, spriteDefinition );
420 }
421
422 if ( !styleDefinition.isEmpty() || !styleUrl.isEmpty() )
423 {
424 if ( styleDefinition.isEmpty() )
425 {
426 QNetworkRequest request = QNetworkRequest( QUrl( styleUrl ) );
427
428 QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsVectorTileLayer" ) );
429
430 QgsBlockingNetworkRequest networkRequest;
431 switch ( networkRequest.get( request ) )
432 {
434 break;
435
439 error = QObject::tr( "Error retrieving default style" );
440 return false;
441 }
442
443 const QgsNetworkReplyContent content = networkRequest.reply();
444 styleDefinition = QgsJsonUtils::parseJson( content.content() ).toMap();
445 }
446
447 QgsVectorTileUtils::loadSprites( styleDefinition, context, styleUrl );
448 }
449
450 if ( !styleDefinition.isEmpty() )
451 {
452 // convert automatically from pixel sizes to millimeters, because pixel sizes
453 // are a VERY edge case in QGIS and don't play nice with hidpi map renders or print layouts
455 //assume source uses 96 dpi
456 context.setPixelSizeConversionFactor( 25.4 / 96.0 );
457
459 if ( converter.convert( styleDefinition, &context ) != QgsMapBoxGlStyleConverter::Success )
460 {
461 warnings = converter.warnings();
462 error = converter.errorMessage();
463 return false;
464 }
465
466 setRenderer( converter.renderer() );
467 setLabeling( converter.labeling() );
468 warnings = converter.warnings();
469
470 if ( subLayers )
471 {
472 *subLayers = converter.createSubLayers();
473 }
474
475 return true;
476 }
477 else
478 {
479 bool resultFlag = false;
480 error = QgsMapLayer::loadDefaultStyle( resultFlag );
481 return resultFlag;
482 }
483}
484
486{
488
489 resultFlag = false;
490 if ( !mDataProvider || !mDataProvider->isValid() )
491 return QString();
492
493 if ( qgis::down_cast< QgsVectorTileDataProvider * >( mDataProvider.get() )->providerCapabilities() & Qgis::VectorTileProviderCapability::ReadLayerMetadata )
494 {
495 setMetadata( mDataProvider->layerMetadata() );
496 }
497 else
498 {
500 }
501 resultFlag = true;
502 return QString();
503}
504
505QString QgsVectorTileLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
506{
508
510}
511
512QString QgsVectorTileLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
513{
515
516 return QgsProviderRegistry::instance()->relativeToAbsoluteUri( provider, source, context );
517}
518
520{
522
523 const QgsLayerMetadataFormatter htmlFormatter( metadata() );
524
525 QString info = QStringLiteral( "<html><head></head>\n<body>\n" );
526
527 info += generalHtmlMetadata();
528
529 info += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" ) %
530 QStringLiteral( "<table class=\"list-view\">\n" );
531
532 info += QStringLiteral( "<tr><td class=\"highlight\">" ) % tr( "Source type" ) % QStringLiteral( "</td><td>" ) % sourceType() % QStringLiteral( "</td></tr>\n" );
533
534 info += QStringLiteral( "<tr><td class=\"highlight\">" ) % tr( "Zoom levels" ) % QStringLiteral( "</td><td>" ) % QStringLiteral( "%1 - %2" ).arg( sourceMinZoom() ).arg( sourceMaxZoom() ) % QStringLiteral( "</td></tr>\n" );
535
536 if ( mDataProvider )
537 info += qobject_cast< const QgsVectorTileDataProvider * >( mDataProvider.get() )->htmlMetadata();
538
539 info += QLatin1String( "</table>\n<br>" );
540
541 // CRS
542 info += crsHtmlMetadata();
543
544 // Identification section
545 info += QStringLiteral( "<h1>" ) % tr( "Identification" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
546 htmlFormatter.identificationSectionHtml() %
547 QStringLiteral( "<br>\n" ) %
548
549 // extent section
550 QStringLiteral( "<h1>" ) % tr( "Extent" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
551 htmlFormatter.extentSectionHtml( ) %
552 QStringLiteral( "<br>\n" ) %
553
554 // Start the Access section
555 QStringLiteral( "<h1>" ) % tr( "Access" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
556 htmlFormatter.accessSectionHtml( ) %
557 QStringLiteral( "<br>\n" ) %
558
559
560 // Start the contacts section
561 QStringLiteral( "<h1>" ) % tr( "Contacts" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
562 htmlFormatter.contactsSectionHtml( ) %
563 QStringLiteral( "<br><br>\n" ) %
564
565 // Start the links section
566 QStringLiteral( "<h1>" ) % tr( "References" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
567 htmlFormatter.linksSectionHtml( ) %
568 QStringLiteral( "<br>\n" ) %
569
570 // Start the history section
571 QStringLiteral( "<h1>" ) % tr( "History" ) % QStringLiteral( "</h1>\n<hr>\n" ) %
572 htmlFormatter.historySectionHtml( ) %
573 QStringLiteral( "<br>\n" ) %
574
575 QStringLiteral( "\n</body>\n</html>\n" );
576
577 return info;
578}
579
581{
582 if ( QgsVectorTileDataProvider *vtProvider = qobject_cast< QgsVectorTileDataProvider * >( mDataProvider.get() ) )
583 return vtProvider->sourcePath();
584
585 return QString();
586}
587
589{
591
592 QgsVectorTileDataProvider *vtProvider = qobject_cast< QgsVectorTileDataProvider * >( mDataProvider.get() );
593 if ( !vtProvider )
594 return QgsVectorTileRawData();
595
596 return vtProvider->readTile( mMatrixSet, tileID );
597}
598
600{
602
603 mRenderer.reset( r );
605}
606
608{
610
611 return mRenderer.get();
612}
613
615{
617
618 mLabeling.reset( labeling );
620}
621
623{
625
626 return mLabeling.get();
627}
628
630{
631 // non fatal for now -- the "rasterize" processing algorithm is not thread safe and calls this
633
634 return mLabelsEnabled && static_cast< bool >( mLabeling );
635}
636
638{
640
641 mLabelsEnabled = enabled;
642}
643
645{
647
648 QList< QgsFeature > res;
649 res.reserve( mSelectedFeatures.size() );
650 for ( auto it = mSelectedFeatures.begin(); it != mSelectedFeatures.end(); ++it )
651 res.append( it.value() );
652
653 return res;
654}
655
657{
659
660 return mSelectedFeatures.size();
661}
662
664{
666
667 if ( !isInScaleRange( context.scale() ) )
668 {
669 QgsDebugMsgLevel( QStringLiteral( "Out of scale limits" ), 2 );
670 return;
671 }
672
673 QSet< QgsFeatureId > prevSelection;
674 prevSelection.reserve( mSelectedFeatures.size() );
675 for ( auto it = mSelectedFeatures.begin(); it != mSelectedFeatures.end(); ++it )
676 prevSelection.insert( it.key() );
677
679 {
680 switch ( behavior )
681 {
683 mSelectedFeatures.clear();
684 break;
685
689 break;
690 }
691 }
692
693 QgsGeometry selectionGeom = geometry;
694 bool isPointOrRectangle;
695 QgsPointXY point;
696 bool isSinglePoint = selectionGeom.type() == Qgis::GeometryType::Point;
697 if ( isSinglePoint )
698 {
699 isPointOrRectangle = true;
700 point = selectionGeom.asPoint();
702 }
703 else
704 {
705 // we have a polygon - maybe it is a rectangle - in such case we can avoid costly instersection tests later
706 isPointOrRectangle = QgsGeometry::fromRect( selectionGeom.boundingBox() ).isGeosEqual( selectionGeom );
707 }
708
709 auto addDerivedFields = []( QgsFeature & feature, const int tileZoom, const QString & layer )
710 {
711 QgsFields fields = feature.fields();
712 fields.append( QgsField( QStringLiteral( "tile_zoom" ), QVariant::Int ) );
713 fields.append( QgsField( QStringLiteral( "tile_layer" ), QVariant::String ) );
714 QgsAttributes attributes = feature.attributes();
715 attributes << tileZoom << layer;
716 feature.setFields( fields );
717 feature.setAttributes( attributes );
718 };
719
720 std::unique_ptr<QgsGeometryEngine> selectionGeomPrepared;
721 QList< QgsFeature > singleSelectCandidates;
722
723 QgsRectangle r;
724 if ( isSinglePoint )
725 {
726 r = QgsRectangle( point.x(), point.y(), point.x(), point.y() );
727 }
728 else
729 {
730 r = selectionGeom.boundingBox();
731
732 if ( !isPointOrRectangle || relationship == Qgis::SelectGeometryRelationship::Within )
733 {
734 // use prepared geometry for faster intersection test
735 selectionGeomPrepared.reset( QgsGeometry::createGeometryEngine( selectionGeom.constGet() ) );
736 }
737 }
738
739 switch ( behavior )
740 {
743 {
744 // when adding to or setting a selection, we retrieve the tile data for the current scale
745 const int tileZoom = tileMatrixSet().scaleToZoomLevel( context.scale() );
746 const QgsTileMatrix tileMatrix = tileMatrixSet().tileMatrix( tileZoom );
747 const QgsTileRange tileRange = tileMatrix.tileRangeFromExtent( r );
748 const QVector< QgsTileXYZ> tiles = tileMatrixSet().tilesInRange( tileRange, tileZoom );
749
750 for ( const QgsTileXYZ &tileID : tiles )
751 {
752 const QgsVectorTileRawData data = getRawTile( tileID );
753 if ( data.data.isEmpty() )
754 continue; // failed to get data
755
757 if ( !decoder.decode( data ) )
758 continue; // failed to decode
759
760 QMap<QString, QgsFields> perLayerFields;
761 const QStringList layerNames = decoder.layers();
762 for ( const QString &layerName : layerNames )
763 {
764 QSet<QString> fieldNames = qgis::listToSet( decoder.layerFieldNames( layerName ) );
765 perLayerFields[layerName] = QgsVectorTileUtils::makeQgisFields( fieldNames );
766 }
767
768 const QgsVectorTileFeatures features = decoder.layerFeatures( perLayerFields, QgsCoordinateTransform() );
769 const QStringList featuresLayerNames = features.keys();
770 for ( const QString &layerName : featuresLayerNames )
771 {
772 const QgsFields fFields = perLayerFields[layerName];
773 const QVector<QgsFeature> &layerFeatures = features[layerName];
774 for ( const QgsFeature &f : layerFeatures )
775 {
776 if ( renderContext && mRenderer && !mRenderer->willRenderFeature( f, tileID.zoomLevel(), layerName, *renderContext ) )
777 continue;
778
779 if ( f.geometry().intersects( r ) )
780 {
781 bool selectFeature = true;
782 if ( selectionGeomPrepared )
783 {
784 switch ( relationship )
785 {
787 selectFeature = selectionGeomPrepared->intersects( f.geometry().constGet() );
788 break;
790 selectFeature = selectionGeomPrepared->contains( f.geometry().constGet() );
791 break;
792 }
793 }
794
795 if ( selectFeature )
796 {
797 QgsFeature derivedFeature = f;
798 addDerivedFields( derivedFeature, tileID.zoomLevel(), layerName );
800 singleSelectCandidates << derivedFeature;
801 else
802 mSelectedFeatures.insert( derivedFeature.id(), derivedFeature );
803 }
804 }
805 }
806 }
807 }
808 break;
809 }
810
813 {
814 // when removing from the selection, we instead just iterate over the current selection and test against the geometry
815 // we do this as we don't want the selection removal operation to depend at all on the tile zoom
816 for ( auto it = mSelectedFeatures.begin(); it != mSelectedFeatures.end(); )
817 {
818 bool matchesGeometry = false;
819 if ( selectionGeomPrepared )
820 {
821 switch ( relationship )
822 {
824 matchesGeometry = selectionGeomPrepared->intersects( it->geometry().constGet() );
825 break;
827 matchesGeometry = selectionGeomPrepared->contains( it->geometry().constGet() );
828 break;
829 }
830 }
831 else
832 {
833 switch ( relationship )
834 {
836 matchesGeometry = it->geometry().intersects( r );
837 break;
839 matchesGeometry = r.contains( it->geometry().boundingBox() );
840 break;
841 }
842 }
843
845 {
846 singleSelectCandidates << it.value();
847 it++;
848 }
849 else if ( ( matchesGeometry && behavior == Qgis::SelectBehavior::IntersectSelection )
850 || ( !matchesGeometry && behavior == Qgis::SelectBehavior::RemoveFromSelection ) )
851 {
852 it++;
853 }
854 else
855 {
856 it = mSelectedFeatures.erase( it );
857 }
858 }
859 break;
860 }
861 }
862
863 if ( ( flags & Qgis::SelectionFlag::SingleFeatureSelection ) && !singleSelectCandidates.empty() )
864 {
865 QgsFeature bestCandidate;
866
868 {
869 // when toggling a selection, we first check to see if we can remove a feature from the current selection -- that takes precedence over adding new features to the selection
870
871 // find smallest feature in the current selection
872 double smallestArea = std::numeric_limits< double >::max();
873 double smallestLength = std::numeric_limits< double >::max();
874 for ( const QgsFeature &candidate : std::as_const( singleSelectCandidates ) )
875 {
876 if ( !mSelectedFeatures.contains( candidate.id() ) )
877 continue;
878
879 switch ( candidate.geometry().type() )
880 {
882 bestCandidate = candidate;
883 break;
885 {
886 const double length = candidate.geometry().length();
887 if ( length < smallestLength && bestCandidate.geometry().type() != Qgis::GeometryType::Point )
888 {
889 bestCandidate = candidate;
890 smallestLength = length;
891 }
892 break;
893 }
895 {
896 const double area = candidate.geometry().area();
897 if ( area < smallestArea && bestCandidate.geometry().type() != Qgis::GeometryType::Point && bestCandidate.geometry().type() != Qgis::GeometryType::Line )
898 {
899 bestCandidate = candidate;
900 smallestArea = area;
901 }
902 break;
903 }
906 break;
907 }
908 }
909 }
910
911 if ( !bestCandidate.isValid() )
912 {
913 // find smallest feature (ie. pick the "hardest" one to click on)
914 double smallestArea = std::numeric_limits< double >::max();
915 double smallestLength = std::numeric_limits< double >::max();
916 for ( const QgsFeature &candidate : std::as_const( singleSelectCandidates ) )
917 {
918 switch ( candidate.geometry().type() )
919 {
921 bestCandidate = candidate;
922 break;
924 {
925 const double length = candidate.geometry().length();
926 if ( length < smallestLength && bestCandidate.geometry().type() != Qgis::GeometryType::Point )
927 {
928 bestCandidate = candidate;
929 smallestLength = length;
930 }
931 break;
932 }
934 {
935 const double area = candidate.geometry().area();
936 if ( area < smallestArea && bestCandidate.geometry().type() != Qgis::GeometryType::Point && bestCandidate.geometry().type() != Qgis::GeometryType::Line )
937 {
938 bestCandidate = candidate;
939 smallestArea = area;
940 }
941 break;
942 }
945 break;
946 }
947 }
948 }
949
951 {
952 if ( prevSelection.contains( bestCandidate.id() ) )
953 mSelectedFeatures.remove( bestCandidate.id() );
954 else
955 mSelectedFeatures.insert( bestCandidate.id(), bestCandidate );
956 }
957 else
958 {
959 switch ( behavior )
960 {
963 mSelectedFeatures.insert( bestCandidate.id(), bestCandidate );
964 break;
965
967 {
968 if ( mSelectedFeatures.contains( bestCandidate.id() ) )
969 {
970 mSelectedFeatures.clear();
971 mSelectedFeatures.insert( bestCandidate.id(), bestCandidate );
972 }
973 else
974 {
975 mSelectedFeatures.clear();
976 }
977 break;
978 }
979
981 {
982 mSelectedFeatures.remove( bestCandidate.id() );
983 break;
984 }
985 }
986 }
987 }
988
989 QSet< QgsFeatureId > newSelection;
990 newSelection.reserve( mSelectedFeatures.size() );
991 for ( auto it = mSelectedFeatures.begin(); it != mSelectedFeatures.end(); ++it )
992 newSelection.insert( it.key() );
993
994 // signal
995 if ( prevSelection != newSelection )
996 emit selectionChanged();
997}
998
1000{
1002
1003 if ( mSelectedFeatures.empty() )
1004 return;
1005
1006 mSelectedFeatures.clear();
1007 emit selectionChanged();
1008}
1009
1010
The Qgis class provides global constants for use throughout the application.
Definition: qgis.h:54
@ IsBasemapLayer
Layer is considered a 'basemap' layer, and certain properties of the layer should be ignored when cal...
@ ReadLayerMetadata
Provider can read layer metadata from data store. See QgsDataProvider::layerMetadata()
@ AlwaysUseTileMatrixSetFromProvider
Vector tile layer must always use the tile matrix set from the data provider, and should never store,...
QFlags< SelectionFlag > SelectionFlags
Flags which control feature selection behavior.
Definition: qgis.h:1394
BlendMode
Blending modes defining the available composition modes that can be used when painting.
Definition: qgis.h:4041
@ Polygon
Polygons.
@ Unknown
Unknown types.
@ Null
No geometry.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ Millimeters
Millimeters.
@ ToggleSelection
Enables a "toggle" selection mode, where previously selected matching features will be deselected and...
@ SingleFeatureSelection
Select only a single feature, picking the "best" match for the selection geometry.
QFlags< MapLayerProperty > MapLayerProperties
Map layer properties.
Definition: qgis.h:1824
SelectGeometryRelationship
Geometry relationship test to apply for selecting features.
Definition: qgis.h:1372
@ Within
Select where features are within the reference geometry.
@ Intersect
Select where features intersect the reference geometry.
SelectBehavior
Specifies how a selection should be applied.
Definition: qgis.h:1358
@ SetSelection
Set selection, removing any existing selection.
@ AddToSelection
Add selection to current selection.
@ IntersectSelection
Modify current selection to include only select features which match.
@ RemoveFromSelection
Remove from current selection.
A vector of attributes.
Definition: qgsattributes.h:59
A thread safe class for performing blocking (sync) network requests, with full support for QGIS proxy...
ErrorCode get(QNetworkRequest &request, bool forceRefresh=false, QgsFeedback *feedback=nullptr)
Performs a "get" operation on the specified request.
@ NetworkError
A network error occurred.
@ ServerExceptionError
An exception was raised by the server.
@ NoError
No error was encountered.
@ TimeoutError
Timeout was reached before a reply was received.
QgsNetworkReplyContent reply() const
Returns the content of the network reply, after a get(), post(), head() or put() request has been mad...
This class represents a coordinate reference system (CRS).
Contains information about the context in which a coordinate transform is executed.
Class for doing transforms between two map coordinate systems.
Abstract base class for spatial data provider implementations.
QFlags< ReadFlag > ReadFlags
Class for storing the component parts of a RDBMS data source URI (e.g.
void setEncodedUri(const QByteArray &uri)
Sets the complete encoded uri.
QString param(const QString &key) const
Returns a generic parameter value corresponding to the specified key.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsAttributes attributes
Definition: qgsfeature.h:65
QgsFields fields
Definition: qgsfeature.h:66
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:160
void setFields(const QgsFields &fields, bool initAttributes=false)
Assigns a field map with the feature to allow attribute access by attribute name.
Definition: qgsfeature.cpp:195
QgsGeometry geometry
Definition: qgsfeature.h:67
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:216
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:53
Container of fields for a vector layer.
Definition: qgsfields.h:45
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
Definition: qgsfields.cpp:59
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:162
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Qgis::GeometryType type
Definition: qgsgeometry.h:165
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
bool isGeosEqual(const QgsGeometry &) const
Compares the geometry with another geometry using GEOS.
static QVariant parseJson(const std::string &jsonString)
Converts JSON jsonString to a QVariant, in case of parsing error an invalid QVariant is returned and ...
Class for metadata formatter.
Context for a MapBox GL style conversion operation.
void setTargetUnit(Qgis::RenderUnit targetUnit)
Sets the target unit type.
void setPixelSizeConversionFactor(double sizeConversionFactor)
Sets the pixel size conversion factor, used to scale the original pixel sizes when converting styles.
void setSprites(const QImage &image, const QVariantMap &definitions)
Sets the sprite image and definitions JSON to use during conversion.
Handles conversion of MapBox GL styles to QGIS vector tile renderers and labeling settings.
QgsVectorTileRenderer * renderer() const
Returns a new instance of a vector tile renderer representing the converted style,...
QgsVectorTileLabeling * labeling() const
Returns a new instance of a vector tile labeling representing the converted style,...
Result convert(const QVariantMap &style, QgsMapBoxGlStyleConversionContext *context=nullptr)
Converts a JSON style map, and returns the resultant status of the conversion.
QList< QgsMapLayer * > createSubLayers() const
Returns a list of new map layers corresponding to sublayers of the style, e.g.
@ Success
Conversion was successful.
QString errorMessage() const
Returns a descriptive error message if an error was encountered during the style conversion,...
QStringList warnings() const
Returns a list of user-friendly warnings generated during the conversion, e.g.
static QString typeToString(Qgis::LayerType type)
Converts a map layer type to a string value.
Base class for utility classes that encapsulate information necessary for rendering of map layers.
Base class for all map layer types.
Definition: qgsmaplayer.h:75
QString name
Definition: qgsmaplayer.h:78
void readStyleManager(const QDomNode &layerNode)
Read style manager's configuration (if any). To be called by subclasses.
bool isInScaleRange(double scale) const
Tests whether the layer should be visible at the specified scale.
void writeStyleManager(QDomNode &layerNode, QDomDocument &doc) const
Write style manager's configuration (if exists). To be called by subclasses.
QString source() const
Returns the source for the layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
QgsMapLayer::LayerFlags flags() const
Returns the flags for this layer.
virtual QString loadDefaultStyle(bool &resultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:2124
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
QString crsHtmlMetadata() const
Returns a HTML fragment containing the layer's CRS metadata, for use in the htmlMetadata() method.
QgsLayerMetadata metadata
Definition: qgsmaplayer.h:80
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
virtual void setOpacity(double opacity)
Sets the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1....
virtual void setMetadata(const QgsLayerMetadata &metadata)
Sets the layer's metadata store.
QFlags< StyleCategory > StyleCategories
Definition: qgsmaplayer.h:188
QString mProviderKey
Data provider key (name of the data provider)
Definition: qgsmaplayer.h:2162
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
virtual QgsError error() const
Gets current status error.
virtual QStringList subLayers() const
Returns the sublayers of this layer.
virtual void setExtent(const QgsRectangle &rect)
Sets the extent.
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:2121
virtual QString loadDefaultMetadata(bool &resultFlag)
Retrieve the default metadata for this layer if one exists (either as a .qmd file on disk or as a rec...
void setValid(bool valid)
Sets whether layer is valid or not.
void readCommonStyle(const QDomElement &layerElement, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories)
Read style data common to all layer types.
double opacity
Definition: qgsmaplayer.h:84
@ Symbology
Symbology.
Definition: qgsmaplayer.h:167
@ Rendering
Rendering: scale visibility, simplify method, opacity.
Definition: qgsmaplayer.h:176
@ Labeling
Labeling.
Definition: qgsmaplayer.h:169
QString generalHtmlMetadata() const
Returns an HTML fragment containing general metadata information, for use in the htmlMetadata() metho...
void writeCommonStyle(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const
Write style data common to all layer types.
void invalidateWgs84Extent()
Invalidates the WGS84 extent.
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
Encapsulates a network reply within a container which is inexpensive to copy and safe to pass between...
QByteArray content() const
Returns the reply content.
static Qgis::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a Qgis::BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:81
static QPainter::CompositionMode getCompositionMode(Qgis::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a Qgis::BlendMode.
Definition: qgspainting.cpp:21
A class to represent a 2D point.
Definition: qgspointxy.h:60
double y
Definition: qgspointxy.h:64
Q_GADGET double x
Definition: qgspointxy.h:63
QString absoluteToRelativeUri(const QString &providerKey, const QString &uri, const QgsReadWriteContext &context) const
Converts absolute path(s) to relative path(s) in the given provider-specific URI.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString relativeToAbsoluteUri(const QString &providerKey, const QString &uri, const QgsReadWriteContext &context) const
Converts relative path(s) to absolute path(s) in the given provider-specific URI.
The class is used as a container of context for various read/write operations on other objects.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
Definition: qgsrectangle.h:385
Contains information about the context of a rendering operation.
Encapsulates the context of a layer selection operation.
double scale() const
Returns the map scale at which the selection should occur.
virtual QDomElement writeXml(QDomDocument &document, const QgsReadWriteContext &context) const
Writes the set to an XML element.
Definition: qgstiles.cpp:391
QgsCoordinateReferenceSystem crs() const
Returns the coordinate reference system associated with the tiles.
Definition: qgstiles.cpp:218
QVector< QgsTileXYZ > tilesInRange(QgsTileRange range, int zoomLevel) const
Returns a list of tiles in the given tile range.
Definition: qgstiles.cpp:428
QgsTileMatrix tileMatrix(int zoom) const
Returns the tile matrix corresponding to the specified zoom.
Definition: qgstiles.cpp:156
virtual bool readXml(const QDomElement &element, QgsReadWriteContext &context)
Reads the set from an XML element.
Definition: qgstiles.cpp:342
int scaleToZoomLevel(double scale, bool clamp=true) const
Finds the best fitting (integer) zoom level given a map scale denominator.
Definition: qgstiles.cpp:283
Defines a matrix of tiles for a single zoom level: it is defined by its size (width *.
Definition: qgstiles.h:134
QgsTileRange tileRangeFromExtent(const QgsRectangle &mExtent) const
Returns tile range that fully covers the given extent.
Definition: qgstiles.cpp:97
Range of tiles in a tile matrix to be rendered.
Definition: qgstiles.h:97
Stores coordinates of a tile in a tile matrix set.
Definition: qgstiles.h:38
Basic labeling configuration for vector tile layers.
The default vector tile renderer implementation.
static QList< QgsVectorTileBasicRendererStyle > simpleStyleWithRandomColors()
Returns a list of styles to render all layers, using random colors.
Base class for vector tile layer data providers.
Base class for labeling configuration classes for vector tile layers.
virtual void readXml(const QDomElement &elem, const QgsReadWriteContext &context)=0
Reads labeling properties from given XML element.
This class provides map rendering functionality for vector tile layers.
Implements a map layer that is dedicated to rendering of vector tiles.
QgsVectorTileLayer(const QString &path=QString(), const QString &baseName=QString(), const QgsVectorTileLayer::LayerOptions &options=QgsVectorTileLayer::LayerOptions())
Constructs a new vector tile layer.
bool readXml(const QDomNode &layerNode, QgsReadWriteContext &context) override
Called by readLayerXML(), used by children to read state specific to them from project files.
bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const override
Write the style for the layer into the document provided.
void setRenderer(QgsVectorTileRenderer *r)
Sets renderer for the map layer.
bool loadDefaultStyleAndSubLayers(QString &error, QStringList &warnings, QList< QgsMapLayer * > &subLayers)
Loads the default style for the layer, and returns true if the style was successfully loaded.
QString decodedSource(const QString &source, const QString &provider, const QgsReadWriteContext &context) const FINAL
Called by readLayerXML(), used by derived classes to decode provider's specific data source from proj...
QString sourceType() const
Returns type of the data source.
void setLabelsEnabled(bool enabled)
Sets whether labels should be enabled for the layer.
bool writeXml(QDomNode &layerNode, QDomDocument &doc, const QgsReadWriteContext &context) const override
Called by writeLayerXML(), used by children to write state specific to them to project files.
void selectByGeometry(const QgsGeometry &geometry, const QgsSelectionContext &context, Qgis::SelectBehavior behavior=Qgis::SelectBehavior::SetSelection, Qgis::SelectGeometryRelationship relationship=Qgis::SelectGeometryRelationship::Intersect, Qgis::SelectionFlags flags=Qgis::SelectionFlags(), QgsRenderContext *renderContext=nullptr)
Selects features found within the search geometry (in layer's coordinates).
bool labelsEnabled() const
Returns whether the layer contains labels which are enabled and should be drawn.
void setLabeling(QgsVectorTileLabeling *labeling)
Sets labeling for the map layer.
QList< QgsFeature > selectedFeatures() const
Returns the list of features currently selected in the layer.
QgsVectorTileLabeling * labeling() const
Returns currently assigned labeling.
~QgsVectorTileLayer() override
bool readSymbology(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) override
Read the symbology for the current layer from the DOM node supplied.
int sourceMinZoom() const
Returns minimum zoom level at which source has any valid tiles (negative = unconstrained)
QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext) override
Returns new instance of QgsMapLayerRenderer that will be used for rendering of given context.
QString loadDefaultStyle(bool &resultFlag) override
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
Qgis::MapLayerProperties properties() const override
Returns the map layer properties of this layer.
QString htmlMetadata() const override
Obtain a formatted HTML string containing assorted metadata for this layer.
QString encodedSource(const QString &source, const QgsReadWriteContext &context) const FINAL
Called by writeLayerXML(), used by derived classes to encode provider's specific data source to proje...
int sourceMaxZoom() const
Returns maximum zoom level at which source has any valid tiles (negative = unconstrained)
QgsVectorTileRenderer * renderer() const
Returns currently assigned renderer.
void removeSelection()
Clear selection.
QgsDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
QString loadDefaultMetadata(bool &resultFlag) override
Retrieve the default metadata for this layer if one exists (either as a .qmd file on disk or as a rec...
QString sourcePath() const
Returns URL/path of the data source (syntax different to each data source type)
QgsVectorTileRawData getRawTile(QgsTileXYZ tileID)
Fetches raw tile data for the give tile coordinates.
void setTransformContext(const QgsCoordinateTransformContext &transformContext) override
Sets the coordinate transform context to transformContext.
QgsVectorTileMatrixSet & tileMatrixSet()
Returns the vector tile matrix set.
void selectionChanged()
Emitted whenever the selected features in the layer are changed.
QgsVectorTileLayer * clone() const override
Returns a new instance equivalent to this one except for the id which is still unique.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
This class is responsible for decoding raw tile data written with Mapbox Vector Tiles encoding.
QStringList layerFieldNames(const QString &layerName) const
Returns a list of all field names in a tile. It can only be called after a successful decode()
QStringList layers() const
Returns a list of sub-layer names in a tile. It can only be called after a successful decode()
bool decode(const QgsVectorTileRawData &rawTileData)
Tries to decode raw tile data, returns true on success.
QgsVectorTileFeatures layerFeatures(const QMap< QString, QgsFields > &perLayerFields, const QgsCoordinateTransform &ct, const QSet< QString > *layerSubset=nullptr) const
Returns decoded features grouped by sub-layers.
Keeps track of raw tile data that need to be decoded.
QByteArray data
Raw tile data.
Abstract base class for all vector tile renderer implementations.
virtual void readXml(const QDomElement &elem, const QgsReadWriteContext &context)=0
Reads renderer's properties from given XML element.
static QgsFields makeQgisFields(const QSet< QString > &flds)
Returns QgsFields instance based on the set of field names.
static void loadSprites(const QVariantMap &styleDefinition, QgsMapBoxGlStyleConversionContext &context, const QString &styleUrl=QString())
Downloads the sprite image and sets it to the conversion context.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugError(str)
Definition: qgslogger.h:38
#define QgsSetRequestInitiatorClass(request, _class)
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS_NON_FATAL
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS
QMap< QString, QVector< QgsFeature > > QgsVectorTileFeatures
Features of a vector tile, grouped by sub-layer names (key of the map)
Setting options for creating vector data providers.
Setting options for loading vector tile layers.