QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgsterraintexturegenerator_p.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsterraintexturegenerator_p.cpp
3 --------------------------------------
4 Date : July 2017
5 Copyright : (C) 2017 by Martin Dobias
6 Email : wonder dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17
20#include <qgsmapsettings.h>
22#include <qgsproject.h>
23
24#include "qgs3dmapsettings.h"
25
26#include "qgseventtracing.h"
27
29
30QgsTerrainTextureGenerator::QgsTerrainTextureGenerator( const Qgs3DMapSettings &map )
31 : mMap( map )
32 , mLastJobId( 0 )
33 , mTextureSize( QSize( mMap.mapTileResolution(), mMap.mapTileResolution() ) )
34{
35}
36
37int QgsTerrainTextureGenerator::render( const QgsRectangle &extent, QgsChunkNodeId tileId, const QString &debugText )
38{
39 QgsMapSettings mapSettings( baseMapSettings() );
40 mapSettings.setExtent( extent );
41
42 QList<QgsMapLayer *> layers = mMap.layers();
43 QList<QgsMapLayer *> toBeRenderedLayers;
44 for ( QgsMapLayer *l : layers )
45 {
46 if ( l->renderer3D() == nullptr )
47 toBeRenderedLayers.push_back( l );
48 }
49 mapSettings.setLayers( toBeRenderedLayers );
50
51 QgsEventTracing::addEvent( QgsEventTracing::AsyncBegin, QStringLiteral( "3D" ), QStringLiteral( "Texture" ), tileId.text() );
52
54 connect( job, &QgsMapRendererJob::finished, this, &QgsTerrainTextureGenerator::onRenderingFinished );
55
56 JobData jobData;
57 jobData.jobId = ++mLastJobId;
58 jobData.tileId = tileId;
59 jobData.job = job;
60 jobData.extent = extent;
61 jobData.debugText = debugText;
62
63 mJobs.insert( job, jobData ); //store job data just before launching the job
64 job->start();
65
66 // QgsDebugMsgLevel( QStringLiteral("added job: %1 .... in queue: %2").arg( jobData.jobId ).arg( jobs.count() ), 2);
67 return jobData.jobId;
68}
69
70void QgsTerrainTextureGenerator::cancelJob( int jobId )
71{
72 for ( const JobData &jd : std::as_const( mJobs ) )
73 {
74 if ( jd.jobId == jobId )
75 {
76 // QgsDebugMsgLevel( QStringLiteral("canceling job %1").arg( jobId ), 2 );
77 jd.job->cancelWithoutBlocking();
78 disconnect( jd.job, &QgsMapRendererJob::finished, this, &QgsTerrainTextureGenerator::onRenderingFinished );
79 jd.job->deleteLater();
80 mJobs.remove( jd.job );
81 return;
82 }
83 }
84 Q_ASSERT( false && "requested job ID does not exist!" );
85}
86
87void QgsTerrainTextureGenerator::waitForFinished()
88{
89 for ( QgsMapRendererSequentialJob *job : mJobs.keys() )
90 disconnect( job, &QgsMapRendererJob::finished, this, &QgsTerrainTextureGenerator::onRenderingFinished );
91 QVector<QgsMapRendererSequentialJob *> toBeDeleted;
92 for ( QgsMapRendererSequentialJob *mapJob : mJobs.keys() )
93 {
94 mapJob->waitForFinished();
95 JobData jobData = mJobs.value( mapJob );
96 toBeDeleted.push_back( mapJob );
97
98 QImage img = mapJob->renderedImage();
99
100 if ( mMap.showTerrainTilesInfo() )
101 {
102 // extra tile information for debugging
103 QPainter p( &img );
104 p.setPen( Qt::white );
105 p.drawRect( 0, 0, img.width() - 1, img.height() - 1 );
106 p.drawText( img.rect(), jobData.debugText, QTextOption( Qt::AlignCenter ) );
107 p.end();
108 }
109
110 // pass QImage further
111 emit tileReady( jobData.jobId, img );
112 }
113
114 for ( QgsMapRendererSequentialJob *mapJob : toBeDeleted )
115 {
116 mJobs.remove( mapJob );
117 mapJob->deleteLater();
118 }
119}
120
121void QgsTerrainTextureGenerator::onRenderingFinished()
122{
123 QgsMapRendererSequentialJob *mapJob = static_cast<QgsMapRendererSequentialJob *>( sender() );
124
125 Q_ASSERT( mJobs.contains( mapJob ) );
126 JobData jobData = mJobs.value( mapJob );
127
128 QImage img = mapJob->renderedImage();
129
130 if ( mMap.showTerrainTilesInfo() )
131 {
132 // extra tile information for debugging
133 QPainter p( &img );
134 p.setPen( Qt::white );
135 p.drawRect( 0, 0, img.width() - 1, img.height() - 1 );
136 p.drawText( img.rect(), jobData.debugText, QTextOption( Qt::AlignCenter ) );
137 p.end();
138 }
139
140 mapJob->deleteLater();
141 mJobs.remove( mapJob );
142
143 // QgsDebugMsgLevel( QStringLiteral("finished job %1 ... in queue: %2").arg( jobData.jobId).arg( jobs.count() ), 2 );
144
145 QgsEventTracing::addEvent( QgsEventTracing::AsyncEnd, QStringLiteral( "3D" ), QStringLiteral( "Texture" ), jobData.tileId.text() );
146
147 // pass QImage further
148 emit tileReady( jobData.jobId, img );
149}
150
151QgsMapSettings QgsTerrainTextureGenerator::baseMapSettings()
152{
153 QgsMapSettings mapSettings;
154
155 mapSettings.setOutputSize( mTextureSize );
156 mapSettings.setDestinationCrs( mMap.crs() );
157 mapSettings.setBackgroundColor( mMap.backgroundColor() );
158 mapSettings.setFlag( Qgis::MapSettingsFlag::DrawLabeling, mMap.showLabels() );
160 mapSettings.setTransformContext( mMap.transformContext() );
161 mapSettings.setPathResolver( mMap.pathResolver() );
162 mapSettings.setRendererUsage( mMap.rendererUsage() );
163
164 QgsMapThemeCollection *mapThemes = mMap.mapThemeCollection();
165 QString mapThemeName = mMap.terrainMapTheme();
166 if ( mapThemeName.isEmpty() || !mapThemes || !mapThemes->hasMapTheme( mapThemeName ) )
167 {
168 mapSettings.setLayers( mMap.layers() );
169 }
170 else
171 {
172 mapSettings.setLayers( mapThemes->mapThemeVisibleLayers( mapThemeName ) );
173 mapSettings.setLayerStyleOverrides( mapThemes->mapThemeStyleOverrides( mapThemeName ) );
174 }
175
176 return mapSettings;
177}
178
@ DrawLabeling
Enable drawing of labels on top of the map.
@ Render3DMap
Render is for a 3D map.
Base class for all map layer types.
Definition: qgsmaplayer.h:73
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.
The QgsMapSettings class contains configuration for rendering of the map.
void setLayers(const QList< QgsMapLayer * > &layers)
Sets the list of layers to render in the map.
void setRendererUsage(Qgis::RendererUsage rendererUsage)
Sets the rendering usage.
void setLayerStyleOverrides(const QMap< QString, QString > &overrides)
Sets the map of map layer style overrides (key: layer ID, value: style name) where a different style ...
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the coordinate transform context, which stores various information regarding which datum transfo...
void setPathResolver(const QgsPathResolver &resolver)
Sets the path resolver for conversion between relative and absolute paths during rendering operations...
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.
Container class that allows storage of map themes consisting of visible map layers and layer styles.
bool hasMapTheme(const QString &name) const
Returns whether a map theme with a matching name exists.
QList< QgsMapLayer * > mapThemeVisibleLayers(const QString &name) const
Returns the list of layers that are visible for the specified map theme.
QMap< QString, QString > mapThemeStyleOverrides(const QString &name)
Gets layer style overrides (for QgsMapSettings) of the visible layers for given map theme.
A rectangle specified with double values.
Definition: qgsrectangle.h:42