Skip to content

Commit e9afc7b

Browse files
committed
WCS time support
1 parent e09a0a5 commit e9afc7b

10 files changed

+280
-139
lines changed

src/gui/qgsowssourceselect.cpp

+22-4
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ void QgsOWSSourceSelect::populateFormats()
160160
// selectedLayersFormats may come in various forms:
161161
// image/tiff, GTiff, GeoTIFF, TIFF, geotiff_int16, geotiff_rgb,
162162
// PNG, GTOPO30, ARCGRID, IMAGEMOSAIC
163-
// and even any string defined in server configuration, for example the
164-
// value used in UMN Mapserver for OUTPUTFORMAT->NAME is used in
163+
// and even any string defined in server configuration, for example the
164+
// value used in UMN Mapserver for OUTPUTFORMAT->NAME is used in
165165
// WCS 1.0.0 SupportedFormats/Format
166166

167167
// TODO: It is impossible to cover all possible formats comming from server
@@ -241,6 +241,14 @@ void QgsOWSSourceSelect::populateFormats()
241241
mImageFormatsGroupBox->setEnabled( true );
242242
}
243243

244+
void QgsOWSSourceSelect::populateTimes()
245+
{
246+
QgsDebugMsg( "entered" );
247+
mTimeComboBox->clear();
248+
mTimeComboBox->insertItems( 0, selectedLayersTimes() );
249+
mTimeComboBox->setEnabled( !selectedLayersTimes().isEmpty() );
250+
}
251+
244252
void QgsOWSSourceSelect::populateConnectionList()
245253
{
246254
mConnectionsComboBox->clear();
@@ -436,7 +444,7 @@ void QgsOWSSourceSelect::on_mLayersTreeWidget_itemSelectionChanged()
436444

437445
void QgsOWSSourceSelect::populateCRS()
438446
{
439-
QgsDebugMsg ("Entered");
447+
QgsDebugMsg( "Entered" );
440448
mSelectedLayersCRSs = selectedLayersCRSs().toSet();
441449
mCRSGroupBox->setTitle( tr( "Coordinate Reference System (%n available)", "crs count", mSelectedLayersCRSs.count() ) );
442450

@@ -474,7 +482,7 @@ void QgsOWSSourceSelect::populateCRS()
474482
mSelectedCRS = "";
475483
mSelectedCRSLabel->setText( "" );
476484
}
477-
QgsDebugMsg ("mSelectedCRS = " + mSelectedCRS);
485+
QgsDebugMsg( "mSelectedCRS = " + mSelectedCRS );
478486
mChangeCRSButton->setEnabled( !mSelectedLayersCRSs.isEmpty() );
479487
}
480488

@@ -535,6 +543,11 @@ QString QgsOWSSourceSelect::selectedCRS()
535543
return mSelectedCRS;
536544
}
537545

546+
QString QgsOWSSourceSelect::selectedTime()
547+
{
548+
return mTimeComboBox->currentText();
549+
}
550+
538551
void QgsOWSSourceSelect::setConnectionListPosition()
539552
{
540553
QString toSelect = QgsOWSConnection::selectedConnection( mService );
@@ -805,6 +818,11 @@ QStringList QgsOWSSourceSelect::selectedLayersCRSs()
805818
return QStringList();
806819
}
807820

821+
QStringList QgsOWSSourceSelect::selectedLayersTimes()
822+
{
823+
return QStringList();
824+
}
825+
808826
void QgsOWSSourceSelect::updateButtons()
809827
{
810828
}

src/gui/qgsowssourceselect.h

+9
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ class GUI_EXPORT QgsOWSSourceSelect : public QDialog, public Ui::QgsOWSSourceSel
124124
//! Server CRS supported for currently selected layer item(s)
125125
virtual QStringList selectedLayersCRSs();
126126

127+
//! List of times (temporalDomain timePosition/timePeriod for currently selected layer item(s)
128+
virtual QStringList selectedLayersTimes();
129+
127130
//virtual QStringList layerCRS( int id );
128131

129132
//! Populate the connection list combo box
@@ -138,6 +141,9 @@ class GUI_EXPORT QgsOWSSourceSelect : public QDialog, public Ui::QgsOWSSourceSel
138141
//! Set supported CRSs
139142
void populateCRS();
140143

144+
//! Populate times
145+
void populateTimes();
146+
141147
//! Connection name
142148
QString connName();
143149

@@ -199,6 +205,9 @@ class GUI_EXPORT QgsOWSSourceSelect : public QDialog, public Ui::QgsOWSSourceSel
199205
//! Returns currently selected Crs
200206
QString selectedCRS();
201207

208+
//! Returns currently selected time
209+
QString selectedTime();
210+
202211
QList<QTreeWidgetItem*> mCurrentSelection;
203212
QTableWidgetItem* mCurrentTileset;
204213

