QGIS API Documentation 3.99.0-Master (09f76ad7019)
Loading...
Searching...
No Matches
qgsquickmapcanvasmap.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsquickmapcanvasmap.cpp
3 --------------------------------------
4 Date : 10.12.2014
5 Copyright : (C) 2014 by Matthias Kuhn
6 Email : matthias (at) opengis.ch
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 "qgis.h"
19#include "qgsannotationlayer.h"
21#include "qgsgrouplayer.h"
22#include "qgslabelingresults.h"
25#include "qgsmaprenderercache.h"
27#include "qgsmessagelog.h"
28#include "qgspallabeling.h"
29#include "qgsproject.h"
30#include "qgsquickmapsettings.h"
32#include "qgssymbollayerutils.h"
33#include "qgsvectorlayer.h"
34
35#include <QQuickWindow>
36#include <QSGSimpleTextureNode>
37#include <QScreen>
38#include <QString>
39
40#include "moc_qgsquickmapcanvasmap.cpp"
41
42using namespace Qt::StringLiterals;
43
45 : QQuickItem( parent )
46 , mMapSettings( std::make_unique<QgsQuickMapSettings>() )
47 , mCache( std::make_unique<QgsMapRendererCache>() )
48{
49 connect( this, &QQuickItem::windowChanged, this, &QgsQuickMapCanvasMap::onWindowChanged );
50 connect( &mRefreshTimer, &QTimer::timeout, this, [this] { refreshMap(); } );
51 connect( &mMapUpdateTimer, &QTimer::timeout, this, &QgsQuickMapCanvasMap::renderJobUpdated );
52
53 connect( mMapSettings.get(), &QgsQuickMapSettings::extentChanged, this, &QgsQuickMapCanvasMap::onExtentChanged );
54 connect( mMapSettings.get(), &QgsQuickMapSettings::layersChanged, this, &QgsQuickMapCanvasMap::onLayersChanged );
55 connect( mMapSettings.get(), &QgsQuickMapSettings::temporalStateChanged, this, &QgsQuickMapCanvasMap::onTemporalStateChanged );
56 connect( mMapSettings.get(), &QgsQuickMapSettings::zRangeChanged, this, &QgsQuickMapCanvasMap::onzRangeChanged );
57
60
61 mMapUpdateTimer.setSingleShot( false );
62 mMapUpdateTimer.setInterval( 250 );
63 mRefreshTimer.setSingleShot( true );
64 setTransformOrigin( QQuickItem::TopLeft );
65 setFlags( QQuickItem::ItemHasContents );
66}
67
69
71{
72 return mMapSettings.get();
73}
74
75void QgsQuickMapCanvasMap::zoom( QPointF center, qreal scale )
76{
77 QgsRectangle extent = mMapSettings->extent();
78 QgsPoint oldCenter( extent.center() );
79 QgsPoint mousePos( mMapSettings->screenToCoordinate( center ) );
80
81 QgsPointXY newCenter( mousePos.x() + ( ( oldCenter.x() - mousePos.x() ) * scale ), mousePos.y() + ( ( oldCenter.y() - mousePos.y() ) * scale ) );
82
83 // same as zoomWithCenter (no coordinate transformations are needed)
84 extent.scale( scale, &newCenter );
85 mMapSettings->setExtent( extent );
86}
87
88void QgsQuickMapCanvasMap::pan( QPointF oldPos, QPointF newPos )
89{
90 QgsPoint start = mMapSettings->screenToCoordinate( oldPos.toPoint() );
91 QgsPoint end = mMapSettings->screenToCoordinate( newPos.toPoint() );
92
93 double dx = end.x() - start.x();
94 double dy = end.y() - start.y();
95
96 // modify the extent
97 QgsRectangle extent = mMapSettings->extent();
98
99 extent.setXMinimum( extent.xMinimum() + dx );
100 extent.setXMaximum( extent.xMaximum() + dx );
101 extent.setYMaximum( extent.yMaximum() + dy );
102 extent.setYMinimum( extent.yMinimum() + dy );
103
104 mMapSettings->setExtent( extent );
105}
106
107void QgsQuickMapCanvasMap::refreshMap()
108{
109 stopRendering(); // if any...
110
111 if ( mCacheInvalidations.testFlag( CacheInvalidationType::Temporal ) )
112 {
113 clearTemporalCache();
114 mCacheInvalidations &= ~( static_cast<int>( CacheInvalidationType::Temporal ) );
115 }
116 if ( mCacheInvalidations.testFlag( CacheInvalidationType::Elevation ) )
117 {
118 clearElevationCache();
119 mCacheInvalidations &= ~( static_cast<int>( CacheInvalidationType::Elevation ) );
120 }
121
122 QgsMapSettings mapSettings = mMapSettings->mapSettings();
123 if ( !mapSettings.hasValidSettings() )
124 return;
125
126 //build the expression context
127 QgsExpressionContext expressionContext;
128 expressionContext << QgsExpressionContextUtils::globalScope()
130
131 QgsProject *project = mMapSettings->project();
132 if ( project )
133 {
134 expressionContext << QgsExpressionContextUtils::projectScope( project );
135
136 mapSettings.setLabelingEngineSettings( project->labelingEngineSettings() );
137 mapSettings.setSelectiveMaskingSourceSets( project->selectiveMaskingSourceSetManager()->sets() );
138
139 // render main annotation layer above all other layers
140 QList<QgsMapLayer *> allLayers = mapSettings.layers();
141 allLayers.insert( 0, project->mainAnnotationLayer() );
142 mapSettings.setLayers( allLayers );
143 }
144
145 mapSettings.setExpressionContext( expressionContext );
146
147 // enables on-the-fly simplification of geometries to spend less time rendering
149 // with incremental rendering - enables updates of partially rendered layers (good for WMTS, XYZ layers)
150 mapSettings.setFlag( Qgis::MapSettingsFlag::RenderPartialOutput, mIncrementalRendering );
151
152 // create the renderer job
153 Q_ASSERT( !mJob );
154 mJob = new QgsMapRendererParallelJob( mapSettings );
155
156 if ( mIncrementalRendering )
157 mMapUpdateTimer.start();
158
159 connect( mJob, &QgsMapRendererJob::renderingLayersFinished, this, &QgsQuickMapCanvasMap::renderJobUpdated );
160 connect( mJob, &QgsMapRendererJob::finished, this, &QgsQuickMapCanvasMap::renderJobFinished );
161 mJob->setCache( mCache.get() );
162
163 mJob->start();
164
165 if ( !mSilentRefresh )
166 {
167 emit renderStarting();
168 }
169}
170
171void QgsQuickMapCanvasMap::renderJobUpdated()
172{
173 if ( !mJob )
174 return;
175
176 mImage = mJob->renderedImage();
177 mImageMapSettings = mJob->mapSettings();
178 mDirty = true;
179 // Temporarily freeze the canvas, we only need to reset the geometry but not trigger a repaint
180 bool freeze = mFreeze;
181 mFreeze = true;
182 updateTransform();
183 mFreeze = freeze;
184
185 update();
186}
187
188void QgsQuickMapCanvasMap::renderJobFinished()
189{
190 if ( !mJob )
191 return;
192
193 const QgsMapRendererJob::Errors errors = mJob->errors();
194 for ( const QgsMapRendererJob::Error &error : errors )
195 {
196 QgsMessageLog::logMessage( u"%1 :: %2"_s.arg( error.layerID, error.message ), tr( "Rendering" ) );
197 }
198
199 // take labeling results before emitting renderComplete, so labeling map tools
200 // connected to signal work with correct results
201 delete mLabelingResults;
202 mLabelingResults = mJob->takeLabelingResults();
203
204 mImage = mJob->renderedImage();
205 mImageMapSettings = mJob->mapSettings();
206
207 // now we are in a slot called from mJob - do not delete it immediately
208 // so the class is still valid when the execution returns to the class
209 mJob->deleteLater();
210 mJob = nullptr;
211 mDirty = true;
212 mMapUpdateTimer.stop();
213
214 // Temporarily freeze the canvas, we only need to reset the geometry but not trigger a repaint
215 bool freeze = mFreeze;
216 mFreeze = true;
217 updateTransform();
218 mFreeze = freeze;
219
220 update();
221 if ( !mSilentRefresh )
222 {
223 emit mapCanvasRefreshed();
224 }
225 else
226 {
227 mSilentRefresh = false;
228 }
229
230 if ( mDeferredRefreshPending )
231 {
232 mDeferredRefreshPending = false;
233 mSilentRefresh = true;
234 refresh();
235 }
236}
237
238void QgsQuickMapCanvasMap::layerRepaintRequested( bool deferred )
239{
240 if ( mMapSettings->outputSize().isNull() )
241 return; // the map image size has not been set yet
242
243 if ( !mFreeze )
244 {
245 if ( deferred )
246 {
247 if ( !mJob )
248 {
249 mSilentRefresh = true;
250 refresh();
251 }
252 else
253 {
254 mDeferredRefreshPending = true;
255 }
256 }
257 else
258 {
259 refresh();
260 }
261 }
262}
263
264void QgsQuickMapCanvasMap::onWindowChanged( QQuickWindow *window )
265{
266 if ( mWindow == window )
267 return;
268
269 if ( mWindow )
270 disconnect( mWindow, &QQuickWindow::screenChanged, this, &QgsQuickMapCanvasMap::onScreenChanged );
271
272 if ( window )
273 {
274 connect( window, &QQuickWindow::screenChanged, this, &QgsQuickMapCanvasMap::onScreenChanged );
275 onScreenChanged( window->screen() );
276 }
277
278 mWindow = window;
279}
280
281void QgsQuickMapCanvasMap::onScreenChanged( QScreen *screen )
282{
283 if ( screen )
284 {
285 if ( screen->devicePixelRatio() > 0 )
286 {
287 mMapSettings->setDevicePixelRatio( screen->devicePixelRatio() );
288 }
289 mMapSettings->setOutputDpi( screen->physicalDotsPerInch() );
290 }
291}
292
293void QgsQuickMapCanvasMap::onExtentChanged()
294{
295 updateTransform();
296
297 // And trigger a new rendering job
298 refresh();
299}
300
301void QgsQuickMapCanvasMap::onTemporalStateChanged()
302{
303 mCacheInvalidations |= CacheInvalidationType::Temporal;
304
305 // And trigger a new rendering job
306 refresh();
307}
308
309void QgsQuickMapCanvasMap::onzRangeChanged()
310{
311 mCacheInvalidations |= CacheInvalidationType::Elevation;
312
313 // And trigger a new rendering job
314 refresh();
315}
316
317void QgsQuickMapCanvasMap::updateTransform()
318{
319 QgsRectangle imageExtent = mImageMapSettings.visibleExtent();
320 QgsRectangle newExtent = mMapSettings->mapSettings().visibleExtent();
321 setScale( imageExtent.width() / newExtent.width() );
322
323 QgsPointXY pixelPt = mMapSettings->coordinateToScreen( QgsPoint( imageExtent.xMinimum(), imageExtent.yMaximum() ) );
324 setX( pixelPt.x() );
325 setY( pixelPt.y() );
326}
327
329{
330 return mMapUpdateTimer.interval();
331}
332
334{
335 if ( mMapUpdateTimer.interval() == mapUpdateInterval )
336 return;
337
338 mMapUpdateTimer.setInterval( mapUpdateInterval );
339
341}
342
344{
345 return mIncrementalRendering;
346}
347
349{
350 if ( incrementalRendering == mIncrementalRendering )
351 return;
352
353 mIncrementalRendering = incrementalRendering;
355}
356
358{
359 return mFreeze;
360}
361
363{
364 if ( freeze == mFreeze )
365 return;
366
367 mFreeze = freeze;
368
369 if ( mFreeze )
371 else
372 refresh();
373
374 emit freezeChanged();
375}
376
378{
379 return mJob;
380}
381
382QSGNode *QgsQuickMapCanvasMap::updatePaintNode( QSGNode *oldNode, QQuickItem::UpdatePaintNodeData * )
383{
384 if ( mDirty )
385 {
386 delete oldNode;
387 oldNode = nullptr;
388 mDirty = false;
389 }
390
391 if ( mImage.isNull() )
392 {
393 return nullptr;
394 }
395
396 QSGSimpleTextureNode *node = static_cast<QSGSimpleTextureNode *>( oldNode );
397 if ( !node )
398 {
399 node = new QSGSimpleTextureNode();
400 QSGTexture *texture = window()->createTextureFromImage( mImage );
401 node->setTexture( texture );
402 node->setOwnsTexture( true );
403 }
404
405 QRectF rect( boundingRect() );
406 QSizeF size = mImage.size();
407 if ( !size.isEmpty() )
408 size /= mMapSettings->devicePixelRatio();
409
410 // Check for resizes that change the w/h ratio
411 if ( !rect.isEmpty() && !size.isEmpty() && !qgsDoubleNear( rect.width() / rect.height(), ( size.width() ) / static_cast<double>( size.height() ), 3 ) )
412 {
413 if ( qgsDoubleNear( rect.height(), mImage.height() ) )
414 {
415 rect.setHeight( rect.width() / size.width() * size.height() );
416 }
417 else
418 {
419 rect.setWidth( rect.height() / size.height() * size.width() );
420 }
421 }
422
423 node->setRect( rect );
424
425 return node;
426}
427
428void QgsQuickMapCanvasMap::geometryChange( const QRectF &newGeometry, const QRectF &oldGeometry )
429{
430 QQuickItem::geometryChange( newGeometry, oldGeometry );
431 if ( newGeometry.size() != oldGeometry.size() )
432 {
433 mMapSettings->setOutputSize( newGeometry.size().toSize() );
434 refresh();
435 }
436}
437
438void QgsQuickMapCanvasMap::onLayersChanged()
439{
440 if ( mMapSettings->extent().isEmpty() )
441 zoomToFullExtent();
442
443 for ( const QMetaObject::Connection &conn : std::as_const( mLayerConnections ) )
444 {
445 disconnect( conn );
446 }
447 mLayerConnections.clear();
448
449 const QList<QgsMapLayer *> layers = mMapSettings->layers();
450 for ( QgsMapLayer *layer : layers )
451 {
452 mLayerConnections << connect( layer, &QgsMapLayer::repaintRequested, this, &QgsQuickMapCanvasMap::layerRepaintRequested );
453 }
454
455 refresh();
456}
457
458void QgsQuickMapCanvasMap::destroyJob( QgsMapRendererJob *job )
459{
460 job->cancel();
461 job->deleteLater();
462}
463
465{
466 if ( mJob )
467 {
468 disconnect( mJob, &QgsMapRendererJob::renderingLayersFinished, this, &QgsQuickMapCanvasMap::renderJobUpdated );
469 disconnect( mJob, &QgsMapRendererJob::finished, this, &QgsQuickMapCanvasMap::renderJobFinished );
470
471 mJob->cancelWithoutBlocking();
472 mJob = nullptr;
473 }
474}
475
476void QgsQuickMapCanvasMap::zoomToFullExtent()
477{
478 QgsRectangle extent;
479 const QList<QgsMapLayer *> layers = mMapSettings->layers();
480 for ( QgsMapLayer *layer : layers )
481 {
482 if ( mMapSettings->destinationCrs() != layer->crs() )
483 {
484 QgsCoordinateTransform transform( layer->crs(), mMapSettings->destinationCrs(), mMapSettings->transformContext() );
485 try
486 {
487 extent.combineExtentWith( transform.transformBoundingBox( layer->extent() ) );
488 }
489 catch ( const QgsCsException &exp )
490 {
491 // Ignore extent if it can't be transformed
492 }
493 }
494 else
495 {
496 extent.combineExtentWith( layer->extent() );
497 }
498 }
499 mMapSettings->setExtent( extent );
500
501 refresh();
502}
503
505{
506 if ( mMapSettings->outputSize().isNull() )
507 return; // the map image size has not been set yet
508
509 if ( !mFreeze )
510 mRefreshTimer.start( 1 );
511}
512
514{
515 if ( mCache )
516 mCache->clear();
517}
518
519void QgsQuickMapCanvasMap::clearTemporalCache()
520{
521 if ( mCache )
522 {
523 bool invalidateLabels = false;
524 const QList<QgsMapLayer *> layerList = mMapSettings->mapSettings().layers();
525 for ( QgsMapLayer *layer : layerList )
526 {
527 bool alreadyInvalidatedThisLayer = false;
528 if ( QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer ) )
529 {
530 if ( vl->renderer() && QgsSymbolLayerUtils::rendererFrameRate( vl->renderer() ) > -1 )
531 {
532 // layer has an animated symbol assigned, so we have to redraw it regardless of whether
533 // or not it has temporal settings
534 mCache->invalidateCacheForLayer( layer );
535 alreadyInvalidatedThisLayer = true;
536 // we can't shortcut and "continue" here, as we still need to check whether the layer
537 // will cause label invalidation using the logic below
538 }
539 }
540
541 if ( layer->temporalProperties() && layer->temporalProperties()->isActive() )
542 {
543 if ( QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer ) )
544 {
545 if ( vl->labelsEnabled() || vl->diagramsEnabled() )
546 invalidateLabels = true;
547 }
548
549 if ( layer->temporalProperties()->flags() & QgsTemporalProperty::FlagDontInvalidateCachedRendersWhenRangeChanges )
550 continue;
551
552 if ( !alreadyInvalidatedThisLayer )
553 mCache->invalidateCacheForLayer( layer );
554 }
555 else if ( QgsGroupLayer *gl = qobject_cast<QgsGroupLayer *>( layer ) )
556 {
557 const QList<QgsMapLayer *> childLayerList = gl->childLayers();
558 for ( QgsMapLayer *childLayer : childLayerList )
559 {
560 if ( childLayer->temporalProperties() && childLayer->temporalProperties()->isActive() )
561 {
562 if ( childLayer->temporalProperties()->flags() & QgsTemporalProperty::FlagDontInvalidateCachedRendersWhenRangeChanges )
563 continue;
564
565 mCache->invalidateCacheForLayer( layer );
566 break;
567 }
568 }
569 }
570 }
571
572 if ( invalidateLabels )
573 {
574 mCache->clearCacheImage( u"_labels_"_s );
575 mCache->clearCacheImage( u"_preview_labels_"_s );
576 }
577 }
578}
579
580void QgsQuickMapCanvasMap::clearElevationCache()
581{
582 if ( mCache )
583 {
584 bool invalidateLabels = false;
585 const QList<QgsMapLayer *> layerList = mMapSettings->mapSettings().layers();
586 for ( QgsMapLayer *layer : layerList )
587 {
588 if ( layer->elevationProperties() && layer->elevationProperties()->hasElevation() )
589 {
590 if ( QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer ) )
591 {
592 if ( vl->labelsEnabled() || vl->diagramsEnabled() )
593 invalidateLabels = true;
594 }
595
597 continue;
598
599 mCache->invalidateCacheForLayer( layer );
600 }
601 else if ( QgsGroupLayer *gl = qobject_cast<QgsGroupLayer *>( layer ) )
602 {
603 const QList<QgsMapLayer *> childLayerList = gl->childLayers();
604 for ( QgsMapLayer *childLayer : childLayerList )
605 {
606 if ( childLayer->elevationProperties() && childLayer->elevationProperties()->hasElevation() )
607 {
608 if ( childLayer->elevationProperties()->flags() & QgsMapLayerElevationProperties::FlagDontInvalidateCachedRendersWhenRangeChanges )
609 continue;
610
611 mCache->invalidateCacheForLayer( layer );
612 break;
613 }
614 }
615 }
616 }
617
618 if ( invalidateLabels )
619 {
620 mCache->clearCacheImage( u"_labels_"_s );
621 mCache->clearCacheImage( u"_preview_labels_"_s );
622 }
623 }
624}
@ UseRenderingOptimization
Enable vector simplification and other rendering optimizations.
Definition qgis.h:2780
@ RenderPartialOutput
Whether to make extra effort to update map image with partially rendered layers (better for interacti...
Definition qgis.h:2784
Handles coordinate transforms between two coordinate systems.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
@ FlagDontInvalidateCachedRendersWhenRangeChanges
Any cached rendering will not be invalidated when z range context is modified.
Base class for all map layer types.
Definition qgsmaplayer.h:83
void repaintRequested(bool deferredUpdate=false)
By emitting this signal the layer tells that either appearance or content have been changed and any v...
Responsible for keeping a cache of rendered images resulting from a map rendering job.
Abstract base class for map rendering implementations.
void renderingLayersFinished()
Emitted when the layers are rendered.
void finished()
emitted when asynchronous rendering is finished (or canceled).
QList< QgsMapRendererJob::Error > Errors
virtual void cancel()=0
Stop the rendering job - does not return until the job has terminated.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
Represents a 2D point.
Definition qgspointxy.h:62
double y
Definition qgspointxy.h:66
double x
Definition qgspointxy.h:65
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:53
double x
Definition qgspoint.h:56
double y
Definition qgspoint.h:57
QgsAnnotationLayer * mainAnnotationLayer()
Returns the main annotation layer associated with the project.
const QgsLabelingEngineSettings & labelingEngineSettings() const
Returns project's global labeling engine settings.
const QgsSelectiveMaskingSourceSetManager * selectiveMaskingSourceSetManager() const
Returns the project's selective masking set manager, which manages storage of a set of selective mask...
void freezeChanged()
When freeze property is set to true, the map canvas does not refresh.
bool isRendering
The isRendering property is set to true while a rendering job is pending for this map canvas map.
void mapCanvasRefreshed()
Signal is emitted when a canvas is refreshed.
void incrementalRenderingChanged()
When the incrementalRendering property is set to true, the automatic refresh of map canvas during ren...
int mapUpdateInterval
Interval in milliseconds after which the map canvas will be updated while a rendering job is ongoing.
void setMapUpdateInterval(int mapUpdateInterval)
Interval in milliseconds after which the map canvas will be updated while a rendering job is ongoing.
void pan(QPointF oldPos, QPointF newPos)
Set map setting's extent (pan the map) based on the difference of positions.
void renderStarting()
Signal is emitted when a rendering is starting.
void stopRendering()
Stop map rendering.
~QgsQuickMapCanvasMap() override
void zoom(QPointF center, qreal scale)
Set map setting's extent (zoom the map) on the center by given scale.
void setIncrementalRendering(bool incrementalRendering)
When the incrementalRendering property is set to true, the automatic refresh of map canvas during ren...
void clearCache()
Clears rendering cache.
void setFreeze(bool freeze)
When freeze property is set to true, the map canvas does not refresh.
QgsQuickMapSettings * mapSettings
The mapSettings property contains configuration for rendering of the map.
void refresh()
Refresh the map canvas.
QSGNode * updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *) override
void mapUpdateIntervalChanged()
Interval in milliseconds after which the map canvas will be updated while a rendering job is ongoing.
bool incrementalRendering
When the incrementalRendering property is set to true, the automatic refresh of map canvas during ren...
bool freeze
When freeze property is set to true, the map canvas does not refresh.
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override
QgsQuickMapCanvasMap(QQuickItem *parent=nullptr)
Create map canvas map.
void isRenderingChanged()
The isRendering property is set to true while a rendering job is pending for this map canvas map.
Encapsulates QgsMapSettings class to offer settings of configuration of map rendering via QML propert...
void extentChanged()
Geographical coordinates of the rectangle that should be rendered.
void layersChanged()
Set list of layers for map rendering.
void temporalStateChanged()
Emitted when the temporal state has changed.
void zRangeChanged()
Emitted when the Z range has changed.
A rectangle specified with double values.
void scale(double scaleFactor, const QgsPointXY *c=nullptr)
Scale the rectangle around its center point.
double xMinimum
double yMinimum
double xMaximum
void setYMinimum(double y)
Set the minimum y value.
void setXMinimum(double x)
Set the minimum x value.
void setYMaximum(double y)
Set the maximum y value.
void setXMaximum(double x)
Set the maximum x value.
double yMaximum
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
QgsPointXY center
QVector< QgsSelectiveMaskingSourceSet > sets() const
Returns a list of all sets contained in the manager.
static double rendererFrameRate(const QgsFeatureRenderer *renderer)
Calculates the frame rate (in frames per second) at which the given renderer must be redrawn.
@ FlagDontInvalidateCachedRendersWhenRangeChanges
Any cached rendering will not be invalidated when temporal range context is modified.
Represents a vector layer which manages a vector based dataset.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6935