QGIS API Documentation 3.99.0-Master (8e76e220402)
Loading...
Searching...
No Matches
qgsmapoverlaytexturegenerator_p.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmapoverlaytexturegenerator_p.cpp
3 --------------------------------------
4 Date : July 2025
5 Copyright : (C) 2025 by Jean Felder
6 Email : jean dot felder at oslandia 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"
19#include "qgseventtracing.h"
21#include "qgsmapsettings.h"
22
23#include <QString>
24
25#include "moc_qgsmapoverlaytexturegenerator_p.cpp"
26
27using namespace Qt::StringLiterals;
28
30
31QgsMapOverlayTextureGenerator::QgsMapOverlayTextureGenerator( const Qgs3DMapSettings &mapSettings, int size )
32 : m3DMapSettings( mapSettings )
33 , mSize( QSize( size, size ) )
34 , mLastJobId( 0 )
35{
36}
37
38QgsMapOverlayTextureGenerator::~QgsMapOverlayTextureGenerator()
39{
40 cancelActiveJob();
41}
42
43int QgsMapOverlayTextureGenerator::render( const QgsRectangle &extent, const QVector<QgsPointXY> &frustumExtent, double azimuthDegrees, bool showFrustum )
44{
45 cancelActiveJob();
46 QgsMapSettings mapSettings( baseMapSettings() );
47 mapSettings.setExtent( extent );
48
49 mExtent = extent;
50 mRotation = azimuthDegrees;
51 mFrustumExtent = frustumExtent;
52 mShowFrustum = showFrustum;
53 mLastJobId++;
54 QgsEventTracing::addEvent( QgsEventTracing::AsyncBegin, u"3D"_s, u"Texture"_s, QString::number( mLastJobId ) );
55
56 mActiveJob = new QgsMapRendererParallelJob( mapSettings );
57 connect( mActiveJob, &QgsMapRendererJob::finished, this, &QgsMapOverlayTextureGenerator::onRenderingFinished );
58
59 mActiveJob->start();
60
61 return mLastJobId;
62}
63
64void QgsMapOverlayTextureGenerator::cancelActiveJob()
65{
66 if ( !mActiveJob )
67 {
68 return;
69 }
70
71 disconnect( mActiveJob, &QgsMapRendererJob::finished, this, &QgsMapOverlayTextureGenerator::onRenderingFinished );
72 connect( mActiveJob, &QgsMapRendererJob::finished, mActiveJob, &QgsMapRendererParallelJob::deleteLater );
73 mActiveJob->cancelWithoutBlocking();
74 mActiveJob = nullptr;
75}
76
77void QgsMapOverlayTextureGenerator::onRenderingFinished()
78{
79 QImage renderedImage = mActiveJob->renderedImage();
80 const QPoint center = renderedImage.rect().center();
81
82 QPainter painter( &renderedImage );
83 painter.setRenderHint( QPainter::Antialiasing );
84 painter.setPen( QPen( Qt::black, 2 ) );
85
86 // draw a black border
87 painter.setBackgroundMode( Qt::OpaqueMode );
88 painter.drawRect( renderedImage.rect().adjusted( 1, 1, -1, -1 ) );
89
90 // draw a circle around the center (ie. where the camera is looking at)
91 const int arrowSize = 16;
92 painter.setBrush( QColor( 0, 0, 0, 50 ) );
93 painter.setPen( QPen( QColor( 0, 0, 0, 120 ), 1 ) );
94 painter.drawEllipse( center, arrowSize, arrowSize );
95
96 // draw an oriented arrow at the center
97 painter.setBrush( QColor( 0, 0, 0, 160 ) );
98 painter.setPen( Qt::NoPen );
99
100 QPolygon arrow;
101 arrow << QPoint( 0, -arrowSize ) // arrowhead
102 << QPoint( -arrowSize / 3, 0 ) // left corner
103 << QPoint( arrowSize / 3, 0 ); // right corner
104
105 painter.translate( center );
106 // Qt applies rotation in a clockwise direction with the Y-axis points downward
107 painter.rotate( -mRotation );
108 painter.drawPolygon( arrow );
109
110 if ( mShowFrustum )
111 {
112 // go back to the original position to draw the frustum
113 painter.rotate( mRotation );
114 painter.translate( -center );
115 painter.setBrush( QColor::fromRgba( qRgba( 0, 0, 255, 50 ) ) );
116 QPolygonF frustum;
117 double sizeX = mSize.width() / mExtent.width();
118 double sizeY = mSize.height() / mExtent.height();
119 for ( const QgsPointXY &frustumPoint : mFrustumExtent )
120 {
121 frustum << QPointF( ( frustumPoint.x() - mExtent.xMinimum() ) * sizeX, mSize.height() - ( frustumPoint.y() - mExtent.yMinimum() ) * sizeY );
122 }
123
124 painter.drawPolygon( frustum );
125 }
126
127 painter.end();
128
129 mActiveJob->deleteLater();
130 mActiveJob = nullptr;
131
132 QgsEventTracing::addEvent( QgsEventTracing::AsyncEnd, u"3D"_s, u"Texture"_s, QString::number( mLastJobId ) );
133
134 // pass QImage further
135 emit textureReady( renderedImage );
136}
137
138QgsMapSettings QgsMapOverlayTextureGenerator::baseMapSettings() const
139{
140 QgsMapSettings mapSettings;
141
142 mapSettings.setOutputSize( mSize );
143 mapSettings.setDestinationCrs( m3DMapSettings.sceneMode() == Qgis::SceneMode::Globe ? m3DMapSettings.crs().toGeographicCrs() : m3DMapSettings.crs() );
144 mapSettings.setBackgroundColor( m3DMapSettings.backgroundColor() );
145 mapSettings.setFlag( Qgis::MapSettingsFlag::DrawLabeling, m3DMapSettings.showLabels() );
146 mapSettings.setTransformContext( m3DMapSettings.transformContext() );
147 mapSettings.setPathResolver( m3DMapSettings.pathResolver() );
148 mapSettings.setRendererUsage( m3DMapSettings.rendererUsage() );
149 mapSettings.setLayers( m3DMapSettings.layers() );
150
151 return mapSettings;
152}
153
@ Globe
Scene is represented as a globe using a geocentric CRS.
Definition qgis.h:4252
@ DrawLabeling
Enable drawing of labels on top of the map.
Definition qgis.h:2779
Definition of the world.
void finished()
emitted when asynchronous rendering is finished (or canceled).
Job implementation that renders all layers in parallel.
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 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.
Represents a 2D point.
Definition qgspointxy.h:62
A rectangle specified with double values.