src/providers/wcs/URI

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ Parameters:
1111

1212
* identifier (required) : Coverage name
1313

14-
* format: (optional) : Supported format name. Default is the first supported format with tif in name or the first supported format.
14+
* time (optional) : time position or time period (beginPosition/endPosition[/timeResolution])
15+
16+
* format (optional) : Supported format name. Default is the first supported format with tif in name or the first supported format.
1517

1618
* crs (optional) : CRS in form AUTHORITY:ID, e.g. EPSG:4326. Default is EPSG:4326 if supported or the first supported CRS.
1719

src/providers/wcs/qgswcscapabilities.cpp

+55-17
Original file line numberDiff line numberDiff line change
@@ -196,15 +196,15 @@ bool QgsWcsCapabilities::retrieveServerCapabilities( )
196196

197197
if ( !preferredVersion.isEmpty() )
198198
{
199-
// This is not
200-
if ( preferredVersion.startsWith ( "1.0" ) )
199+
// This is not
200+
if ( preferredVersion.startsWith( "1.0" ) )
201201
{
202202
versions << "VERSION=" + preferredVersion;
203203
}
204-
else if ( preferredVersion.startsWith ( "1.1" ) )
204+
else if ( preferredVersion.startsWith( "1.1" ) )
205205
{
206-
// Ignored by UMN Mapserver 6.0.3, see below
207-
versions << "AcceptVersions=" + preferredVersion;
206+
// Ignored by UMN Mapserver 6.0.3, see below
207+
versions << "AcceptVersions=" + preferredVersion;
208208
}
209209
}
210210
else
@@ -214,7 +214,7 @@ bool QgsWcsCapabilities::retrieveServerCapabilities( )
214214
versions << "AcceptVersions=1.1,1.0" << "VERSION=1.0";
215215
}
216216

