QGIS API Documentation  3.20.0-Odense (decaadbb31)
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>
21 #include <qgsmapthemecollection.h>
22 #include <qgsproject.h>
23 
24 #include "qgs3dmapsettings.h"
25 
26 #include "qgseventtracing.h"
27 
29 
30 QgsTerrainTextureGenerator::QgsTerrainTextureGenerator( const Qgs3DMapSettings &map )
31  : mMap( map )
32  , mLastJobId( 0 )
33  , mTextureSize( QSize( mMap.mapTileResolution(), mMap.mapTileResolution() ) )
34 {
35 }
36 
37 int QgsTerrainTextureGenerator::render( const QgsRectangle &extent, QgsChunkNodeId tileId, const QString &debugText )
38 {
39  QgsMapSettings mapSettings( baseMapSettings() );
40  mapSettings.setExtent( extent );
41 
42  QgsEventTracing::addEvent( QgsEventTracing::AsyncBegin, QStringLiteral( "3D" ), QStringLiteral( "Texture" ), tileId.text() );
43 
45  connect( job, &QgsMapRendererJob::finished, this, &QgsTerrainTextureGenerator::onRenderingFinished );
46 
47  JobData jobData;
48  jobData.jobId = ++mLastJobId;
49  jobData.tileId = tileId;
50  jobData.job = job;
51  jobData.extent = extent;
52  jobData.debugText = debugText;
53 
54  mJobs.insert( job, jobData ); //store job data just before launching the job
55  job->start();
56 
57  // QgsDebugMsgLevel( QStringLiteral("added job: %1 .... in queue: %2").arg( jobData.jobId ).arg( jobs.count() ), 2);
58  return jobData.jobId;
59 }
60 
61 void QgsTerrainTextureGenerator::cancelJob( int jobId )
62 {
63  for ( const JobData &jd : std::as_const( mJobs ) )
64  {
65  if ( jd.jobId == jobId )
66  {
67  // QgsDebugMsgLevel( QStringLiteral("canceling job %1").arg( jobId ), 2 );
68  jd.job->cancelWithoutBlocking();
69  disconnect( jd.job, &QgsMapRendererJob::finished, this, &QgsTerrainTextureGenerator::onRenderingFinished );
70  jd.job->deleteLater();
71  mJobs.remove( jd.job );
72  return;
73  }
74  }
75  Q_ASSERT( false && "requested job ID does not exist!" );
76 }
77 
78 void QgsTerrainTextureGenerator::waitForFinished()
79 {
80  for ( QgsMapRendererSequentialJob *job : mJobs.keys() )
81  disconnect( job, &QgsMapRendererJob::finished, this, &QgsTerrainTextureGenerator::onRenderingFinished );
82  QVector<QgsMapRendererSequentialJob *> toBeDeleted;
83  for ( QgsMapRendererSequentialJob *mapJob : mJobs.keys() )
84  {
85  mapJob->waitForFinished();
86  JobData jobData = mJobs.value( mapJob );
87  toBeDeleted.push_back( mapJob );
88 
89  QImage img = mapJob->renderedImage();
90 
91  if ( mMap.showTerrainTilesInfo() )
92  {
93  // extra tile information for debugging
94  QPainter p( &img );
95  p.setPen( Qt::white );
96  p.drawRect( 0, 0, img.width() - 1, img.height() - 1 );
97  p.drawText( img.rect(), jobData.debugText, QTextOption( Qt::AlignCenter ) );
98  p.end();
99  }
100 
101  // pass QImage further
102  emit tileReady( jobData.jobId, img );
103  }
104 
105  for ( QgsMapRendererSequentialJob *mapJob : toBeDeleted )
106  {
107  mJobs.remove( mapJob );
108  mapJob->deleteLater();
109  }
110 }
111 
112 void QgsTerrainTextureGenerator::onRenderingFinished()
113 {
114  QgsMapRendererSequentialJob *mapJob = static_cast<QgsMapRendererSequentialJob *>( sender() );
115 
116  Q_ASSERT( mJobs.contains( mapJob ) );
117  JobData jobData = mJobs.value( mapJob );
118 
119  QImage img = mapJob->renderedImage();
120 
121  if ( mMap.showTerrainTilesInfo() )
122  {
123  // extra tile information for debugging
124  QPainter p( &img );
125  p.setPen( Qt::white );
126  p.drawRect( 0, 0, img.width() - 1, img.height() - 1 );
127  p.drawText( img.rect(), jobData.debugText, QTextOption( Qt::AlignCenter ) );
128  p.end();
129  }
130 
131  mapJob->deleteLater();
132  mJobs.remove( mapJob );
133 
134  // QgsDebugMsgLevel( QStringLiteral("finished job %1 ... in queue: %2").arg( jobData.jobId).arg( jobs.count() ), 2 );
135 
136  QgsEventTracing::addEvent( QgsEventTracing::AsyncEnd, QStringLiteral( "3D" ), QStringLiteral( "Texture" ), jobData.tileId.text() );
137 
138  // pass QImage further
139  emit tileReady( jobData.jobId, img );
140 }
141 
142 QgsMapSettings QgsTerrainTextureGenerator::baseMapSettings()
143 {
144  QgsMapSettings mapSettings;
145 
146  mapSettings.setOutputSize( mTextureSize );
147  mapSettings.setDestinationCrs( mMap.crs() );
148  mapSettings.setBackgroundColor( mMap.backgroundColor() );
149  mapSettings.setFlag( QgsMapSettings::DrawLabeling, mMap.showLabels() );
150  mapSettings.setFlag( QgsMapSettings::Render3DMap );
151  mapSettings.setTransformContext( mMap.transformContext() );
152  mapSettings.setPathResolver( mMap.pathResolver() );
153 
154  QgsMapThemeCollection *mapThemes = mMap.mapThemeCollection();
155  QString mapThemeName = mMap.terrainMapTheme();
156  if ( mapThemeName.isEmpty() || !mapThemes || !mapThemes->hasMapTheme( mapThemeName ) )
157  {
158  mapSettings.setLayers( mMap.terrainLayers() );
159  }
160  else
161  {
162  mapSettings.setLayers( mapThemes->mapThemeVisibleLayers( mapThemeName ) );
163  mapSettings.setLayerStyleOverrides( mapThemes->mapThemeStyleOverrides( mapThemeName ) );
164  }
165 
166  return mapSettings;
167 }
168 
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.
@ Render3DMap
Render is for a 3D map.
@ DrawLabeling
Enable drawing of labels on top of the map.
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 setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
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 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