QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgstemporalutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgstemporalutils.cpp
3  -----------------------
4  Date : March 2020
5  Copyright : (C) 2020 by Nyall Dawson
6  Email : nyall dot dawson 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 
16 #include "qgstemporalutils.h"
17 #include "qgsproject.h"
19 #include "qgsrasterlayer.h"
20 #include "qgsmeshlayer.h"
21 #include "qgsvectorlayer.h"
26 #include "qgsmapdecoration.h"
27 #include "qgsmapsettings.h"
30 
32 {
33  const QMap<QString, QgsMapLayer *> &mapLayers = project->mapLayers();
34  QgsMapLayer *currentLayer = nullptr;
35 
36  QDateTime minDate;
37  QDateTime maxDate;
38 
39  for ( QMap<QString, QgsMapLayer *>::const_iterator it = mapLayers.constBegin(); it != mapLayers.constEnd(); ++it )
40  {
41  currentLayer = it.value();
42 
43  if ( !currentLayer->temporalProperties() || !currentLayer->temporalProperties()->isActive() )
44  continue;
45  QgsDateTimeRange layerRange = currentLayer->temporalProperties()->calculateTemporalExtent( currentLayer );
46 
47  if ( layerRange.begin().isValid() && ( !minDate.isValid() || layerRange.begin() < minDate ) )
48  minDate = layerRange.begin();
49  if ( layerRange.end().isValid() && ( !maxDate.isValid() || layerRange.end() > maxDate ) )
50  maxDate = layerRange.end();
51  }
52 
53  return QgsDateTimeRange( minDate, maxDate );
54 }
55 
56 bool QgsTemporalUtils::exportAnimation( const QgsMapSettings &mapSettings, const QgsTemporalUtils::AnimationExportSettings &settings, QString &error, QgsFeedback *feedback )
57 {
58  if ( settings.fileNameTemplate.isEmpty() )
59  {
60  error = QObject::tr( "Filename template is empty" );
61  return false;
62  }
63  int numberOfDigits = settings.fileNameTemplate.count( QLatin1Char( '#' ) );
64  if ( numberOfDigits < 0 )
65  {
66  error = QObject::tr( "Wrong filename template format (must contain #)" );
67  return false;
68  }
69  const QString token( numberOfDigits, QLatin1Char( '#' ) );
70  if ( !settings.fileNameTemplate.contains( token ) )
71  {
72  error = QObject::tr( "Filename template must contain all # placeholders in one continuous group." );
73  return false;
74  }
75  if ( !QDir().mkpath( settings.outputDirectory ) )
76  {
77  error = QObject::tr( "Output directory creation failure." );
78  return false;
79  }
80 
82  navigator.setTemporalExtents( settings.animationRange );
83  navigator.setFrameDuration( settings.frameDuration );
84  QgsMapSettings ms = mapSettings;
85  const QgsExpressionContext context = ms.expressionContext();
86 
87  const long long totalFrames = navigator.totalFrameCount();
88  long long currentFrame = 0;
89 
90  while ( currentFrame < totalFrames )
91  {
92  if ( feedback )
93  {
94  if ( feedback->isCanceled() )
95  {
96  error = QObject::tr( "Export canceled" );
97  return false;
98  }
99  feedback->setProgress( currentFrame / static_cast<double>( totalFrames ) * 100 );
100  }
101  ++currentFrame;
102 
103  navigator.setCurrentFrameNumber( currentFrame );
104 
105  ms.setIsTemporal( true );
106  ms.setTemporalRange( navigator.dateTimeRangeForFrameNumber( currentFrame ) );
107 
108  QgsExpressionContext frameContext = context;
109  frameContext.appendScope( navigator.createExpressionContextScope() );
111  ms.setExpressionContext( frameContext );
112 
113  QString fileName( settings.fileNameTemplate );
114  const QString frameNoPaddedLeft( QStringLiteral( "%1" ).arg( currentFrame, numberOfDigits, 10, QChar( '0' ) ) ); // e.g. 0001
115  fileName.replace( token, frameNoPaddedLeft );
116  const QString path = QDir( settings.outputDirectory ).filePath( fileName );
117 
118  QImage img = QImage( ms.outputSize(), ms.outputImageFormat() );
119  img.setDotsPerMeterX( 1000 * ms.outputDpi() / 25.4 );
120  img.setDotsPerMeterY( 1000 * ms.outputDpi() / 25.4 );
121  img.fill( ms.backgroundColor().rgb() );
122 
123  QPainter p( &img );
124  QgsMapRendererCustomPainterJob job( ms, &p );
125  job.start();
126  job.waitForFinished();
127 
129  context.setPainter( &p );
130 
131  const auto constMDecorations = settings.decorations;
132  for ( QgsMapDecoration *decoration : constMDecorations )
133  {
134  decoration->render( ms, context );
135  }
136 
137  p.end();
138 
139  img.save( path );
140  }
141 
142  return true;
143 }
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:370
qgsexpressioncontextutils.h
QgsFeedback::setProgress
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:62
QgsTemporalUtils::exportAnimation
static bool exportAnimation(const QgsMapSettings &mapSettings, const AnimationExportSettings &settings, QString &error, QgsFeedback *feedback=nullptr)
Exports animation frames by rendering the map to multiple destination images.
Definition: qgstemporalutils.cpp:56
qgsrasterlayer.h
QgsMapRendererCustomPainterJob::waitForFinished
void waitForFinished() override
Block until the job has finished.
Definition: qgsmaprenderercustompainterjob.cpp:172
QgsMapSettings::outputSize
QSize outputSize() const
Returns the size of the resulting map image.
Definition: qgsmapsettings.cpp:235
QgsRenderContext::fromMapSettings
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
Definition: qgsrendercontext.cpp:197
QgsTemporalUtils::AnimationExportSettings
Contains settings relating to exporting animations.
Definition: qgstemporalutils.h:50
QgsProject::mapLayers
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
Definition: qgsproject.cpp:3436
QgsTemporalRangeObject::setIsTemporal
void setIsTemporal(bool enabled)
Sets whether the temporal range is enabled (i.e.
Definition: qgstemporalrangeobject.cpp:25
QgsRenderContext::setPainter
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
Definition: qgsrendercontext.h:491
qgstemporalnavigationobject.h
QgsExpressionContextUtils::mapSettingsScope
static QgsExpressionContextScope * mapSettingsScope(const QgsMapSettings &mapSettings)
Creates a new scope which contains variables and functions relating to a QgsMapSettings object.
Definition: qgsexpressioncontextutils.cpp:357
qgsmaprenderercustompainterjob.h
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:58
QgsTemporalNavigationObject::dateTimeRangeForFrameNumber
QgsDateTimeRange dateTimeRangeForFrameNumber(long long frame) const
Calculates the temporal range associated with a particular animation frame.
Definition: qgstemporalnavigationobject.cpp:84
QgsMapLayerTemporalProperties::calculateTemporalExtent
virtual QgsDateTimeRange calculateTemporalExtent(QgsMapLayer *layer) const
Attempts to calculate the overall temporal extent for the specified layer, using the settings defined...
Definition: qgsmaplayertemporalproperties.cpp:30
QgsMapSettings::outputImageFormat
QImage::Format outputImageFormat() const
format of internal QImage, default QImage::Format_ARGB32_Premultiplied
Definition: qgsmapsettings.h:361
QgsTemporalUtils::AnimationExportSettings::animationRange
QgsDateTimeRange animationRange
Dictates the overall temporal range of the animation.
Definition: qgstemporalutils.h:52
QgsTemporalNavigationObject::setFrameDuration
void setFrameDuration(QgsInterval duration)
Sets the frame duration, which dictates the temporal length of each frame in the animation.
Definition: qgstemporalnavigationobject.cpp:185
qgsmapsettings.h
QgsMapRendererCustomPainterJob::start
void start() override
Start the rendering job and immediately return.
Definition: qgsmaprenderercustompainterjob.cpp:78
QgsProject
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:95
qgsmapdecoration.h
qgsmaplayertemporalproperties.h
qgsvectorlayertemporalproperties.h
QgsTemporalUtils::AnimationExportSettings::outputDirectory
QString outputDirectory
Destination directory for created image files.
Definition: qgstemporalutils.h:58
QgsTemporalProperty::isActive
bool isActive() const
Returns true if the temporal property is active.
Definition: qgstemporalproperty.cpp:36
QgsTemporalNavigationObject::setCurrentFrameNumber
void setCurrentFrameNumber(long long frame)
Sets the current animation frame number.
Definition: qgstemporalnavigationobject.cpp:168
QgsFeedback
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:44
QgsTemporalNavigationObject::setTemporalExtents
void setTemporalExtents(const QgsDateTimeRange &extents)
Sets the navigation temporal extents, which dictate the earliest and latest date time possible in the...
Definition: qgstemporalnavigationobject.cpp:132
QgsTemporalUtils::AnimationExportSettings::fileNameTemplate
QString fileNameTemplate
The filename template for exporting the frames.
Definition: qgstemporalutils.h:67
QgsMapSettings::backgroundColor
QColor backgroundColor() const
Gets the background color of the map.
Definition: qgsmapsettings.h:293
QgsMapLayer::temporalProperties
virtual QgsMapLayerTemporalProperties * temporalProperties()
Returns the layer's temporal properties.
Definition: qgsmaplayer.h:1203
QgsTemporalNavigationObject::createExpressionContextScope
QgsExpressionContextScope * createExpressionContextScope() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Definition: qgstemporalnavigationobject.cpp:72
QgsTemporalNavigationObject::totalFrameCount
long long totalFrameCount()
Returns the total number of frames for the navigation.
Definition: qgstemporalnavigationobject.cpp:291
QgsMapSettings::expressionContext
const QgsExpressionContext & expressionContext() const
Gets the expression context.
Definition: qgsmapsettings.h:396
QgsTemporalNavigationObject
Implements a temporal controller based on a frame by frame navigation and animation.
Definition: qgstemporalnavigationobject.h:40
qgstemporalutils.h
QgsExpressionContext::appendScope
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Definition: qgsexpressioncontext.cpp:490
qgsmeshlayer.h
qgsvectorlayer.h
QgsMapRendererCustomPainterJob
Job implementation that renders everything sequentially using a custom painter.
Definition: qgsmaprenderercustompainterjob.h:64
QgsFeedback::isCanceled
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:53
QgsTemporalUtils::AnimationExportSettings::frameDuration
QgsInterval frameDuration
Duration of individual export frames.
Definition: qgstemporalutils.h:55
QgsMapSettings::setExpressionContext
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
Definition: qgsmapsettings.h:388
QgsMapLayer
Base class for all map layer types.
Definition: qgsmaplayer.h:83
QgsTemporalRangeObject::setTemporalRange
void setTemporalRange(const QgsDateTimeRange &range)
Sets the temporal range for the object.
Definition: qgstemporalrangeobject.cpp:35
qgsrasterlayertemporalproperties.h
QgsMapDecoration
Interface for map decorations.
Definition: qgsmapdecoration.h:33
QgsMapSettings::outputDpi
double outputDpi() const
Returns DPI used for conversion between real world units (e.g.
Definition: qgsmapsettings.cpp:263
QgsMapSettings
The QgsMapSettings class contains configuration for rendering of the map.
Definition: qgsmapsettings.h:88
QgsTemporalUtils::AnimationExportSettings::decorations
QList< QgsMapDecoration * > decorations
List of decorations to draw onto exported frames.
Definition: qgstemporalutils.h:70
qgsproject.h
qgsmeshlayertemporalproperties.h
QgsTemporalUtils::calculateTemporalRangeForProject
static QgsDateTimeRange calculateTemporalRangeForProject(QgsProject *project)
Calculates the temporal range for a project.
Definition: qgstemporalutils.cpp:31