39#include <QWaitCondition>
41using namespace Qt::StringLiterals;
48 int tile2tms(
const int y,
const int zoom )
50 double n = std::pow( 2, zoom );
51 return (
int ) std::floor( n - y - 1 );
55void MetaTile::addTile(
const int row,
const int col, Tile tileToAdd,
const QgsRectangle &extent )
57 tiles.insert( QPair<int, int>( row, col ), tileToAdd );
66 mExtent.combineExtentWith( extent );
72 QList<MetaTile> getMetatiles(
78 const QList<QgsTileExtentMaxZoomRegion> &maxZoomRegions,
85 const long long matrixWidth = targetZoomMatrix.
matrixWidth();
86 const long long matrixHeight = targetZoomMatrix.
matrixHeight();
89 const double tileWidthUnits = tileMatrixSetExtent.
width() / matrixWidth;
90 const double tileHeightUnits = tileMatrixSetExtent.
height() / matrixHeight;
92 int minX =
static_cast<int>( std::floor( ( contentsExtent.
xMinimum() - tileMatrixSetExtent.
xMinimum() ) / tileWidthUnits ) );
93 int maxX =
static_cast<int>( std::ceil( ( contentsExtent.
xMaximum() - tileMatrixSetExtent.
xMinimum() ) / tileWidthUnits ) - 1 );
94 int minY =
static_cast<int>( std::floor( ( tileMatrixSetExtent.
yMaximum() - contentsExtent.
yMaximum() ) / tileHeightUnits ) );
95 int maxY =
static_cast<int>( std::ceil( ( tileMatrixSetExtent.
yMaximum() - contentsExtent.
yMinimum() ) / tileHeightUnits ) - 1 );
97 minX = std::clamp<int>( minX, 0,
static_cast<int>( matrixWidth - 1 ) );
98 maxX = std::clamp<int>( maxX, 0,
static_cast<int>( matrixWidth - 1 ) );
99 minY = std::clamp<int>( minY, 0,
static_cast<int>( matrixHeight - 1 ) );
100 maxY = std::clamp<int>( maxY, 0,
static_cast<int>( matrixHeight - 1 ) );
103 const int totalMetaColumns =
static_cast<int>( std::ceil(
static_cast<double>( maxX - minX + 1 ) / metaTileSize ) );
104 const int totalMetaRows =
static_cast<int>( std::ceil(
static_cast<double>( maxY - minY + 1 ) / metaTileSize ) );
106 QList<MetaTile> metaTiles;
107 bool hasWarnedForManyTiles =
false;
108 for (
int metaTileColumn = 0; metaTileColumn < totalMetaColumns; ++metaTileColumn )
113 const int startI = metaTileColumn * metaTileSize;
114 const int endI = std::min( startI + metaTileSize - 1, maxX - minX );
115 const int startX = minX + startI;
116 const int endX = minX + endI;
118 for (
int metaTileRow = 0; metaTileRow < totalMetaRows; ++metaTileRow )
123 const int startJ = metaTileRow * metaTileSize;
124 const int endJ = std::min( startJ + metaTileSize - 1, maxY - minY );
125 const int startY = minY + startJ;
126 const int endY = minY + endJ;
128 const double metaTileMinX = tileMatrixSetExtent.
xMinimum() + startX * tileWidthUnits;
129 const double metaTileMaxX = tileMatrixSetExtent.
xMinimum() + ( endX + 1 ) * tileWidthUnits;
130 const double metaTileMaxY = tileMatrixSetExtent.
yMaximum() - startY * tileHeightUnits;
131 const double metaTileMinY = tileMatrixSetExtent.
yMaximum() - ( endY + 1 ) * tileHeightUnits;
132 const QgsRectangle metaTileExtent( metaTileMinX, metaTileMaxY, metaTileMaxX, metaTileMinY );
135 if ( !maxZoomRegions.isEmpty() )
139 if ( metaTileMaxZoom < zoom )
148 for (
int x = startX, i = startI; x <= endX; ++x, ++i )
150 for (
int y = startY, j = startJ; y <= endY; ++y, ++j )
152 const double tileMinX = tileMatrixSetExtent.
xMinimum() + x * tileWidthUnits;
153 const double tileMaxX = tileMinX + tileWidthUnits;
154 const double tileMaxY = tileMatrixSetExtent.
yMaximum() - y * tileHeightUnits;
155 const double tileMinY = tileMaxY - tileHeightUnits;
157 const QgsRectangle tileExtent( tileMinX, tileMinY, tileMaxX, tileMaxY );
159 metaTile.addTile( i % metaTileSize, j % metaTileSize, Tile( x, y, zoom ), tileExtent );
164 if ( !metaTile.tiles.isEmpty() )
166 metaTiles.append( metaTile );
167 constexpr qsizetype MAX_METATILES_BEFORE_WARNING = 1'000'000;
168 if ( !hasWarnedForManyTiles && metaTiles.size() >= MAX_METATILES_BEFORE_WARNING )
171 QObject::tr(
"A large number of tiles (more than %1 metatiles) will be created for zoom level %2. This will take some time. Please check the tile matrix settings and extent to confirm these parameters are correct." )
172 .arg( MAX_METATILES_BEFORE_WARNING )
175 hasWarnedForManyTiles =
true;
194template<
typename T>
class PendingTilesToWriteQueue
200 void push(
const QList<T> &tiles )
202 if ( tiles.isEmpty() )
205 QMutexLocker locker( &mMutex );
206 for (
const T &tile : tiles )
208 mQueue.enqueue( tile );
220 bool popBatch( QList<T> &batch,
int maxBatchSize,
unsigned long timeoutMs = 500 )
222 QMutexLocker locker( &mMutex );
225 while ( mQueue.isEmpty() && !mFinished )
227 mNotEmpty.wait( &mMutex );
230 if ( mQueue.isEmpty() )
234 while ( mQueue.size() < maxBatchSize && !mFinished )
236 if ( !mNotEmpty.wait( &mMutex, timeoutMs ) )
243 while ( !mQueue.isEmpty() && batch.size() < maxBatchSize )
245 batch.append( mQueue.dequeue() );
255 QMutexLocker locker( &mMutex );
262 mutable QMutex mMutex;
263 QWaitCondition mNotEmpty;
264 bool mFinished =
false;
271QString QgsXyzTilesBaseAlgorithm::group()
const
273 return QObject::tr(
"Raster tools" );
276QString QgsXyzTilesBaseAlgorithm::groupId()
const
278 return u
"rastertools"_s;
286void QgsXyzTilesBaseAlgorithm::createCommonParameters()
288 auto extentParam = std::make_unique<QgsProcessingParameterExtent>( u
"EXTENT"_s, QObject::tr(
"Extent" ) );
289 extentParam->setHelp( QObject::tr(
"Spatial extent of the area for tile generation." ) );
290 addParameter( extentParam.release() );
293 minZoomParam->setHelp(
295 "Minimum zoom level for generated tiles (0–25). Lower zoom levels cover broader geographic areas "
296 "at lower spatial resolution. Must be less than or equal to the maximum zoom level."
299 addParameter( minZoomParam.release() );
302 maxZoomParam->setHelp(
304 "Maximum zoom level for generated tiles (0–25). Higher zoom levels capture finer map details "
305 "and higher resolution, but exponentially increase total tile count, storage requirements, and rendering time. "
306 "Must be greater than or equal to the minimum zoom level."
309 addParameter( maxZoomParam.release() );
312 dpiParam->setHelp( QObject::tr(
"Output resolution in DPI for rendered map content." ) );
314 addParameter( dpiParam.release() );
316 auto bgColorParam = std::make_unique<QgsProcessingParameterColor>( u
"BACKGROUND_COLOR"_s, QObject::tr(
"Background color" ), QColor( Qt::transparent ),
true,
true );
317 bgColorParam->setHelp( QObject::tr(
"Background color used when rendering map tiles." ) );
318 addParameter( bgColorParam.release() );
320 auto antialiasParam = std::make_unique<QgsProcessingParameterBoolean>( u
"ANTIALIAS"_s, QObject::tr(
"Enable antialiasing" ),
true );
321 antialiasParam->setHelp( QObject::tr(
"Controls whether antialiasing is applied during tile rendering." ) );
323 addParameter( antialiasParam.release() );
325 auto tileFormatParam = std::make_unique<QgsProcessingParameterEnum>( u
"TILE_FORMAT"_s, QObject::tr(
"Tile format" ), QStringList { u
"PNG"_s, u
"JPG"_s, u
"WEBP"_s },
false, 0 );
326 tileFormatParam->setHelp( QObject::tr(
"Output image format for the rendered tiles." ) );
327 addParameter( tileFormatParam.release() );
330 qualityParam->setHelp( QObject::tr(
"Image quality percentage used when tile format is set to JPG (1–100)." ) );
332 addParameter( qualityParam.release() );
335 metaTileSizeParam->setHelp( QObject::tr(
"Size of metatiles (in tile units) used during rendering." ) );
337 addParameter( metaTileSizeParam.release() );
339 auto skipEmptyTilesParam = std::make_unique<QgsProcessingParameterBoolean>( u
"SKIP_EMPTY_TILES"_s, QObject::tr(
"Skip empty tiles" ),
false );
340 skipEmptyTilesParam->setHelp( QObject::tr(
"If set, completely empty tiles will be skipped." ) );
342 addParameter( skipEmptyTilesParam.release() );
344 auto tileExtentMaxZoomParam = std::make_unique<QgsProcessingParameterTileExtentMaxZoomList>( u
"TILE_MAX_ZOOM_EXTENTS"_s, QObject::tr(
"Maximum zoom extents" ), QVariant(),
true );
345 tileExtentMaxZoomParam->setHelp( QObject::tr(
"Allows overriding the maximum zoom level for specific geographic regions, so that more detailed tiles can be created for important areas." ) );
347 addParameter( tileExtentMaxZoomParam.release() );
350void QgsXyzTilesBaseAlgorithm::createTileMatrixParameters()
352 auto crsParam = std::make_unique<QgsProcessingParameterCrs>( u
"TARGET_CRS"_s, QObject::tr(
"Target CRS" ), QVariant( u
"EPSG:3857"_s ) );
354 crsParam->setHelp( QObject::tr(
"Coordinate reference system used for the output tile matrix set." ) );
355 addParameter( crsParam.release() );
357 auto z0ExtentParam = std::make_unique<QgsProcessingParameterExtent>( u
"Z0_EXTENT"_s, QObject::tr(
"Zoom 0 extent" ) );
359 z0ExtentParam->setHelp(
361 "Extent of zoom level 0 in target CRS coordinates. Required when target CRS is not EPSG:3857. If the target CRS is EPSG:3857 then this parameter will be ignored and a standard Web Mercator "
362 "tile matrix will be used instead."
365 addParameter( z0ExtentParam.release() );
369 z0WidthParam->setHelp( QObject::tr(
"Number of tile columns at zoom level 0 (matrix width)." ) );
370 addParameter( z0WidthParam.release() );
374 z0HeightParam->setHelp( QObject::tr(
"Number of tile rows at zoom level 0 (matrix height)." ) );
375 addParameter( z0HeightParam.release() );
380 Q_UNUSED( feedback );
387 QSet<QString> visibleLayers;
390 if ( layer->isVisible() )
392 visibleLayers << layer->layer()->id();
399 if ( visibleLayers.contains( layer->id() ) )
402 clonedLayer->moveToThread(
nullptr );
403 mLayers.emplace_back( std::unique_ptr< QgsMapLayer >( clonedLayer ) );
407 if ( parameters.contains( u
"TILE_WIDTH"_s ) )
409 mTileWidth = parameterAsInt( parameters, u
"TILE_WIDTH"_s, context );
412 if ( parameters.contains( u
"TILE_HEIGHT"_s ) )
414 mTileHeight = parameterAsInt( parameters, u
"TILE_HEIGHT"_s, context );
417 if ( parameters.contains( u
"TARGET_CRS"_s ) )
419 mTargetCrs = parameterAsCrs( parameters, u
"TARGET_CRS"_s, context );
426 int z0MatrixWidth = 1;
427 if ( parameters.contains( u
"Z0_MATRIX_WIDTH"_s ) )
429 z0MatrixWidth = parameterAsInt( parameters, u
"Z0_MATRIX_WIDTH"_s, context );
432 int z0MatrixHeight = 1;
433 if ( parameters.contains( u
"Z0_MATRIX_HEIGHT"_s ) )
435 z0MatrixHeight = parameterAsInt( parameters, u
"Z0_MATRIX_HEIGHT"_s, context );
438 mTileGenerationRegion = parameterAsExtent( parameters, u
"EXTENT"_s, context, mTargetCrs );
440 const QgsRectangle userZ0Extent = parameterAsExtent( parameters, u
"Z0_EXTENT"_s, context, mTargetCrs );
442 if ( mTargetCrs.authid() ==
"EPSG:3857"_L1 )
446 feedback->
pushWarning( QObject::tr(
"Tiles are being generated in EPSG:3857, so a standard Web Mercator tile matrix will be used. The manual zoom 0 extent will be ignored." ) );
448 z0Extent =
QgsRectangle( -MERC_MAX, -MERC_MAX, MERC_MAX, MERC_MAX );
454 throw QgsProcessingException( QObject::tr(
"Zoom 0 extent must be specified when using a custom target CRS (%1)" ).arg( mTargetCrs.userFriendlyIdentifier() ) );
456 z0Extent = userZ0Extent;
457 const double rawPixelXSize = z0Extent.
width() / (
static_cast<double>( z0MatrixWidth ) * mTileWidth );
458 const double rawPixelYSize = z0Extent.
height() / (
static_cast<double>( z0MatrixHeight ) * mTileHeight );
463 const double isotropicPixelSize = std::max( rawPixelXSize, rawPixelYSize );
464 const double requiredWidth = isotropicPixelSize * z0MatrixWidth * mTileWidth;
465 const double requiredHeight = isotropicPixelSize * z0MatrixHeight * mTileHeight;
468 z0Extent =
QgsRectangle( center.
x() - requiredWidth / 2.0, center.
y() - requiredHeight / 2.0, center.
x() + requiredWidth / 2.0, center.
y() + requiredHeight / 2.0 );
469 feedback->
pushWarning( QObject::tr(
"The manual zoom 0 extent does not result in square pixels. This has been automatically adjusted to %1." ).arg( z0Extent.
toString() ) );
486 mMinZoom = parameterAsInt( parameters, u
"ZOOM_MIN"_s, context );
487 mMaxZoom = parameterAsInt( parameters, u
"ZOOM_MAX"_s, context );
488 if ( mMaxZoom < mMinZoom )
490 throw QgsProcessingException( QObject::tr(
"Maximum zoom (%1) must be ≥ minimum zoom (%2)" ).arg( mMaxZoom ).arg( mMinZoom ) );
493 mMaxZoomLimitIncludingOverrides = mMaxZoom;
494 const QList<QgsTileExtentMaxZoomRegion> rawRegions
495 = qgis::down_cast< const QgsProcessingParameterTileExtentMaxZoomList *>( parameterDefinition( u
"TILE_MAX_ZOOM_EXTENTS"_s ) )->parameterAsRegionList( parameters.value( u
"TILE_MAX_ZOOM_EXTENTS"_s ), context );
496 if ( !rawRegions.isEmpty() )
505 ct.setBallparkTransformsAreAppropriate(
true );
507 mMaxZoomRegions.append( targetRegion );
508 mMaxZoomLimitIncludingOverrides = std::max( mMaxZoomLimitIncludingOverrides, region.maxZoom );
517 mDpi = parameterAsInt( parameters, u
"DPI"_s, context );
518 mBackgroundColor = parameterAsColor( parameters, u
"BACKGROUND_COLOR"_s, context );
519 mAntialias = parameterAsBool( parameters, u
"ANTIALIAS"_s, context );
520 mSkipEmptyTiles = parameterAsBool( parameters, u
"SKIP_EMPTY_TILES"_s, context );
521 switch ( parameterAsEnum( parameters, u
"TILE_FORMAT"_s, context ) )
524 mTileFormat = u
"PNG"_s;
527 mTileFormat = u
"JPG"_s;
530 mTileFormat = u
"WEBP"_s;
533 mTileFormat = u
"PNG"_s;
537 mJpgQuality = mTileFormat !=
"PNG"_L1 ? parameterAsInt( parameters, u
"QUALITY"_s, context ) : -1;
538 mMetaTileSize = parameterAsInt( parameters, u
"METATILESIZE"_s, context );
543 if ( ( mTileFormat !=
"PNG"_L1 && mTileFormat !=
"WEBP"_L1 ) && mBackgroundColor.alpha() != 255 )
546 QObject::tr(
"A semi-transparent background color was set, but the JPG format only supports fully opaque colors. The background color setting will be ignored. Please use a fully opaque background color instead." )
559 auto it = mLayers.begin();
560 while ( it != mLayers.end() )
566 QObject::tr(
"Layer %1 will be skipped as the algorithm leads to bulk downloading behavior which is prohibited by the %2OpenStreetMap Foundation tile usage policy%3" )
567 .arg( it->get()->name(), u
"<a href=\"https://operations.osmfoundation.org/policies/tiles/\">"_s, u
"</a>"_s ),
568 QObject::tr(
"Layer %1 will be skipped as the algorithm leads to bulk downloading behavior which is prohibited by the %2OpenStreetMap Foundation tile usage policy%3" )
569 .arg( it->get()->name(), QString(), QString() )
571 it = mLayers.erase( it );
581std::optional< QgsMapSettings > QgsXyzTilesBaseAlgorithm::mapSettingsForTile(
const MetaTile &metaTile )
const
590 QList< QgsMapLayer * > layers;
591 for (
const std::unique_ptr< QgsMapLayer > &layer : std::as_const( mLayers ) )
593 layers << layer.get();
603 if ( mTileFormat ==
"PNG"_L1 || mTileFormat ==
"WEBP"_L1 || mBackgroundColor.alpha() == 255 )
607 QSize size( mTileWidth * metaTile.rows, mTileHeight * metaTile.cols );
623 while ( mRendererJobs.size() < mThreadsNumber && !mMetaTiles.empty() )
628 MetaTile metaTile = mMetaTiles.takeFirst();
629 const std::optional<QgsMapSettings> settings = mapSettingsForTile( metaTile );
630 if ( !settings.has_value() )
632 mProcessedMetaTiles++;
633 feedback->
setProgress( 100.0 * mProcessedMetaTiles / mTotalMetaTiles );
638 mRendererJobs.insert( job, metaTile );
641 const MetaTile tile = mRendererJobs.take( job );
645 mProcessedMetaTiles++;
646 feedback->
setProgress( 100.0 * mProcessedMetaTiles / mTotalMetaTiles );
648 processMetaTile( tile, renderedImage, feedback );
652 startJobs( feedback );
654 checkPipelineFinished( feedback );
660 checkPipelineFinished( feedback );
665 if ( feedback->
isCanceled() || ( mMetaTiles.isEmpty() && mRendererJobs.isEmpty() && mActivePostProcessingTasks == 0 ) )
678QString QgsXyzTilesDirectoryAlgorithm::name()
const
680 return u
"tilesxyzdirectory"_s;
683QString QgsXyzTilesDirectoryAlgorithm::displayName()
const
685 return QObject::tr(
"Generate XYZ tiles (Directory)" );
688QStringList QgsXyzTilesDirectoryAlgorithm::tags()
const
690 return QObject::tr(
"tiles,xyz,tms,directory" ).split(
',' );
693QString QgsXyzTilesDirectoryAlgorithm::shortHelpString()
const
696 "This algorithm generates XYZ raster tiles from the current project and saves them as individual image files in a structured directory hierarchy ({z}/{x}/{y}.png or .jpg).\n\n"
697 "All visible map layers from the project will be rendered into tiles across the specified extent and zoom range.\n\n"
698 "Optionally, a standalone Leaflet HTML file can be generated for instant web previewing of the tiles."
702QString QgsXyzTilesDirectoryAlgorithm::shortDescription()
const
704 return QObject::tr(
"Generates XYZ tiles from the project as a structured directory hierarchy ({z}/{x}/{y}.png/jpg)." );
707QgsXyzTilesDirectoryAlgorithm *QgsXyzTilesDirectoryAlgorithm::createInstance()
const
709 return new QgsXyzTilesDirectoryAlgorithm();
712void QgsXyzTilesDirectoryAlgorithm::initAlgorithm(
const QVariantMap & )
714 createCommonParameters();
715 createTileMatrixParameters();
718 tileWidthParam->setHelp( QObject::tr(
"Width of each tile image in pixels." ) );
719 addParameter( tileWidthParam.release() );
722 tileHeightParam->setHelp( QObject::tr(
"Height of each tile image in pixels." ) );
723 addParameter( tileHeightParam.release() );
725 auto tmsParam = std::make_unique<QgsProcessingParameterBoolean>( u
"TMS_CONVENTION"_s, QObject::tr(
"Use inverted tile Y axis (TMS convention)" ),
false );
726 tmsParam->setHelp( QObject::tr(
"Inverts the Y tile coordinate naming convention to follow TMS format." ) );
727 addParameter( tmsParam.release() );
729 auto titleParam = std::make_unique<QgsProcessingParameterString>( u
"HTML_TITLE"_s, QObject::tr(
"Leaflet HTML output title" ), QVariant(),
false,
true );
731 titleParam->setHelp( QObject::tr(
"Title displayed in the generated Leaflet HTML web viewer." ) );
732 addParameter( titleParam.release() );
734 auto attributionParam = std::make_unique<QgsProcessingParameterString>( u
"HTML_ATTRIBUTION"_s, QObject::tr(
"Leaflet HTML output attribution" ), QVariant(),
false,
true );
736 attributionParam->setHelp( QObject::tr(
"Attribution text displayed in the generated Leaflet HTML web viewer." ) );
737 addParameter( attributionParam.release() );
739 auto osmParam = std::make_unique<QgsProcessingParameterBoolean>( u
"HTML_OSM"_s, QObject::tr(
"Include OpenStreetMap basemap in Leaflet HTML output" ),
false );
741 osmParam->setHelp( QObject::tr(
"Includes an OpenStreetMap background layer in the generated Leaflet HTML viewer." ) );
742 addParameter( osmParam.release() );
744 auto outputDirParam = std::make_unique<QgsProcessingParameterFolderDestination>( u
"OUTPUT_DIRECTORY"_s, QObject::tr(
"Output directory" ) );
745 outputDirParam->setHelp( QObject::tr(
"Destination folder where the generated directory structure and tile files will be stored." ) );
746 addParameter( outputDirParam.release() );
748 auto outputHtmlParam = std::make_unique<QgsProcessingParameterFileDestination>( u
"OUTPUT_HTML"_s, QObject::tr(
"Output HTML (Leaflet)" ), QObject::tr(
"HTML files (*.html)" ), QVariant(),
true );
749 outputHtmlParam->setHelp( QObject::tr(
"Destination file path for the optional Leaflet HTML web map preview." ) );
750 addParameter( outputHtmlParam.release() );
757 QGS_MARK_ALGORITHM_SOURCE
759 const bool tms = parameterAsBoolean( parameters, u
"TMS_CONVENTION"_s, context );
760 const QString title = parameterAsString( parameters, u
"HTML_TITLE"_s, context );
761 const QString attribution = parameterAsString( parameters, u
"HTML_ATTRIBUTION"_s, context );
762 const bool useOsm = parameterAsBoolean( parameters, u
"HTML_OSM"_s, context );
763 QString outputDir = parameterAsString( parameters, u
"OUTPUT_DIRECTORY"_s, context );
764 const QString outputHtml = parameterAsString( parameters, u
"OUTPUT_HTML"_s, context );
766 mOutputDir = outputDir;
769 long long totalTiles = 0;
771 for (
int z = mMinZoom; z <= mMaxZoomLimitIncludingOverrides; z++ )
779 long long tileCount = 0;
780 mMetaTiles += getMetatiles( mZ0matrix, mTileGenerationRegion, z, tileCount, mMetaTileSize, mMaxZoomRegions, mMaxZoom, feedback );
781 feedback->
pushInfo( QObject::tr(
"%1 metatiles (%2 tiles) will be created for zoom level %3" ).arg( mMetaTiles.size() - mTotalMetaTiles ).arg( tileCount ).arg( z ) );
782 mTotalMetaTiles = mMetaTiles.size();
783 totalTiles += tileCount;
785 if ( mTotalMetaTiles == 0 )
787 throw QgsProcessingException( QObject::tr(
"No metatiles will be created -- please check the extent and zoom limits" ) );
790 feedback->
pushInfo( QObject::tr(
"A total of %1 metatiles (%2 tiles) will be created" ).arg( mTotalMetaTiles ).arg( totalTiles ) );
797 checkLayersUsagePolicy( feedback );
799 for (
const std::unique_ptr< QgsMapLayer > &layer : std::as_const( mLayers ) )
801 layer->moveToThread( QThread::currentThread() );
809 doExport( feedback );
813 if ( mSkipEmptyTiles )
815 feedback->
pushInfo( QObject::tr(
"Wrote %1 total tiles, skipped %2 empty tiles" ).arg( mTilesWritten.load() ).arg( mEmptyTiles.load() ) );
819 results.insert( u
"OUTPUT_DIRECTORY"_s, outputDir );
821 if ( !outputHtml.isEmpty() )
823 const QString osm = QStringLiteral(
824 "var osm_layer = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png',"
825 "{minZoom: %1, maxZoom: %2, attribution: '© <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors'}).addTo(map);"
828 .arg( mMaxZoomLimitIncludingOverrides );
830 const QString addOsm = useOsm ? osm : QString();
831 const QString tmsConvention = tms ? u
"true"_s : u
"false"_s;
832 const QString attr = attribution.isEmpty() ? u
"Created by QGIS"_s : attribution;
833 const QString tileSource = u
"'file:///%1/{z}/{x}/{y}.%2'"_s.arg( outputDir.replace(
"\\",
"/" ).toHtmlEscaped(), mTileFormat.toLower() );
835 const QString html = QStringLiteral(
836 "<!DOCTYPE html><html><head><title>%1</title><meta charset=\"utf-8\"/>"
837 "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
838 "<link rel=\"stylesheet\" href=\"https://unpkg.com/leaflet@1.9.4/dist/leaflet.css\""
839 "integrity=\"sha384-sHL9NAb7lN7rfvG5lfHpm643Xkcjzp4jFvuavGOndn6pjVqS6ny56CAt3nsEVT4H\""
841 "<script src=\"https://unpkg.com/leaflet@1.9.4/dist/leaflet.js\""
842 "integrity=\"sha384-cxOPjt7s7Iz04uaHJceBmS+qpjv2JkIHNVcuOrM+YHwZOmJGBXI00mdUXEq65HTH\""
843 "crossorigin=\"\"></script>"
844 "<style type=\"text/css\">body {margin: 0;padding: 0;} html, body, #map{width: 100%;height: 100%;}</style></head>"
845 "<body><div id=\"map\"></div><script>"
846 "var map = L.map('map', {attributionControl: false}).setView([%2, %3], %4);"
847 "L.control.attribution({prefix: false}).addTo(map);"
849 "var tilesource_layer = L.tileLayer(%6, {minZoom: %7, maxZoom: %8, tms: %9, attribution: '%10'}).addTo(map);"
850 "</script></body></html>"
852 .arg( title.isEmpty() ? u
"Leaflet preview"_s : title )
853 .arg( mWgs84Extent.center().y() )
854 .arg( mWgs84Extent.center().x() )
855 .arg( ( mMaxZoom + mMinZoom ) / 2 )
856 .arg( addOsm, tileSource )
858 .arg( mMaxZoomLimitIncludingOverrides )
859 .arg( tmsConvention, attr );
861 QFile htmlFile( outputHtml );
862 if ( !htmlFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
866 QTextStream fout( &htmlFile );
869 results.insert( u
"OUTPUT_HTML"_s, outputHtml );
875 const QString layerUri
876 = u
"type=xyz&url=file:///%1/%7Bz%7D/%7Bx%7D/%7By%7D.%2&zmax=%3&zmin=%4"_s.arg( outputDir.replace(
"\\",
"/" ).toHtmlEscaped(), mTileFormat.toLower() ).arg( mMaxZoom ).arg( mMinZoom );
877 auto layer = std::make_unique<QgsRasterLayer>( layerUri,
"OUTPUT_LAYER", u
"wms"_s );
878 if ( !layer->isValid() )
880 feedback->
reportError( QObject::tr(
"Failed to open XYZ directory as a raster layer" ) );
882 const QString layerId = layer->id();
884 details.setOutputLayerName( layer.get() );
887 results.insert( u
"OUTPUT_LAYER"_s, layerId );
893void QgsXyzTilesDirectoryAlgorithm::processMetaTile(
const MetaTile &metaTile,
const QImage &renderedImage,
QgsProcessingFeedback *feedback )
895 mActivePostProcessingTasks++;
897 mPostProcessingPool->start( [
this, metaTile, renderedImage, feedback]() {
898 const bool testEmptyTilesUsingAlpha0 = mTileFormat !=
"JPG"_L1 && mBackgroundColor.alpha() == 0;
899 long long localWritten = 0;
900 long long localEmpty = 0;
902 QSet<QString> createdDirs;
904 for (
auto it = metaTile.tiles.constBegin(); it != metaTile.tiles.constEnd(); ++it )
909 const QPair<int, int> tm = it.key();
910 const QImage tileImage = renderedImage.copy( mTileWidth * tm.first, mTileHeight * tm.second, mTileWidth, mTileHeight );
918 const Tile tile = it.value();
919 const QString dirPath = u
"%1/%2/%3"_s.arg( mOutputDir ).arg( tile.z ).arg( tile.x );
920 if ( !createdDirs.contains( dirPath ) )
922 QDir().mkpath( dirPath );
923 createdDirs.insert( dirPath );
926 const int y = mTms ? tile2tms( tile.y, tile.z ) : tile.y;
927 const QString filePath = u
"%1/%2.%3"_s.arg( dirPath ).arg( y ).arg( mTileFormat.toLower() );
928 tileImage.save( filePath, mTileFormat.toStdString().c_str(), mJpgQuality );
933 mTilesWritten += localWritten;
934 mEmptyTiles += localEmpty;
936 mActivePostProcessingTasks--;
937 checkPipelineFinished( feedback );
943 mPostProcessingPool = std::make_unique<QThreadPool>();
944 mPostProcessingPool->setMaxThreadCount( std::max( 1, mThreadsNumber ) );
948 mJobOwner.reset(
new QObject() );
950 startJobs( feedback );
952 if ( !mMetaTiles.isEmpty() || !mRendererJobs.isEmpty() || mActivePostProcessingTasks.load() > 0 )
957 for (
auto it = mRendererJobs.constBegin(); it != mRendererJobs.constEnd(); it++ )
961 mRendererJobs.clear();
963 mPostProcessingPool->waitForDone();
964 mPostProcessingPool.reset();
965 mEventLoop =
nullptr;
973QString QgsXyzTilesMbtilesAlgorithm::name()
const
975 return u
"tilesxyzmbtiles"_s;
978QString QgsXyzTilesMbtilesAlgorithm::displayName()
const
980 return QObject::tr(
"Generate XYZ tiles (MBTiles)" );
983QStringList QgsXyzTilesMbtilesAlgorithm::tags()
const
985 return QObject::tr(
"tiles,xyz,tms,mbtiles" ).split(
',' );
988QString QgsXyzTilesMbtilesAlgorithm::shortHelpString()
const
991 "This algorithm generates XYZ raster tiles from the current project and packages them into a single, portable MBTiles (SQLite) database file.\n\n"
992 "All visible map layers from the project will be rendered into tiles across the specified extent and zoom range."
996QString QgsXyzTilesMbtilesAlgorithm::shortDescription()
const
998 return QObject::tr(
"Generates XYZ tiles from the project as a single, portable MBTiles (SQLite) database." );
1001QgsXyzTilesMbtilesAlgorithm *QgsXyzTilesMbtilesAlgorithm::createInstance()
const
1003 return new QgsXyzTilesMbtilesAlgorithm();
1006void QgsXyzTilesMbtilesAlgorithm::initAlgorithm(
const QVariantMap & )
1008 createCommonParameters();
1016 QGS_MARK_ALGORITHM_SOURCE
1018 const QString outputFile = parameterAsString( parameters, u
"OUTPUT_FILE"_s, context );
1019 if ( QFile::exists( outputFile ) )
1021 feedback->
pushWarning( QObject::tr(
"Removing existing file '%1'" ).arg( QDir::toNativeSeparators( outputFile ) ) );
1022 if ( !QFile( outputFile ).remove() )
1024 throw QgsProcessingException( QObject::tr(
"Could not remove existing file '%1'" ).arg( QDir::toNativeSeparators( outputFile ) ) );
1028 mMbtilesWriter = std::make_unique<QgsMbTiles>( outputFile );
1031 if ( !mMbtilesWriter->create(
true ) )
1033 throw QgsProcessingException( QObject::tr(
"Failed to create MBTiles file %1: %2" ).arg( outputFile, mMbtilesWriter->lastError() ) );
1035 mMbtilesWriter->setMetadataValue( u
"format"_s, mTileFormat.toLower() );
1036 mMbtilesWriter->setMetadataValue( u
"name"_s, QFileInfo( outputFile ).baseName() );
1037 mMbtilesWriter->setMetadataValue( u
"description"_s, QFileInfo( outputFile ).baseName() );
1038 mMbtilesWriter->setMetadataValue( u
"version"_s, u
"1.1"_s );
1039 mMbtilesWriter->setMetadataValue( u
"type"_s, u
"overlay"_s );
1040 mMbtilesWriter->setMetadataValue( u
"minzoom"_s, QString::number( mMinZoom ) );
1041 mMbtilesWriter->setMetadataValue( u
"maxzoom"_s, QString::number( mMaxZoomLimitIncludingOverrides ) );
1042 QString boundsStr = QString( u
"%1,%2,%3,%4"_s ).arg( mWgs84Extent.xMinimum() ).arg( mWgs84Extent.yMinimum() ).arg( mWgs84Extent.xMaximum() ).arg( mWgs84Extent.yMaximum() );
1043 mMbtilesWriter->setMetadataValue( u
"bounds"_s, boundsStr );
1045 long long totalTiles = 0;
1046 mTotalMetaTiles = 0;
1047 for (
int z = mMinZoom; z <= mMaxZoomLimitIncludingOverrides; z++ )
1055 long long tileCount = 0;
1056 mMetaTiles += getMetatiles( mZ0matrix, mTileGenerationRegion, z, tileCount, mMetaTileSize, mMaxZoomRegions, mMaxZoom, feedback );
1057 feedback->
pushInfo( QObject::tr(
"%1 metatiles (%2 tiles) will be created for zoom level %3" ).arg( mMetaTiles.size() - mTotalMetaTiles ).arg( tileCount ).arg( z ) );
1058 mTotalMetaTiles = mMetaTiles.size();
1059 totalTiles += tileCount;
1061 if ( mTotalMetaTiles == 0 )
1063 throw QgsProcessingException( QObject::tr(
"No metatiles will be created -- please check the extent and zoom limits" ) );
1066 feedback->
pushInfo( QObject::tr(
"A total of %1 metatiles (%2 tiles) will be created" ).arg( mTotalMetaTiles ).arg( totalTiles ) );
1073 checkLayersUsagePolicy( feedback );
1075 for (
const std::unique_ptr< QgsMapLayer > &layer : std::as_const( mLayers ) )
1077 layer->moveToThread( QThread::currentThread() );
1086 doExport( feedback );
1092 mMbtilesWriter->finalize();
1095 if ( mSkipEmptyTiles )
1097 feedback->
pushInfo( QObject::tr(
"Wrote %1 total tiles, skipped %2 empty tiles" ).arg( mTilesWritten.load() ).arg( mEmptyTiles.load() ) );
1099 QVariantMap results;
1100 results.insert( u
"OUTPUT_FILE"_s, outputFile );
1105 auto layer = std::make_unique<QgsRasterLayer>( outputFile,
"OUTPUT_LAYER", u
"gdal"_s );
1106 if ( !layer->isValid() )
1108 feedback->
reportError( QObject::tr(
"Failed to open MBTiles file as a raster layer" ) );
1110 const QString layerId = layer->id();
1112 details.setOutputLayerName( layer.get() );
1115 results.insert( u
"OUTPUT_LAYER"_s, layerId );
1121void QgsXyzTilesMbtilesAlgorithm::processMetaTile(
const MetaTile &metaTile,
const QImage &renderedImg,
QgsProcessingFeedback *feedback )
1123 mActivePostProcessingTasks++;
1125 mPostProcessingPool->start( [
this, feedback, metaTile, renderedImg]() {
1126 const bool testEmptyTilesUsingAlpha0 = mTileFormat !=
"JPG"_L1 && mBackgroundColor.alpha() == 0;
1127 long long localWritten = 0;
1128 long long localEmpty = 0;
1130 QList<QgsMbTiles::TileData> metatileTiles;
1131 metatileTiles.reserve( metaTile.tiles.size() );
1133 for (
auto it = metaTile.tiles.constBegin(); it != metaTile.tiles.constEnd(); ++it )
1138 const QPair<int, int> tm = it.key();
1140 const QImage tileImage = renderedImg.copy( mTileWidth * tm.first, mTileHeight * tm.second, mTileWidth, mTileHeight );
1150 QBuffer buffer( &bytes );
1151 buffer.open( QIODevice::WriteOnly );
1152 tileImage.save( &buffer, mTileFormat.toStdString().c_str(), mJpgQuality );
1154 const Tile tile = it.value();
1155 const int tileY = tile2tms( tile.y, tile.z );
1156 metatileTiles.append( { tile.z, tile.x, tileY, bytes } );
1160 mWriteQueue->push( metatileTiles );
1162 mTilesWritten += localWritten;
1163 mEmptyTiles += localEmpty;
1165 mActivePostProcessingTasks--;
1166 checkPipelineFinished( feedback );
1172 mPostProcessingPool = std::make_unique<QThreadPool>();
1173 mPostProcessingPool->setMaxThreadCount( std::max( 1, mThreadsNumber ) );
1175 PendingTilesToWriteQueue< QgsMbTiles::TileData > queue;
1176 mWriteQueue = &queue;
1178 QThread *dbThread = QThread::create( [
this, &queue]() {
1179 QList<QgsMbTiles::TileData> batch;
1180 constexpr int BATCH_SIZE = 10000;
1181 batch.reserve( BATCH_SIZE );
1182 while ( queue.popBatch( batch, BATCH_SIZE ) )
1184 mMbtilesWriter->setTileData( batch );
1192 mJobOwner.reset(
new QObject() );
1194 startJobs( feedback );
1196 if ( !mMetaTiles.isEmpty() || !mRendererJobs.isEmpty() || mActivePostProcessingTasks.load() > 0 )
1201 for (
auto it = mRendererJobs.constBegin(); it != mRendererJobs.constEnd(); it++ )
1205 mRendererJobs.clear();
1207 mPostProcessingPool->waitForDone();
1208 mPostProcessingPool.reset();
1210 queue.setFinished();
1214 mWriteQueue =
nullptr;
1215 mEventLoop =
nullptr;
1223QString QgsXyzTilesGpkgAlgorithm::name()
const
1225 return u
"tilesxyzgpkg"_s;
1228QString QgsXyzTilesGpkgAlgorithm::displayName()
const
1230 return QObject::tr(
"Generate XYZ tiles (GeoPackage)" );
1233QStringList QgsXyzTilesGpkgAlgorithm::tags()
const
1235 return QObject::tr(
"tiles,xyz,geopackage,gpkg,raster" ).split(
',' );
1238QString QgsXyzTilesGpkgAlgorithm::shortDescription()
const
1240 return QObject::tr(
"Renders maps to XYZ raster tiles into a GeoPackage raster tile database." );
1243QString QgsXyzTilesGpkgAlgorithm::shortHelpString()
const
1246 "This algorithm generates XYZ raster tiles from the current project and saves them into an OGC GeoPackage file.\n\n"
1247 "All visible map layers from the project will be rendered into tiles across the specified extent and zoom range."
1251QgsXyzTilesGpkgAlgorithm *QgsXyzTilesGpkgAlgorithm::createInstance()
const
1253 return new QgsXyzTilesGpkgAlgorithm();
1256void QgsXyzTilesGpkgAlgorithm::initAlgorithm(
const QVariantMap & )
1258 createCommonParameters();
1259 createTileMatrixParameters();
1262 tileWidthParam->setHelp( QObject::tr(
"Width of each tile image in pixels." ) );
1263 addParameter( tileWidthParam.release() );
1266 tileHeightParam->setHelp( QObject::tr(
"Height of each tile image in pixels." ) );
1267 addParameter( tileHeightParam.release() );
1276 QGS_MARK_ALGORITHM_SOURCE
1278 const QString outputFile = parameterAsString( parameters, u
"OUTPUT_FILE"_s, context );
1280 if ( QFile::exists( outputFile ) )
1282 feedback->
pushWarning( QObject::tr(
"Removing existing file '%1'" ).arg( QDir::toNativeSeparators( outputFile ) ) );
1283 if ( !QFile( outputFile ).remove() )
1285 throw QgsProcessingException( QObject::tr(
"Could not remove existing file '%1'" ).arg( QDir::toNativeSeparators( outputFile ) ) );
1289 mGpkgWriter = std::make_unique<QgsGeoPackageTiles>( outputFile );
1291 if ( !mGpkgWriter->create( mZ0matrix, mTileGenerationRegion, mMinZoom, mMaxZoomLimitIncludingOverrides, mTileWidth, mTileHeight ) )
1293 throw QgsProcessingException( QObject::tr(
"Failed to create GeoPackage file %1: %2" ).arg( outputFile, mGpkgWriter->lastError() ) );
1296 long long totalTiles = 0;
1297 mTotalMetaTiles = 0;
1298 for (
int z = mMinZoom; z <= mMaxZoomLimitIncludingOverrides; z++ )
1306 long long tileCount = 0;
1307 mMetaTiles += getMetatiles( mZ0matrix, mTileGenerationRegion, z, tileCount, mMetaTileSize, mMaxZoomRegions, mMaxZoom, feedback );
1308 feedback->
pushInfo( QObject::tr(
"%1 metatiles (%2 tiles) will be created for zoom level %3" ).arg( mMetaTiles.size() - mTotalMetaTiles ).arg( tileCount ).arg( z ) );
1309 mTotalMetaTiles = mMetaTiles.size();
1310 totalTiles += tileCount;
1312 if ( mTotalMetaTiles == 0 )
1314 throw QgsProcessingException( QObject::tr(
"No metatiles will be created -- please check the extent and zoom limits" ) );
1316 feedback->
pushInfo( QObject::tr(
"A total of %1 metatiles (%2 tiles) will be created" ).arg( mTotalMetaTiles ).arg( totalTiles ) );
1323 checkLayersUsagePolicy( feedback );
1325 for (
const std::unique_ptr< QgsMapLayer > &layer : std::as_const( mLayers ) )
1327 layer->moveToThread( QThread::currentThread() );
1335 mJobOwner.reset(
new QObject() );
1337 doExport( feedback );
1343 mGpkgWriter->finalize();
1346 mGpkgWriter->close();
1348 if ( mSkipEmptyTiles )
1350 feedback->
pushInfo( QObject::tr(
"Wrote %1 total tiles, skipped %2 empty tiles" ).arg( mTilesWritten.load() ).arg( mEmptyTiles.load() ) );
1353 QVariantMap results;
1358 auto layer = std::make_unique<QgsRasterLayer>( outputFile,
"OUTPUT_LAYER", u
"gdal"_s );
1359 if ( !layer->isValid() )
1361 feedback->
reportError( QObject::tr(
"Failed to open GeoPackage file as a raster layer" ) );
1363 const QString layerId = layer->id();
1365 details.setOutputLayerName( layer.get() );
1368 results.insert( u
"OUTPUT_LAYER"_s, layerId );
1371 results.insert( u
"OUTPUT_FILE"_s, outputFile );
1375void QgsXyzTilesGpkgAlgorithm::processMetaTile(
const MetaTile &metaTile,
const QImage &renderedImg,
QgsProcessingFeedback *feedback )
1377 mActivePostProcessingTasks++;
1378 mPostProcessingPool->start( [
this, feedback, metaTile, renderedImg]() {
1379 const bool testEmptyTilesUsingAlpha0 = mTileFormat !=
"JPG"_L1 && mBackgroundColor.alpha() == 0;
1380 long long localWritten = 0;
1381 long long localEmpty = 0;
1383 QList<QgsGeoPackageTiles::TileData> metatileTiles;
1384 metatileTiles.reserve( metaTile.tiles.size() );
1386 for (
auto it = metaTile.tiles.constBegin(); it != metaTile.tiles.constEnd(); ++it )
1391 const QPair<int, int> tm = it.key();
1393 const QImage tileImage = renderedImg.copy( mTileWidth * tm.first, mTileHeight * tm.second, mTileWidth, mTileHeight );
1403 QBuffer buffer( &bytes );
1404 buffer.open( QIODevice::WriteOnly );
1405 tileImage.save( &buffer, mTileFormat.toStdString().c_str(), mJpgQuality );
1407 const Tile tile = it.value();
1409 metatileTiles.append( { tile.z, tile.x, tile.y, bytes } );
1413 mWriteQueue->push( metatileTiles );
1415 mTilesWritten += localWritten;
1416 mEmptyTiles += localEmpty;
1418 mActivePostProcessingTasks--;
1419 checkPipelineFinished( feedback );
1425 mPostProcessingPool = std::make_unique<QThreadPool>();
1426 mPostProcessingPool->setMaxThreadCount( std::max( 1, mThreadsNumber ) );
1428 PendingTilesToWriteQueue<QgsGeoPackageTiles::TileData> queue;
1429 mWriteQueue = &queue;
1431 QThread *dbThread = QThread::create( [
this, &queue]() {
1432 QList<QgsGeoPackageTiles::TileData> batch;
1433 constexpr int BATCH_SIZE = 10000;
1434 batch.reserve( BATCH_SIZE );
1435 while ( queue.popBatch( batch, BATCH_SIZE ) )
1437 mGpkgWriter->setTileData( batch );
1445 mJobOwner.reset(
new QObject() );
1447 startJobs( feedback );
1449 if ( !mMetaTiles.isEmpty() || !mRendererJobs.isEmpty() || mActivePostProcessingTasks.load() > 0 )
1454 for (
auto it = mRendererJobs.constBegin(); it != mRendererJobs.constEnd(); it++ )
1458 mRendererJobs.clear();
1460 mPostProcessingPool->waitForDone();
1461 mPostProcessingPool.reset();
1463 queue.setFinished();
1467 mWriteQueue =
nullptr;
1468 mEventLoop =
nullptr;
@ Default
Allow raster-based rendering in situations where it is required for correct rendering or where it wil...
@ UsePartialCandidates
Whether to use also label candidates that are partially outside of the map view.
QFlags< ProcessingAlgorithmFlag > ProcessingAlgorithmFlags
Flags indicating how and when an algorithm operates and should be exposed to users.
@ Export
Renderer used for printing or exporting to a file.
@ RequiresProject
The algorithm requires that a valid QgsProject is available from the processing context in order to e...
@ Advanced
Parameter is an advanced parameter which should be hidden from users by default.
@ Optional
Parameter is optional.
@ RenderMapTile
Draw map such that there are no problems between adjacent tiles.
@ UseRenderingOptimization
Enable vector simplification and other rendering optimizations.
@ Antialiasing
Enable anti-aliasing for map rendering.
@ HighQualityImageTransforms
Enable high quality image transformations, which results in better appearance of scaled or rotated ra...
Represents a coordinate reference system (CRS).
Custom exception class for Coordinate Reference System related exceptions.
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
bool isCanceled() const
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
Contains operations and filters which apply to QImages.
static bool isBlankImage(const QImage &image)
Tests whether an image is completely blank, i.e.
Stores global configuration for labeling engine.
void setFlag(Qgis::LabelingFlag f, bool enabled=true)
Sets whether a particual flag is enabled.
QList< QgsLayerTreeLayer * > findLayers() const
Find all layer nodes.
Layer tree node points to a map layer.
QList< QgsMapLayer * > layerOrder() const
The order in which layers will be rendered on the canvas.
QgsMapLayer * addMapLayer(QgsMapLayer *layer, bool takeOwnership=true)
Add a layer to the store.
static bool isOpenStreetMapLayer(QgsMapLayer *layer)
Returns true if the layer is served by OpenStreetMap server.
Base class for all map layer types.
virtual QgsMapLayer * clone() const =0
Returns a new instance equivalent to this one except for the id which is still unique.
void finished()
emitted when asynchronous rendering is finished (or canceled).
void start()
Start the rendering job and immediately return.
Job implementation that renders everything sequentially in one thread.
QImage renderedImage() override
Gets a preview/resulting image.
Contains configuration for rendering maps.
const QgsLabelingEngineSettings & labelingEngineSettings() const
Returns the global configuration of the labeling engine.
void setLayers(const QList< QgsMapLayer * > &layers)
Sets the list of layers to render in the map.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
void setScaleMethod(Qgis::ScaleCalculationMethod method)
Sets the method to use for scale calculations for the map.
void setOutputDpi(double dpi)
Sets the dpi (dots per inch) used for conversion between real world units (e.g.
void setOutputImageFormat(QImage::Format format)
sets format of internal QImage
void setRendererUsage(Qgis::RendererUsage rendererUsage)
Sets the rendering usage.
void setRasterizedRenderingPolicy(Qgis::RasterizedRenderingPolicy policy)
Sets the policy controlling when rasterisation of content during renders is permitted.
void setExtent(const QgsRectangle &rect, bool magnified=true)
Sets the coordinates of the rectangle which should be rendered.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
void setLabelingEngineSettings(const QgsLabelingEngineSettings &settings)
Sets the global configuration of the labeling engine.
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the coordinate transform context, which stores various information regarding which datum transfo...
void setOutputSize(QSize size)
Sets the size of the resulting map image, in pixels.
void setBackgroundColor(const QColor &color)
Sets the background color of the map.
void setFlag(Qgis::MapSettingsFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected).
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
Sets the destination crs (coordinate reference system) for the map render.
virtual Qgis::ProcessingAlgorithmFlags flags() const
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
Details for layers to load into projects.
Contains information about the context in which a processing algorithm is executed.
QgsExpressionContext & expressionContext()
Returns the expression context.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
void addLayerToLoadOnCompletion(const QString &layer, const QgsProcessingContext::LayerDetails &details)
Adds a layer to load (by ID or datasource) into the canvas upon completion of the algorithm or model.
QgsProject * project() const
Returns the project in which the algorithm is being executed.
QString ellipsoid() const
Returns the ellipsoid to use for distance and area calculations.
QgsMapLayerStore * temporaryLayerStore()
Returns a reference to the layer store used for storing temporary layers during algorithm execution.
int maximumThreads() const
Returns the (optional) number of threads to use when running algorithms.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
virtual void pushWarning(const QString &warning)
Pushes a warning informational message from the algorithm.
virtual void pushFormattedMessage(const QString &html, const QString &text)
Pushes a pre-formatted message from the algorithm.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
A raster layer output for processing algorithms.
A generic file based destination parameter, for specifying the destination path for a file (non-map l...
static int maxZoomForTile(const QgsRectangle &tileExtent, const QList< QgsTileExtentMaxZoomRegion > ®ions, int defaultMaxZoom)
Evaluates the effective maximum zoom level for a given tileExtent.
@ Raster
Raster layer type.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
QgsLayerTree * layerTreeRoot() const
Returns pointer to the root (invisible) node of the project's layer tree.
Qgis::ScaleCalculationMethod scaleMethod
A rectangle specified with double values.
Q_INVOKABLE QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be rounded to the spec...
A QgsRectangle with associated coordinate reference system.
Defines a matrix of tiles for a single zoom level: it is defined by its size (width *.
QgsRectangle extent() const
Returns extent of the tile matrix.
int matrixWidth() const
Returns number of columns of the tile matrix.
int matrixHeight() const
Returns number of rows of the tile matrix.
static QgsTileMatrix fromTileMatrix(int zoomLevel, const QgsTileMatrix &tileMatrix)
Returns a tile matrix based on another one.
static QgsTileMatrix fromCustomDef(int zoomLevel, const QgsCoordinateReferenceSystem &crs, const QgsPointXY &z0TopLeftPoint, double z0Dimension, int z0MatrixWidth=1, int z0MatrixHeight=1)
Returns a tile matrix for a specific CRS, top left point, zoom level 0 dimension in CRS units.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
#define MAXIMUM_OPENSTREETMAP_TILES_FETCH
Represents a spatial region paired with a custom maximum zoom level.
QgsReferencedRectangle extent
Bounding box extent and associated CRS.