QGIS API Documentation 3.41.0-Master (cea29feecf2)
Loading...
Searching...
No Matches
qgsrasterlayertemporalproperties.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsrasterlayertemporalproperties.cpp
3 ---------------
4 begin : February 2020
5 copyright : (C) 2020 by Samweli Mwakisambwe
6 email : samweli at kartoza dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19#include "moc_qgsrasterlayertemporalproperties.cpp"
21#include "qgsrasterlayer.h"
22
24 : QgsMapLayerTemporalProperties( parent, enabled )
25{
26 mTemporalRepresentationScale.setDays( 1.0 );
27}
28
30{
31 if ( !isActive() )
32 return true;
33
34 switch ( mMode )
35 {
37 return range.isInfinite() || mFixedRange.isInfinite() || mFixedRange.overlaps( range );
38
40 {
41 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
42 {
43 if ( it.value().overlaps( range ) )
44 return true;
45 }
46 return false;
47 }
48
52 return true;
53 }
54 return true;
55}
56
58{
59 QgsRasterLayer *rasterLayer = qobject_cast< QgsRasterLayer *>( layer );
60 if ( !rasterLayer )
61 return QgsDateTimeRange();
62
63 switch ( mMode )
64 {
66 return mFixedRange;
67
70
72 {
73 QDateTime begin;
74 QDateTime end;
75 bool includeBeginning = true;
76 bool includeEnd = true;
77 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
78 {
79 if ( it.value().begin() < begin || !begin.isValid() )
80 {
81 begin = it.value().begin();
82 includeBeginning = it.value().includeBeginning();
83 }
84 else if ( !includeBeginning && it.value().begin() == begin && it.value().includeBeginning() )
85 {
86 includeBeginning = true;
87 }
88 if ( it.value().end() > end || !end.isValid() )
89 {
90 end = it.value().end();
91 includeEnd = it.value().includeEnd();
92 }
93 else if ( !includeEnd && it.value().end() == end && it.value().includeEnd() )
94 {
95 includeEnd = true;
96 }
97 }
98 return QgsDateTimeRange( begin, end, includeBeginning, includeEnd );
99 }
100
103 break;
104 }
105
106 return QgsDateTimeRange();
107}
108
110{
111 QgsRasterLayer *rasterLayer = qobject_cast< QgsRasterLayer *>( layer );
112
113 switch ( mMode )
114 {
116 return { mFixedRange };
117
119 {
120 QList<QgsDateTimeRange> results;
121 results.reserve( mRangePerBand.size() );
122 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
123 {
124 results.append( it.value() );
125 }
126 return results;
127 }
128
130 {
131 if ( !rasterLayer || !rasterLayer->dataProvider() )
132 return {};
133
134 const QList< QgsDateTimeRange > ranges = rasterLayer->dataProvider()->temporalCapabilities()->allAvailableTemporalRanges();
135 return ranges.empty() ? QList< QgsDateTimeRange > { rasterLayer->dataProvider()->temporalCapabilities()->availableTemporalRange() } : ranges;
136 }
137
140 break;
141 }
142
143 return {};
144}
145
150
152{
153 if ( mMode == mode )
154 return;
155 mMode = mode;
156}
157
173
178
180{
181 if ( mIntervalHandlingMethod == method )
182 return;
183 mIntervalHandlingMethod = method;
184}
185
187{
188 mFixedRange = range;
189}
190
192{
193 return mFixedRange;
194}
195
197{
198 return mRangePerBand;
199}
200
201void QgsRasterLayerTemporalProperties::setFixedRangePerBand( const QMap<int, QgsDateTimeRange> &ranges )
202{
203 if ( mRangePerBand == ranges )
204 return;
205
206 mRangePerBand = ranges;
207 emit changed();
208}
209
211{
212 switch ( mMode )
213 {
217 return -1;
218
220 {
221 // find the latest-most band which matches the map range
222 int currentMatchingBand = -1;
223 QgsDateTimeRange currentMatchingRange;
224 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
225 {
226 if ( it.value().overlaps( range ) )
227 {
228 if ( currentMatchingRange.isInfinite()
229 || ( it.value().includeEnd() && it.value().end() >= currentMatchingRange.end() ) // cppcheck-suppress mismatchingContainerExpression
230 || ( !currentMatchingRange.includeEnd() && it.value().end() >= currentMatchingRange.end() ) ) // cppcheck-suppress mismatchingContainerExpression
231 {
232 currentMatchingBand = it.key();
233 currentMatchingRange = it.value();
234 }
235 }
236 }
237 return currentMatchingBand;
238 }
239
241 return mBandNumber;
242 }
244}
245
247{
248 switch ( mMode )
249 {
253 {
254 const int bandCount = layer->bandCount();
255 QList< int > res;
256 res.reserve( bandCount );
257 for ( int i = 1; i <= bandCount; ++i )
258 res.append( i );
259 return res;
260 }
261
263 {
264 QList<int> res;
265 res.reserve( mRangePerBand.size() );
266 // find the latest-most band which matches the map range
267 QgsDateTimeRange currentMatchingRange;
268 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
269 {
270 if ( it.value().overlaps( range ) )
271 {
272 res.append( it.key() );
273 }
274 }
275 return res;
276 }
277
279 return QList<int>() << mBandNumber;
280 }
282}
283
285{
286 return mBandNumber;
287}
288
290{
291 if ( mBandNumber == number )
292 return;
293
294 mBandNumber = number;
295}
296
298{
299 return mTemporalRepresentationOffset;
300}
301
303{
304 if ( mTemporalRepresentationOffset == offset )
305 return;
306
307 mTemporalRepresentationOffset = offset;
308}
309
311{
312 return mTemporalRepresentationScale;
313}
314
316{
317 if ( mTemporalRepresentationScale == scale )
318 return;
319
320 mTemporalRepresentationScale = scale;
321}
322
323bool QgsRasterLayerTemporalProperties::readXml( const QDomElement &element, const QgsReadWriteContext &context )
324{
325 Q_UNUSED( context )
326 // TODO add support for raster layers with multi-temporal properties.
327
328 const QDomElement temporalNode = element.firstChildElement( QStringLiteral( "temporal" ) );
329
330 setIsActive( temporalNode.attribute( QStringLiteral( "enabled" ), QStringLiteral( "0" ) ).toInt() );
331
332 mMode = static_cast< Qgis::RasterTemporalMode >( temporalNode.attribute( QStringLiteral( "mode" ), QStringLiteral( "0" ) ). toInt() );
333 mBandNumber = temporalNode.attribute( QStringLiteral( "bandNumber" ), QStringLiteral( "1" ) ).toInt();
334 mIntervalHandlingMethod = static_cast< Qgis::TemporalIntervalMatchMethod >( temporalNode.attribute( QStringLiteral( "fetchMode" ), QStringLiteral( "0" ) ). toInt() );
335
336 switch ( mMode )
337 {
339 {
340 const QDomNode rangeElement = temporalNode.namedItem( QStringLiteral( "fixedRange" ) );
341
342 const QDomNode begin = rangeElement.namedItem( QStringLiteral( "start" ) );
343 const QDomNode end = rangeElement.namedItem( QStringLiteral( "end" ) );
344
345 const QDateTime beginDate = QDateTime::fromString( begin.toElement().text(), Qt::ISODate );
346 const QDateTime endDate = QDateTime::fromString( end.toElement().text(), Qt::ISODate );
347
348 const QgsDateTimeRange range = QgsDateTimeRange( beginDate, endDate );
349 setFixedTemporalRange( range );
350 break;
351 }
352
354 {
355 mRangePerBand.clear();
356
357 const QDomNodeList ranges = temporalNode.firstChildElement( QStringLiteral( "ranges" ) ).childNodes();
358 for ( int i = 0; i < ranges.size(); ++i )
359 {
360 const QDomElement rangeElement = ranges.at( i ).toElement();
361 const int band = rangeElement.attribute( QStringLiteral( "band" ) ).toInt();
362 const QDateTime begin = QDateTime::fromString( rangeElement.attribute( QStringLiteral( "begin" ) ), Qt::ISODate );
363 const QDateTime end = QDateTime::fromString( rangeElement.attribute( QStringLiteral( "end" ) ), Qt::ISODate );
364 const bool includeBeginning = rangeElement.attribute( QStringLiteral( "includeBeginning" ) ).toInt();
365 const bool includeEnd = rangeElement.attribute( QStringLiteral( "includeEnd" ) ).toInt();
366 mRangePerBand.insert( band, QgsDateTimeRange( begin, end, includeBeginning, includeEnd ) );
367 }
368 break;
369 }
370
372 {
373 mTemporalRepresentationOffset = QDateTime::fromString( temporalNode.attribute( QStringLiteral( "temporalRepresentationOffset" ) ), Qt::ISODate );
374 mTemporalRepresentationScale = QgsInterval( temporalNode.attribute( QStringLiteral( "temporalRepresentationScale" ), QStringLiteral( "1" ) ).toDouble(),
375 static_cast< Qgis::TemporalUnit >( temporalNode.attribute( QStringLiteral( "temporalRepresentationScaleUnit" ), QStringLiteral( "4" ) ).toInt() ) );
376 break;
377 }
378
381 break;
382 }
383
384 return true;
385}
386
387QDomElement QgsRasterLayerTemporalProperties::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context )
388{
389 Q_UNUSED( context )
390 if ( element.isNull() )
391 return QDomElement();
392
393 QDomElement temporalElement = document.createElement( QStringLiteral( "temporal" ) );
394 temporalElement.setAttribute( QStringLiteral( "enabled" ), isActive() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
395 temporalElement.setAttribute( QStringLiteral( "mode" ), QString::number( static_cast< int >( mMode ) ) );
396 temporalElement.setAttribute( QStringLiteral( "bandNumber" ), QString::number( mBandNumber ) );
397 temporalElement.setAttribute( QStringLiteral( "fetchMode" ), QString::number( static_cast< int >( mIntervalHandlingMethod ) ) );
398
399 switch ( mMode )
400 {
402 {
403
404 QDomElement rangeElement = document.createElement( QStringLiteral( "fixedRange" ) );
405
406 QDomElement startElement = document.createElement( QStringLiteral( "start" ) );
407 QDomElement endElement = document.createElement( QStringLiteral( "end" ) );
408
409 const QDomText startText = document.createTextNode( mFixedRange.begin().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
410 const QDomText endText = document.createTextNode( mFixedRange.end().toTimeSpec( Qt::OffsetFromUTC ).toString( Qt::ISODate ) );
411 startElement.appendChild( startText );
412 endElement.appendChild( endText );
413 rangeElement.appendChild( startElement );
414 rangeElement.appendChild( endElement );
415
416 temporalElement.appendChild( rangeElement );
417 break;
418 }
419
421 {
422 QDomElement ranges = document.createElement( QStringLiteral( "ranges" ) );
423 for ( auto it = mRangePerBand.constBegin(); it != mRangePerBand.constEnd(); ++it )
424 {
425 QDomElement range = document.createElement( QStringLiteral( "range" ) );
426 range.setAttribute( QStringLiteral( "band" ), it.key() );
427 range.setAttribute( QStringLiteral( "begin" ), it.value().begin().toString( Qt::ISODate ) );
428 range.setAttribute( QStringLiteral( "end" ), it.value().end().toString( Qt::ISODate ) );
429 range.setAttribute( QStringLiteral( "includeBeginning" ), it.value().includeBeginning() ? "1" : "0" );
430 range.setAttribute( QStringLiteral( "includeEnd" ), it.value().includeEnd() ? "1" : "0" );
431 ranges.appendChild( range );
432 }
433 temporalElement.appendChild( ranges );
434 break;
435 }
436
438 {
439 temporalElement.setAttribute( QStringLiteral( "temporalRepresentationOffset" ), mTemporalRepresentationOffset.toString( Qt::ISODate ) );
440 temporalElement.setAttribute( QStringLiteral( "temporalRepresentationScale" ), QString::number( mTemporalRepresentationScale.originalDuration() ) );
441 temporalElement.setAttribute( QStringLiteral( "temporalRepresentationScaleUnit" ), QString::number( static_cast< int >( mTemporalRepresentationScale.originalUnit() ) ) );
442 break;
443 }
444
447 break;
448 }
449
450 element.appendChild( temporalElement );
451
452 return element;
453}
454
456{
457 if ( const QgsRasterDataProviderTemporalCapabilities *rasterCaps = dynamic_cast< const QgsRasterDataProviderTemporalCapabilities *>( capabilities ) )
458 {
459 setIsActive( rasterCaps->hasTemporalCapabilities() );
460 setFixedTemporalRange( rasterCaps->availableTemporalRange() );
461
462 if ( rasterCaps->hasTemporalCapabilities() )
463 {
465 }
466
467 mIntervalHandlingMethod = rasterCaps->intervalHandlingMethod();
468 }
469}
TemporalIntervalMatchMethod
Method to use when resolving a temporal range to a data provider layer or band.
Definition qgis.h:2513
TemporalUnit
Temporal units.
Definition qgis.h:4868
RasterTemporalMode
Raster layer temporal modes.
Definition qgis.h:2498
@ RepresentsTemporalValues
Pixel values represent an datetime.
@ RedrawLayerOnly
Redraw the layer when temporal range changes, but don't apply any filtering. Useful when raster symbo...
@ FixedRangePerBand
Layer has a fixed temporal range per band.
@ TemporalRangeFromDataProvider
Mode when raster layer delegates temporal range handling to the dataprovider.
@ FixedTemporalRange
Mode when temporal properties have fixed start and end datetimes.
Base class for handling properties relating to a data provider's temporal capabilities.
A representation of the interval between two datetime values.
Definition qgsinterval.h:46
double originalDuration() const
Returns the original interval duration.
Qgis::TemporalUnit originalUnit() const
Returns the original interval temporal unit.
void setDays(double days)
Sets the interval duration in days.
Base class for storage of map layer temporal properties.
Base class for all map layer types.
Definition qgsmaplayer.h:76
Implementation of data provider temporal properties for QgsRasterDataProviders.
QList< QgsDateTimeRange > allAvailableTemporalRanges() const
Returns a list of all valid datetime ranges for which temporal data is available from the provider.
const QgsDateTimeRange & availableTemporalRange() const
Returns the overall datetime range extent from which temporal data is available from the provider.
QgsRasterDataProviderTemporalCapabilities * temporalCapabilities() override
Returns the provider's temporal capabilities.
QDomElement writeXml(QDomElement &element, QDomDocument &doc, const QgsReadWriteContext &context) override
Writes the properties to a DOM element, to be used later with readXml().
QDateTime temporalRepresentationOffset() const
Returns the temporal offset, which is a fixed datetime which should be added to individual pixel valu...
void setDefaultsFromDataProviderTemporalCapabilities(const QgsDataProviderTemporalCapabilities *capabilities) override
Sets the layers temporal settings to appropriate defaults based on a provider's temporal capabilities...
bool isVisibleInTemporalRange(const QgsDateTimeRange &range) const override
Returns true if the layer should be visible and rendered for the specified time range.
QgsTemporalProperty::Flags flags() const override
Returns flags associated to the temporal property.
QList< int > filteredBandsForTemporalRange(QgsRasterLayer *layer, const QgsDateTimeRange &range) const
Returns a filtered list of bands which match the specified range.
void setTemporalRepresentationOffset(const QDateTime &offset)
Sets the temporal offset, which is a fixed datetime which should be added to individual pixel values ...
Qgis::TemporalIntervalMatchMethod intervalHandlingMethod() const
Returns the desired method to use when resolving a temporal interval to matching layers or bands in t...
const QgsInterval & temporalRepresentationScale() const
Returns the scale, which is an interval factor which should be applied to individual pixel values fro...
void setIntervalHandlingMethod(Qgis::TemporalIntervalMatchMethod method)
Sets the desired method to use when resolving a temporal interval to matching layers or bands in the ...
Qgis::RasterTemporalMode mode() const
Returns the temporal properties mode.
void setTemporalRepresentationScale(const QgsInterval &scale)
Sets the scale, which is an interval factor which should be applied to individual pixel values from t...
int bandForTemporalRange(QgsRasterLayer *layer, const QgsDateTimeRange &range) const
Returns the band corresponding to the specified range.
QList< QgsDateTimeRange > allTemporalRanges(QgsMapLayer *layer) const override
Attempts to calculate the overall list of all temporal extents which are contained in the specified l...
void setMode(Qgis::RasterTemporalMode mode)
Sets the temporal properties mode.
QgsRasterLayerTemporalProperties(QObject *parent=nullptr, bool enabled=false)
Constructor for QgsRasterLayerTemporalProperties, with the specified parent object.
void setFixedTemporalRange(const QgsDateTimeRange &range)
Sets a temporal range to apply to the whole layer.
void setFixedRangePerBand(const QMap< int, QgsDateTimeRange > &ranges)
Sets the fixed temporal range for each band.
bool readXml(const QDomElement &element, const QgsReadWriteContext &context) override
Reads temporal properties from a DOM element previously written by writeXml().
QMap< int, QgsDateTimeRange > fixedRangePerBand() const
Returns the fixed temporal range for each band.
int bandNumber() const
Returns the band number from which temporal values should be taken.
const QgsDateTimeRange & fixedTemporalRange() const
Returns the fixed temporal range for the layer.
QgsDateTimeRange calculateTemporalExtent(QgsMapLayer *layer) const override
Attempts to calculate the overall temporal extent for the specified layer, using the settings defined...
void setBandNumber(int number)
Sets the band number from which temporal values should be taken.
Represents a raster layer.
int bandCount() const
Returns the number of bands in this layer.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
The class is used as a container of context for various read/write operations on other objects.
void changed()
Emitted when the temporal properties have changed.
bool isActive() const
Returns true if the temporal property is active.
void setIsActive(bool active)
Sets whether the temporal property is active.
@ FlagDontInvalidateCachedRendersWhenRangeChanges
Any cached rendering will not be invalidated when temporal range context is modified.
T begin() const
Returns the beginning of the range.
Definition qgsrange.h:444
T end() const
Returns the upper bound of the range.
Definition qgsrange.h:451
bool overlaps(const QgsTemporalRange< T > &other) const
Returns true if this range overlaps another range.
Definition qgsrange.h:569
bool includeEnd() const
Returns true if the end is inclusive, or false if the end is exclusive.
Definition qgsrange.h:466
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:480
#define BUILTIN_UNREACHABLE
Definition qgis.h:6678
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.
Definition qgsrange.h:742