Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
improved logic for search of closest datetimes
  • Loading branch information
Samweli authored and nyalldawson committed Apr 27, 2020
1 parent 2454613 commit df335f2
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 26 deletions.
38 changes: 20 additions & 18 deletions src/providers/wms/qgswmscapabilities.cpp
Expand Up @@ -98,8 +98,6 @@ bool QgsWmsSettings::parseUri( const QString &uriString )
else
mFixedRange = QgsDateTimeRange();

mDateTimes = dateTimesFromExtent( mTimeDimensionExtent );

if ( uri.param( QStringLiteral( "referenceTimeDimensionExtent" ) ) != QString() )
{
QString referenceExtent = uri.param( QStringLiteral( "referenceTimeDimensionExtent" ) );
Expand Down Expand Up @@ -335,32 +333,36 @@ QDateTime QgsWmsSettings::addTime( QDateTime dateTime, QgsWmstResolution resolut
return resultDateTime;
}

QDateTime QgsWmsSettings::findLeastClosestDateTime( QDateTime dateTime ) const
QDateTime QgsWmsSettings::findLeastClosestDateTime( QDateTime dateTime, bool dateOnly ) const
{
QDateTime closest = dateTime;
long long min = std::numeric_limits<long long>::max();

if ( !dateTime.isValid() || mDateTimes.contains( dateTime ) )
return closest;
long long seconds;

if ( dateOnly )
seconds = QDateTime::fromString( closest.date().toString() ).toSecsSinceEpoch();
else
seconds = closest.toSecsSinceEpoch();

for ( QDateTime current : mDateTimes )
for ( QgsWmstExtentPair pair : mTimeDimensionExtent.datesResolutionList )
{
if ( !current.isValid() )
if ( pair.dates.dateTimes.size() < 2 )
continue;

long long difference = dateTime.secsTo( current );
long long startSeconds = pair.dates.dateTimes.at( 0 ).toSecsSinceEpoch();
long long endSeconds = pair.dates.dateTimes.at( 1 ).toSecsSinceEpoch();

// The datetimes list is sorted, if difference is increasing or
// it is above zero means search is now looking for greater than
// datetimes then search will have to stop.
if ( difference > 0 || std::abs( difference ) > min )
// if out of bounds
if ( seconds < startSeconds || seconds > endSeconds )
continue;
if ( seconds == endSeconds )
break;

if ( std::abs( difference ) < min )
{
min = std::abs( difference );
closest = current;
}
long long resolutionSeconds = pair.resolution.interval();
long long step = std::floor( ( seconds - startSeconds ) / resolutionSeconds );
long long resultSeconds = startSeconds + ( step * resolutionSeconds );

closest.setSecsSinceEpoch( resultSeconds );
}

return closest;
Expand Down
31 changes: 25 additions & 6 deletions src/providers/wms/qgswmscapabilities.h
Expand Up @@ -27,6 +27,7 @@
#include "qgsrasteriterator.h"
#include "qgsapplication.h"
#include "qgsdataprovider.h"
#include "qgsinterval.h"


class QNetworkReply;
Expand Down Expand Up @@ -406,6 +407,26 @@ struct QgsWmstResolution
int minutes = -1;
int seconds = -1;

long long interval()
{
long long secs = 0.0;

if ( year != -1 )
secs += year * QgsInterval::YEARS ;
if ( month != -1 )
secs += month * QgsInterval::MONTHS;
if ( day != -1 )
secs += day * QgsInterval::DAY;
if ( hour != -1 )
secs += hour * QgsInterval::HOUR;
if ( minutes != -1 )
secs += minutes * QgsInterval::MINUTE;
if ( seconds != -1 )
secs += seconds;

return secs;
}

bool active()
{
return year != -1 || month != -1 || day != -1 ||
Expand Down Expand Up @@ -786,12 +807,13 @@ class QgsWmsSettings
QDateTime addTime( QDateTime dateTime, QgsWmstResolution resolution );

/**
* Finds the least closest datetime from list of available datetimes
* Finds the least closest datetime from list of available dimension temporal ranges
* with the given \a dateTime.
*
* Returns the passed \a dateTime if it is found in the available datetimes.
* \note It works with wms-t capabilities that provide time dimension with temporal ranges only.
*
*/
QDateTime findLeastClosestDateTime( QDateTime dateTime ) const;
QDateTime findLeastClosestDateTime( QDateTime dateTime, bool dateOnly = false ) const;

protected:
QgsWmsParserSettings mParserSettings;
Expand All @@ -816,9 +838,6 @@ class QgsWmsSettings
//! Fixed reference temporal range for the data provider
QgsDateTimeRange mFixedReferenceRange;

//! List of all available datetimes.
QList<QDateTime> mDateTimes;

//! Stores WMS-T time dimension extent dates
QgsWmstDimensionExtent mTimeDimensionExtent;

Expand Down
9 changes: 7 additions & 2 deletions src/providers/wms/qgswmsprovider.cpp
Expand Up @@ -1082,8 +1082,10 @@ QUrl QgsWmsProvider::createRequestUrlWMS( const QgsRectangle &viewExtent, int pi
void QgsWmsProvider::addWmstParameters( QUrlQuery &query )
{
QgsDateTimeRange range = temporalCapabilities()->requestedTemporalRange();

QString format { QStringLiteral( "yyyy-MM-ddThh:mm:ssZ" ) };
QgsDataSourceUri uri { dataSourceUri() };
bool dateOnly = false;

if ( range.isInfinite() )
{
Expand All @@ -1101,7 +1103,10 @@ void QgsWmsProvider::addWmstParameters( QUrlQuery &query )
}

if ( uri.param( QStringLiteral( "enableTime" ) ) == QLatin1String( "no" ) )
{
format = "yyyy-MM-dd";
dateOnly = true;
}

if ( range.begin().isValid() && range.end().isValid() )
{
Expand All @@ -1117,14 +1122,14 @@ void QgsWmsProvider::addWmstParameters( QUrlQuery &query )
break;
case QgsRasterDataProviderTemporalCapabilities::FindClosestMatchToStartOfRange:
{
QDateTime dateTimeStart = mSettings.findLeastClosestDateTime( range.begin() );
QDateTime dateTimeStart = mSettings.findLeastClosestDateTime( range.begin(), dateOnly );
range = QgsDateTimeRange( dateTimeStart, dateTimeStart );
break;
}

case QgsRasterDataProviderTemporalCapabilities::FindClosestMatchToEndOfRange:
{
QDateTime dateTimeEnd = mSettings.findLeastClosestDateTime( range.end() );
QDateTime dateTimeEnd = mSettings.findLeastClosestDateTime( range.end(), dateOnly );
range = QgsDateTimeRange( dateTimeEnd, dateTimeEnd );
break;
}
Expand Down

0 comments on commit df335f2

Please sign in to comment.