217-
foreach( QString v, versions )
217+
foreach ( QString v, versions )
218218
{
219219
if ( retrieveServerCapabilities( v ) )
220220
{
@@ -427,7 +427,7 @@ bool QgsWcsCapabilities::parseCapabilitiesDom( QByteArray const &xml, QgsWcsCapa
427427
capabilities.abstract = domElementText( docElem, "ServiceIdentification.Abstract" );
428428

429429
QList<QDomElement> operationElements = domElements( docElem, "OperationsMetadata.Operation" );
430-
foreach( QDomElement el, operationElements )
430+
foreach ( QDomElement el, operationElements )
431431
{
432432
if ( el.attribute( "name" ) == "GetCoverage" )
433433
{
@@ -509,7 +509,7 @@ QStringList QgsWcsCapabilities::domElementsTexts( const QDomElement &element, co
509509
QStringList list;
510510
QList<QDomElement> elems = domElements( element, path );
511511

512-
foreach( QDomElement el, elems )
512+
foreach ( QDomElement el, elems )
513513
{
514514
list << el.text();
515515
}
@@ -539,9 +539,8 @@ QString QgsWcsCapabilities::domElementText( const QDomElement &element, const QS
539539
QList<int> QgsWcsCapabilities::parseInts( const QString &text )
540540
{
541541
QList<int> list;
542-
foreach( QString s, text.split( " " ) )
542+
foreach ( QString s, text.split( " " ) )
543543
{
544-
int i;
545544
bool ok;
546545
list.append( s.toInt( &ok ) );
547546
if ( !ok )
@@ -556,9 +555,8 @@ QList<int> QgsWcsCapabilities::parseInts( const QString &text )
556555
QList<double> QgsWcsCapabilities::parseDoubles( const QString &text )
557556
{
558557
QList<double> list;
559-
foreach( QString s, text.split( " " ) )
558+
foreach ( QString s, text.split( " " ) )
560559
{
561-
int i;
562560
bool ok;
563561
list.append( s.toDouble( &ok ) );
564562
if ( !ok )
@@ -758,7 +756,7 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom10( QByteArray const &xml, QgsW
758756

759757
QgsDebugMsg( QString( "%1 envelopeElements found" ).arg( envelopeElements.size() ) );
760758

761-
foreach( QDomElement el, envelopeElements )
759+
foreach ( QDomElement el, envelopeElements )
762760
{
763761
QString srsName = el.attribute( "srsName" );
764762

@@ -779,10 +777,30 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom10( QByteArray const &xml, QgsW
779777
}
780778
}
781779

780+
coverage->times = domElementsTexts( coverageOfferingElement, "domainSet.temporalDomain.timePosition" );
781+
782+
QList<QDomElement> timePeriodElements = domElements( coverageOfferingElement, "domainSet.temporalDomain.timePeriod" );
783+
784+
QgsDebugMsg( QString( "%1 timePeriod found" ).arg( timePeriodElements.size() ) );
785+
786+
foreach ( QDomElement el, timePeriodElements )
787+
{
788+
QString beginPosition = domElementText( el, "beginPosition" );
789+
QString endPosition = domElementText( el, "endPosition" );
790+
QString timeResolution = domElementText( el, "timeResolution" );
791+
// Format used in request
792+
QString time = beginPosition + "/" + endPosition;
793+
if ( !timeResolution.isEmpty() )
794+
{
795+
time += "/" + timeResolution;
796+
}
797+
coverage->times << time;
798+
}
799+
782800
// Find native bounding box
783801
if ( !coverage->nativeCrs.isEmpty() )
784802
{
785-
foreach( QString srsName, coverage->boundingBoxes.keys() )
803+
foreach ( QString srsName, coverage->boundingBoxes.keys() )
786804
{
787805
if ( srsName == coverage->nativeCrs )
788806
{
@@ -793,7 +811,7 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom10( QByteArray const &xml, QgsW
793811

794812
// NULL / no data values
795813
// TODO: handle multiple range sets
796-
foreach( QString text, domElementsTexts( coverageOfferingElement, "rangeSet.RangeSet.nullValue.singleValue" ) )
814+
foreach ( QString text, domElementsTexts( coverageOfferingElement, "rangeSet.RangeSet.nullValue.singleValue" ) )
797815
{
798816
bool ok;
799817
double val = text.toDouble( &ok );
@@ -840,7 +858,7 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom11( QByteArray const &xml, QgsW
840858

841859
QgsDebugMsg( QString( "%1 BoundingBox found" ).arg( boundingBoxElements.size() ) );
842860

843-
foreach( QDomElement el, boundingBoxElements )
861+
foreach ( QDomElement el, boundingBoxElements )
844862
{
845863
QString authid = crsUrnToAuthId( el.attribute( "crs" ) );
846864
QList<double> low = parseDoubles( domElementText( el, "LowerCorner" ) );
@@ -876,9 +894,29 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom11( QByteArray const &xml, QgsW
876894
// if urn:ogc:def:crs:OGC::imageCRS BoundingBox was not found
877895
}
878896

897+
coverage->times = domElementsTexts( docElem, "CoverageDescription.Domain.TemporalDomain.timePosition" );
898+
899+
QList<QDomElement> timePeriodElements = domElements( docElem, "CoverageDescription.Domain.TemporalDomain.timePeriod" );
900+
901+
QgsDebugMsg( QString( "%1 timePeriod found" ).arg( timePeriodElements.size() ) );
902+
903+
foreach ( QDomElement el, timePeriodElements )
904+
{
905+
QString beginPosition = domElementText( el, "beginTime" );
906+
QString endPosition = domElementText( el, "endTime" );
907+
QString timeResolution = domElementText( el, "timeResolution" );
908+
// Format used in request
909+
QString time = beginPosition + "/" + endPosition;
910+
if ( !timeResolution.isEmpty() )
911+
{
912+
time += "/" + timeResolution;
913+
}
914+
coverage->times << time;
915+
}
916+
879917
// NULL / no data values
880918
// TODO: handle multiple fields / ranges (?)
881-
foreach( QString text, domElementsTexts( docElem, "CoverageDescription.Range.Field.NullValue" ) )
919+
foreach ( QString text, domElementsTexts( docElem, "CoverageDescription.Range.Field.NullValue" ) )
882920
{
883921
bool ok;
884922
double val = text.toDouble( &ok );

src/providers/wcs/qgswcscapabilities.h

+2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ struct QgsWcsCoverageSummary
4949
// Map of bounding boxes, key is CRS name (srsName), e.g. EPSG:4326
5050
QMap<QString, QgsRectangle> boundingBoxes;
5151
QgsRectangle nativeBoundingBox;
52+
// timePosition or timePeriod (beginPosition/endPosition[/timeResolution] - used in KVP request)
53+
QStringList times;
5254
QVector<QgsWcsCoverageSummary> coverageSummary;
5355
// non reflecting Capabilities structure:
5456
bool valid;

src/providers/wcs/qgswcsprovider.cpp

+13-1
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,8 @@ bool QgsWcsProvider::parseUri( QString uriString )
357357

358358
mIdentifier = uri.param( "identifier" );
359359

360+
mTime = uri.param( "time" );
361+
360362
setFormat( uri.param( "format" ) );
361363

362364
if ( !uri.param( "crs" ).isEmpty() )
@@ -561,6 +563,10 @@ void QgsWcsProvider::getCache( int bandNo, QgsRectangle const & viewExtent, int
561563
if ( mCapabilities.version().startsWith( "1.0" ) )
562564
{
563565
setQueryItem( url, "COVERAGE", mIdentifier );
566+
if ( !mTime.isEmpty() )
567+
{
568+
setQueryItem( url, "TIME", mTime );
569+
}
564570
setQueryItem( url, "BBOX", bbox );
565571
setQueryItem( url, "CRS", crs ); // request BBOX CRS
566572
setQueryItem( url, "RESPONSE_CRS", crs ); // response CRS
@@ -574,6 +580,12 @@ void QgsWcsProvider::getCache( int bandNo, QgsRectangle const & viewExtent, int
574580
setQueryItem( url, "IDENTIFIER", mIdentifier );
575581
QString crsUrn = QString( "urn:ogc:def:crs:%1::%2" ).arg( crs.split( ':' ).value( 0 ) ).arg( crs.split( ':' ).value( 1 ) );
576582
bbox += "," + crsUrn;
583+
584+
if ( !mTime.isEmpty() )
585+
{
586+
setQueryItem( url, "TIMESEQUENCE", mTime );
587+
}
588+
577589
setQueryItem( url, "BOUNDINGBOX", bbox );
578590

579591
// GridBaseCRS=urn:ogc:def:crs:SG:6.6:32618
@@ -1292,7 +1304,7 @@ QString QgsWcsProvider::metadata()
12921304
metadata += tr( "Coverages" );
12931305
metadata += "</th></tr>";
12941306

1295-
foreach( QgsWcsCoverageSummary c, mCapabilities.coverages() )
1307+
foreach ( QgsWcsCoverageSummary c, mCapabilities.coverages() )
12961308
{
12971309
metadata += coverageMetadata( c );
12981310
}

src/providers/wcs/qgswcsprovider.h

+3
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ class QgsWcsProvider : public QgsRasterDataProvider, QgsGdalProviderBase
251251
//! Identifier / coverage / layer name
252252
QString mIdentifier;
253253

254+
//! Time (temporalDomain), optional
255+
QString mTime;
256+
254257
//! Format of coverage to be used in request
255258
QString mFormat;
256259

src/providers/wcs/qgswcssourceselect.cpp

+24-6
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,12 @@ void QgsWCSSourceSelect::addClicked( )
144144
uri.setParam( "format", selectedFormat() );
145145
}
146146

147+
QgsDebugMsg( "selectedTime = " + selectedTime() );
148+
if ( !selectedTime().isEmpty() )
149+
{
150+
uri.setParam( "time", selectedTime() );
151+
}
152+
147153
emit addRasterLayer( uri.encodedUri(), identifier, "wcs" );
148154
}
149155

@@ -154,11 +160,9 @@ void QgsWCSSourceSelect::on_mLayersTreeWidget_itemSelectionChanged()
154160
QString identifier = selectedIdentifier();
155161
if ( identifier.isEmpty() ) { return; }
156162

157-
if ( mCapabilities.version().startsWith( "1.0" ) )
158-
{
159-
// 1.0 get additional info
160-
mCapabilities.describeCoverage( identifier );
161-
}
163+
mCapabilities.describeCoverage( identifier );
164+
165+
populateTimes();
162166

163167
populateFormats();
164168

@@ -194,7 +198,7 @@ QList<QgsOWSSupportedFormat> QgsWCSSourceSelect::providerFormats()
194198
QList<QgsOWSSupportedFormat> formats;
195199

196200
QMap<QString, QString> mimes = QgsWcsProvider::supportedMimes();
197-
foreach( QString mime, mimes.keys() )
201+
foreach ( QString mime, mimes.keys() )
198202
{
199203
QgsOWSSupportedFormat format = { mime, mimes.value( mime ) };
200204

@@ -239,6 +243,20 @@ QStringList QgsWCSSourceSelect::selectedLayersCRSs()
239243
return c.supportedCrs;
240244
}
241245

246+
QStringList QgsWCSSourceSelect::selectedLayersTimes()
247+
{
248+
QgsDebugMsg( "entered" );
249+
250+
QString identifier = selectedIdentifier();
251+
if ( identifier.isEmpty() ) { return QStringList(); }
252+
253+
QgsWcsCoverageSummary c = mCapabilities.coverage( identifier );
254+
if ( !c.valid ) { return QStringList(); }
255+
256+
QgsDebugMsg( "times = " + c.times.join( "," ) );
257+
return c.times;
258+
}
259+
242260
void QgsWCSSourceSelect::enableLayersForCrs( QTreeWidgetItem * )
243261
{
244262
// TODO: I am not convinced to disable layers according to selected CRS

src/providers/wcs/qgswcssourceselect.h

+1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ class QgsWCSSourceSelect : public QgsOWSSourceSelect
7878
QList<QgsOWSSupportedFormat> providerFormats();
7979
QStringList selectedLayersFormats();
8080
QStringList selectedLayersCRSs();
81+
QStringList selectedLayersTimes();
8182
};
8283
#endif // QGSWCSSOURCESELECT_H
8384

0 commit comments

Comments
 (0)