QGIS API Documentation 4.3.0-Master (4ecdf0f3f59)
Loading...
Searching...
No Matches
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
18#include "qgs3dmapsettings.h"
20#include "qgseventtracing.h"
21#include "qgsfutureutils.h"
23#include "qgsmapsettings.h"
25#include "qgsproject.h"
26
27#include <QString>
28
29#include "moc_qgsterraintexturegenerator_p.cpp"
30
31using namespace Qt::StringLiterals;
32
34
35QgsTerrainTextureGenerator::QgsTerrainTextureGenerator( const Qgs3DMapSettings &map )
36 : mMap( map )
37 , mTextureSize( QSize( mMap.terrainSettings()->mapTileResolution(), mMap.terrainSettings()->mapTileResolution() ) )
38{}
39
40QFuture<QImage> QgsTerrainTextureGenerator::render( const QgsRectangle &extent, QgsChunkNodeId tileId, const QString &debugText )
41{
42 QgsMapSettings mapSettings( baseMapSettings() );
43 mapSettings.setExtent( extent );
44 QSize size = QSize( mTextureSize );
45
46 QgsRectangle clippedExtent = extent;
47 if ( mMap.sceneMode() == Qgis::SceneMode::Local && mMap.terrainGenerator()->type() == QgsTerrainGenerator::Flat )
48 {
49 // The flat terrain generator might have non-square tiles, clipped at the scene's extent.
50 // We need to produce non-square textures for those cases.
51 clippedExtent = extent.intersect( mMap.extent() );
52 mapSettings.setExtent( clippedExtent );
53 }
54 if ( !qgsDoubleNear( clippedExtent.width(), clippedExtent.height() ) )
55 {
56 if ( clippedExtent.height() > clippedExtent.width() )
57 size.setWidth( static_cast< int >( std::round( size.width() * clippedExtent.width() / clippedExtent.height() ) ) );
58 else if ( clippedExtent.height() < clippedExtent.width() )
59 size.setHeight( static_cast< int >( std::round( size.height() * clippedExtent.height() / clippedExtent.width() ) ) );
60 }
61 mapSettings.setOutputSize( size );
62
63 QgsEventTracing::addEvent( QgsEventTracing::AsyncBegin, u"3D"_s, u"Texture"_s, tileId.text() );
64
66 connect( job, &QgsMapRendererJob::finished, this, &QgsTerrainTextureGenerator::onRenderingFinished );
67
68 auto jobData = std::make_unique<JobData>();
69 jobData->tileId = tileId;
70 jobData->job = job;
71 jobData->extent = extent;
72 jobData->debugText = debugText;
73
74 connect( &jobData->watcher, &QFutureWatcher<QImage>::canceled, this, [this, &jobData = *jobData]() {
75 disconnect( jobData.job, &QgsMapRendererJob::finished, this, &QgsTerrainTextureGenerator::onRenderingFinished );
76 connect( jobData.job, &QgsMapRendererJob::finished, jobData.job, &QgsMapRendererSequentialJob::deleteLater );
77 jobData.job->cancelWithoutBlocking();
78 jobData.promise.finish();
79 mJobs.erase( jobData.job );
80 } );
81 jobData->watcher.setFuture( jobData->promise.future() );
82
83 mJobs[job] = std::move( jobData ); //store job data just before launching the job
84 job->start();
85
86 // QgsDebugMsgLevel( u"added job: %1 .... in queue: %2"_s.arg( jobData.jobId ).arg( jobs.count() ), 2);
87 return mJobs[job]->promise.future();
88}
89
90void QgsTerrainTextureGenerator::onRenderingFinished()
91{
92 QgsMapRendererSequentialJob *mapJob = static_cast<QgsMapRendererSequentialJob *>( sender() );
93
94 Q_ASSERT( mJobs.contains( mapJob ) );
95 JobData &jobData = *mJobs[mapJob];
96
97 QImage img = mapJob->renderedImage();
98
99 if ( mMap.debugFlags().testFlag( Qgis::Map3DDebugFlag::ShowTerrainTileInfo ) )
100 {
101 // extra tile information for debugging
102 QPainter p( &img );
103 p.setPen( Qt::red );
104 p.setBackgroundMode( Qt::OpaqueMode );
105 QFont font = p.font();
106 font.setPixelSize( std::max( 30, mMap.terrainSettings()->mapTileResolution() / 6 ) );
107 p.setFont( font );
108 p.drawRect( 0, 0, img.width() - 1, img.height() - 1 );
109 p.drawText( img.rect(), jobData.debugText, QTextOption( Qt::AlignCenter ) );
110 p.end();
111 }
112
113 mapJob->deleteLater();
114 jobData.promise.addResult( img );
115 jobData.promise.finish();
116 QgsEventTracing::addEvent( QgsEventTracing::AsyncEnd, u"3D"_s, u"Texture"_s, jobData.tileId.text() );
117 mJobs.erase( mapJob );
118}
119
120QgsMapSettings QgsTerrainTextureGenerator::baseMapSettings()
121{
122 QgsMapSettings mapSettings;
123
124 mapSettings.setOutputSize( mTextureSize );
125 mapSettings.setDestinationCrs( mMap.sceneMode() == Qgis::SceneMode::Globe ? mMap.crs().toGeographicCrs() : mMap.crs() );
126 mapSettings.setBackgroundColor( mMap.backgroundColor() );
127 mapSettings.setFlag( Qgis::MapSettingsFlag::DrawLabeling, mMap.showLabels() );
129 mapSettings.setTransformContext( mMap.transformContext() );
130 mapSettings.setPathResolver( mMap.pathResolver() );
131 mapSettings.setRendererUsage( mMap.rendererUsage() );
132
133 QList<QgsMapLayer *> layers;
134 QgsMapThemeCollection *mapThemes = mMap.mapThemeCollection();
135 QString mapThemeName = mMap.terrainMapTheme();
136 if ( mapThemeName.isEmpty() || !mapThemes || !mapThemes->hasMapTheme( mapThemeName ) )
137 {
138 layers = mMap.layers();
139 }
140 else
141 {
142 layers = mapThemes->mapThemeVisibleLayers( mapThemeName );
143 mapSettings.setLayerStyleOverrides( mapThemes->mapThemeStyleOverrides( mapThemeName ) );
144 }
145 layers.erase( std::remove_if( layers.begin(), layers.end(), []( const QgsMapLayer *layer ) { return layer->renderer3D(); } ), layers.end() );
146 mapSettings.setLayers( layers );
147
148 return mapSettings;
149}
150
@ ShowTerrainTileInfo
Displays extra tile info on top of terrain tiles.
Definition qgis.h:4400
@ Globe
Scene is represented as a globe using a geocentric CRS.
Definition qgis.h:4594
@ Local
Local scene based on a projected CRS.
Definition qgis.h:4593
@ DrawLabeling
Enable drawing of labels on top of the map.
Definition qgis.h:2934
@ Render3DMap
Render is for a 3D map.
Definition qgis.h:2944
Definition of the world.
Base class for all map layer types.
Definition qgsmaplayer.h:83
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.
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.
QgsRectangle intersect(const QgsRectangle &rect) const
Returns the intersection with the given rectangle.
@ Flat
The whole terrain is flat area.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:7771