Skip to content

Commit

Permalink
wmts fixes:
Browse files Browse the repository at this point in the history
- [FEATURE] add support for CRS:27 and CRS:83 in QgsCoordinateReferenceSystem
- fix axis orientation for CRS:84
- respect inverted axis orientation in WMTS and allow to ignore it for WMS 1.3/WMTS
- fix: only consider valid TileMatrixSetLimits
  • Loading branch information
jef-n committed May 17, 2012
1 parent e454c5f commit f3330e6
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 41 deletions.
22 changes: 20 additions & 2 deletions src/core/qgscoordinatereferencesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,29 @@ bool QgsCoordinateReferenceSystem::createFromOgcWmsCrs( QString theCrs )
if ( loadFromDb( QgsApplication::srsDbFilePath(), "lower(auth_name||':'||auth_id)", theCrs.toLower() ) )
return true;

// NAD27
if ( theCrs.compare( "CRS:27", Qt::CaseInsensitive ) == 0 ||
theCrs.compare( "OGC:CRS27", Qt::CaseInsensitive ) == 0 )
{
// TODO: verify same axis orientation
return createFromEpsg( 4267 );
}

// NAD83
if ( theCrs.compare( "CRS:83", Qt::CaseInsensitive ) == 0 ||
theCrs.compare( "OGC:CRS83", Qt::CaseInsensitive ) == 0 )
{
// TODO: verify same axis orientation
return createFromEpsg( 4269 );
}

// WGS84
if ( theCrs.compare( "CRS:84", Qt::CaseInsensitive ) == 0 ||
theCrs.compare( "OGC:CRS84", Qt::CaseInsensitive ) == 0 )
{
createFromSrsId( GEOCRS_ID );
return true;
createFromEpsg( 4326 );
mAxisInverted = 0;
return mIsValidFlag;
}

return false;
Expand Down
2 changes: 2 additions & 0 deletions src/gui/qgsmanageconnectionsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ QDomDocument QgsManageConnectionsDialog::saveWMSConnections( const QStringList &
el.setAttribute( "url", settings.value( path + connections[ i ] + "/url", "" ).toString() );
el.setAttribute( "ignoreGetMapURI", settings.value( path + connections[i] + "/ignoreGetMapURI", false ).toBool() ? "true" : "false" );
el.setAttribute( "ignoreGetFeatureInfoURI", settings.value( path + connections[i] + "/ignoreGetFeatureInfoURI", false ).toBool() ? "true" : "false" );
el.setAttribute( "ignoreAxisOrientation", settings.value( path + connections[i] + "/ignoreAxisOrientation", false ).toBool() ? "true" : "false" );

path = "/Qgis/WMS/";
el.setAttribute( "username", settings.value( path + connections[ i ] + "/username", "" ).toString() );
Expand Down Expand Up @@ -491,6 +492,7 @@ void QgsManageConnectionsDialog::loadWMSConnections( const QDomDocument &doc, co
settings.setValue( QString( "/" + connectionName + "/url" ) , child.attribute( "url" ) );
settings.setValue( QString( "/" + connectionName + "/ignoreGetMapURI" ), child.attribute( "ignoreGetMapURI" ) == "true" );
settings.setValue( QString( "/" + connectionName + "/ignoreGetFeatureInfoURI" ), child.attribute( "ignoreGetFeatureInfoURI" ) == "true" );
settings.setValue( QString( "/" + connectionName + "/ignoreAxisOrientation" ), child.attribute( "ignoreAxisOrientation" ) == "true" );
settings.endGroup();

if ( !child.attribute( "username" ).isEmpty() )
Expand Down
24 changes: 15 additions & 9 deletions src/gui/qgsnewhttpconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,13 @@ QgsNewHttpConnection::QgsNewHttpConnection(
{
cbxIgnoreGetMapURI->setChecked( settings.value( key + "/ignoreGetMapURI", false ).toBool() );
cbxIgnoreGetFeatureInfoURI->setChecked( settings.value( key + "/ignoreGetFeatureInfoURI", false ).toBool() );
cbxIgnoreAxisOrientation->setChecked( settings.value( key + "/ignoreAxisOrientation", false ).toBool() );
}
else
{
cbxIgnoreGetMapURI->setVisible( false );
cbxIgnoreGetFeatureInfoURI->setVisible( false );
cbxIgnoreAxisOrientation->setVisible( false );
}

txtUserName->setText( settings.value( credentialsKey + "/username" ).toString() );
Expand Down Expand Up @@ -100,24 +102,28 @@ void QgsNewHttpConnection::accept()
}

QUrl url( txtUrl->text().trimmed() );
const QList< QPair<QByteArray, QByteArray> > &items = url.encodedQueryItems();
QHash< QString, QPair<QByteArray, QByteArray> > params;
for ( QList< QPair<QByteArray, QByteArray> >::const_iterator it = items.constBegin(); it != items.constEnd(); ++it )
{
params.insert( QString( it->first ).toUpper(), *it );
}

QList< QPair<QByteArray, QByteArray> > params = url.encodedQueryItems();
for ( int i = 0; i < params.size(); i++ )
if ( params["SERVICE"].second.toUpper() == "WMS" )
{
if ( params[i].first.toUpper() == "SERVICE" ||
params[i].first.toUpper() == "REQUEST" ||
params[i].first.toUpper() == "FORMAT" )
{
params.removeAt( i-- );
}
params.remove( "SERVICE" );
params.remove( "REQUEST" );
params.remove( "FORMAT" );
}
url.setEncodedQueryItems( params );

url.setEncodedQueryItems( params.values() );

settings.setValue( key + "/url", url.toString() );
if ( mBaseKey == "/Qgis/connections-wms/" )
{
settings.setValue( key + "/ignoreGetMapURI", cbxIgnoreGetMapURI->isChecked() );
settings.setValue( key + "/ignoreGetFeatureInfoURI", cbxIgnoreGetFeatureInfoURI->isChecked() );
settings.setValue( key + "/ignoreAxisOrientation", cbxIgnoreAxisOrientation->isChecked() );
}

settings.setValue( credentialsKey + "/username", txtUserName->text() );
Expand Down
18 changes: 15 additions & 3 deletions src/providers/wms/qgswmsconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,29 @@ QgsWMSConnection::QgsWMSConnection( QString theConnName ) :

bool ignoreGetMap = settings.value( key + "/ignoreGetMapURI", false ).toBool();
bool ignoreGetFeatureInfo = settings.value( key + "/ignoreGetFeatureInfoURI", false ).toBool();
if ( ignoreGetMap || ignoreGetFeatureInfo )
bool ignoreAxisOrientation = settings.value( key + "/ignoreAxisOrientation", false ).toBool();
if ( ignoreGetMap || ignoreGetFeatureInfo || ignoreAxisOrientation )
{
QString connArgs = "ignoreUrl=";

if ( ignoreGetMap )
{
connArgs += "GetMap";
if ( ignoreGetFeatureInfo )
connArgs += ";";
}

if ( ignoreGetFeatureInfo )
{
if ( !connArgs.endsWith( "=" ) )
connArgs += ";";
connArgs += "GetFeatureInfo";
}

if ( ignoreAxisOrientation )
{
if ( !connArgs.endsWith( "=" ) )
connArgs += ";";
connArgs += "AxisOrientation";
}

if ( mConnectionInfo.startsWith( "username=" ) )
{
Expand Down
127 changes: 102 additions & 25 deletions src/providers/wms/qgswmsprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ void QgsWmsProvider::parseUri( QString uri )

mIgnoreGetMapUrl = false;
mIgnoreGetFeatureInfoUrl = false;
mIgnoreAxisOrientation = false;

QString layer;

Expand Down Expand Up @@ -182,6 +183,10 @@ void QgsWmsProvider::parseUri( QString uri )
{
mIgnoreGetFeatureInfoUrl = true;
}
else if ( param == "AxisOrientation" )
{
mIgnoreAxisOrientation = true;
}
}
}
else if ( item.startsWith( "tileMatrixSet=" ) )
Expand Down Expand Up @@ -337,13 +342,6 @@ size_t QgsWmsProvider::layerCount() const
return 1; // XXX properly return actual number of layers
} // QgsWmsProvider::layerCount()

#if 0
bool QgsWmsProvider::hasTiles() const
{
return mCapabilities.capability.tileSetProfiles.size() > 0;
}
#endif

QString QgsWmsProvider::baseUrl() const
{
return mBaseUrl;
Expand Down Expand Up @@ -534,7 +532,7 @@ QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, i

//according to the WMS spec for 1.3, some CRS have inverted axis
bool changeXY = false;
if ( mCapabilities.version == "1.3.0" || mCapabilities.version == "1.3" )
if ( !mIgnoreAxisOrientation && ( mCapabilities.version == "1.3.0" || mCapabilities.version == "1.3" ) )
{
//create CRS from string
QgsCoordinateReferenceSystem theSrs;
Expand Down Expand Up @@ -1070,10 +1068,10 @@ void QgsWmsProvider::tileReplyFinished()
r.width() / cr,
r.height() / cr );

QgsDebugMsg( QString( "tile reply: %1" ).arg( reply->bytesAvailable() ) );
QgsDebugMsg( QString( "tile reply: length %1" ).arg( reply->bytesAvailable() ) );
QImage myLocalImage = QImage::fromData( reply->readAll() );

// myLocalImage.save( QString( "%1/%2-tile-%3.png" ).arg( QDir::tempPath() ).arg( mTileReqNo ).arg( tileNo ) );
myLocalImage.save( QString( "%1/%2-tile-%3.png" ).arg( QDir::tempPath() ).arg( mTileReqNo ).arg( tileNo ) );

if ( !myLocalImage.isNull() )
{
Expand All @@ -1092,7 +1090,10 @@ void QgsWmsProvider::tileReplyFinished()
{
QgsMessageLog::logMessage( tr( "Returned image is flawed [%1]" ).arg( reply->url().toString() ), tr( "WMS" ) );
}

}
else
{
QgsMessageLog::logMessage( tr( "Reply to earlier tile request received too late [%1]" ).arg( reply->url().toString() ), tr( "WMS" ) );
}

mTileReplies.removeOne( reply );
Expand All @@ -1106,9 +1107,18 @@ void QgsWmsProvider::tileReplyFinished()
}
else
{
mErrors++;
if ( mErrors < 100 )
{
QgsMessageLog::logMessage( tr( "Tile request failed [error:%1 url:%2]" ).arg( reply->errorString() ).arg( reply->url().toString() ), tr( "WMS" ) );
}
else if ( mErrors == 100 )
{
QgsMessageLog::logMessage( tr( "Not logging more than 100 request errors." ), tr( "WMS" ) );
}

mTileReplies.removeOne( reply );
reply->deleteLater();
mErrors++;
}

#ifdef QGISDEBUG
Expand Down Expand Up @@ -1200,9 +1210,18 @@ void QgsWmsProvider::cacheReplyFinished()
}
else
{
mErrors++;
if ( mErrors < 100 )
{
QgsMessageLog::logMessage( tr( "Map request failed [error:%1 url:%2]" ).arg( mCacheReply->errorString() ).arg( mCacheReply->url().toString() ), tr( "WMS" ) );
}
else if ( mErrors == 100 )
{
QgsMessageLog::logMessage( tr( "Not logging more than 100 request errors." ), tr( "WMS" ) );
}

mCacheReply->deleteLater();
mCacheReply = 0;
mErrors++;
}
}

Expand Down Expand Up @@ -2446,8 +2465,10 @@ void QgsWmsProvider::parseWMTSContents( QDomElement const &e )
s.abstract = n0.firstChildElement( "ows:Abstract" ).text();
parseKeywords( n0, s.keywords );

QString supportedCRS = n0.firstChildElement( "ows:SupportedCRS" ).text();

QgsCoordinateReferenceSystem crs;
crs.createFromOgcWmsCrs( n0.firstChildElement( "ows:SupportedCRS" ).text() );
crs.createFromOgcWmsCrs( supportedCRS );

s.wkScaleSet = n0.firstChildElement( "WellKnownScaleSet" ).text();

Expand Down Expand Up @@ -2476,7 +2497,13 @@ void QgsWmsProvider::parseWMTSContents( QDomElement const &e )

s.crs = crs.authid();

QgsDebugMsg( QString( "tilematrix set: %1 (crs:%2; metersPerUnit:%3)" ).arg( s.identifier ).arg( s.crs ).arg( metersPerUnit, 0, 'f' ) );
QgsDebugMsg( QString( "tilematrix set: %1 (supportedCRS:%2 crs:%3; metersPerUnit:%4 axisInverted:%5)" )
.arg( s.identifier )
.arg( supportedCRS )
.arg( s.crs )
.arg( metersPerUnit, 0, 'f' )
.arg( !mIgnoreAxisOrientation && crs.axisInverted() ? "yes" : "no" )
);

for ( QDomNode n1 = n0.firstChildElement( "TileMatrix" );
!n1.isNull();
Expand All @@ -2494,7 +2521,14 @@ void QgsWmsProvider::parseWMTSContents( QDomElement const &e )
QStringList topLeft = n1.firstChildElement( "TopLeftCorner" ).text().split( " " );
if ( topLeft.size() == 2 )
{
m.topLeft.set( topLeft[1].toDouble(), topLeft[0].toDouble() );
if ( !mIgnoreAxisOrientation && crs.axisInverted() )
{
m.topLeft.set( topLeft[1].toDouble(), topLeft[0].toDouble() );
}
else
{
m.topLeft.set( topLeft[0].toDouble(), topLeft[1].toDouble() );
}
}
else
{
Expand All @@ -2509,11 +2543,13 @@ void QgsWmsProvider::parseWMTSContents( QDomElement const &e )

double res = m.scaleDenom * 0.00028 / metersPerUnit;

QgsDebugMsg( QString( " %1: scale=%2 res=%3 tile=%4x%5 matrix=%6x%7" )
QgsDebugMsg( QString( " %1: scale=%2 res=%3 tile=%4x%5 matrix=%6x%7 topLeft=%8" )
.arg( m.identifier )
.arg( m.scaleDenom ).arg( res )
.arg( m.tileWidth ).arg( m.tileHeight )
.arg( m.matrixWidth ).arg( m.matrixHeight ) );
.arg( m.matrixWidth ).arg( m.matrixHeight )
.arg( m.topLeft.toString() )
);

s.tileMatrices.insert( res, m );
}
Expand Down Expand Up @@ -2635,6 +2671,8 @@ void QgsWmsProvider::parseWMTSContents( QDomElement const &e )
continue;
}

const QgsWmtsTileMatrixSet &tms = mTileMatrixSets[ sl.tileMatrixSet ];

for ( QDomElement e2 = e1.firstChildElement( "TileMatrixSetLimits" ); !e2.isNull(); e2 = e2.nextSiblingElement( "TileMatrixSetLimits" ) )
{
for ( QDomElement e3 = e2.firstChildElement( "TileMatrixLimits" ); !e3.isNull(); e3 = e3.nextSiblingElement( "TileMatrixLimits" ) )
Expand All @@ -2643,17 +2681,56 @@ void QgsWmsProvider::parseWMTSContents( QDomElement const &e )

QString id = e3.firstChildElement( "TileMatrix" ).text();

limit.minTileRow = e3.firstChildElement( "MinTileRow" ).text().toInt();
limit.maxTileRow = e3.firstChildElement( "MaxTileRow" ).text().toInt();
limit.minTileCol = e3.firstChildElement( "MinTileCol" ).text().toInt();
limit.maxTileCol = e3.firstChildElement( "MaxTileCol" ).text().toInt();
bool isValid = false;
int matrixWidth = -1, matrixHeight = -1;
foreach( const QgsWmtsTileMatrix &m, tms.tileMatrices )
{
isValid = m.identifier == id;
if ( isValid )
{
matrixWidth = m.matrixWidth;
matrixHeight = m.matrixHeight;
break;
}
}

QgsDebugMsg( QString( " TileMatrix id:%1 row:%2-%3 col:%4-%5" )
if ( isValid )
{
limit.minTileRow = e3.firstChildElement( "MinTileRow" ).text().toInt();
limit.maxTileRow = e3.firstChildElement( "MaxTileRow" ).text().toInt();
limit.minTileCol = e3.firstChildElement( "MinTileCol" ).text().toInt();
limit.maxTileCol = e3.firstChildElement( "MaxTileCol" ).text().toInt();

isValid =
limit.minTileCol >= 0 && limit.minTileCol < matrixWidth &&
limit.maxTileCol >= 0 && limit.maxTileCol < matrixWidth &&
limit.minTileCol <= limit.maxTileCol &&
limit.minTileRow >= 0 && limit.minTileRow < matrixHeight &&
limit.maxTileRow >= 0 && limit.maxTileRow < matrixHeight &&
limit.minTileRow <= limit.maxTileRow;
}
else
{
QgsDebugMsg( QString( " TileMatrix id:%1 not found." ).arg( id ) );
}

QgsDebugMsg( QString( " TileMatrixLimit id:%1 row:%2-%3 col:%4-%5 %6" )
.arg( id )
.arg( limit.minTileRow ).arg( limit.maxTileRow )
.arg( limit.minTileCol ).arg( limit.maxTileCol )
.arg( isValid ? "valid" : "INVALID" )
);
sl.limits.insert( id, limit );

if ( isValid )
{
sl.limits.insert( id, limit );
}
else
{
QgsDebugMsg( QString( "Limit of tileset %1 of matrix set %2 of layer %3 is invalid - ignored" )
.arg( id ).arg( sl.tileMatrixSet ).arg( l.identifier )
);
}
}
}

Expand Down Expand Up @@ -3618,7 +3695,7 @@ QStringList QgsWmsProvider::identifyAs( const QgsPoint& point, QString format )

//according to the WMS spec for 1.3, the order of x - and y - coordinates is inverted for geographical CRS
bool changeXY = false;
if ( mCapabilities.version == "1.3.0" || mCapabilities.version == "1.3" )
if ( !mIgnoreAxisOrientation && ( mCapabilities.version == "1.3.0" || mCapabilities.version == "1.3" ) )
{
//create CRS from string
QgsCoordinateReferenceSystem theSrs;
Expand Down
1 change: 1 addition & 0 deletions src/providers/wms/qgswmsprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,7 @@ class QgsWmsProvider : public QgsRasterDataProvider
// the given base urls for GetMap and GetFeatureInfo
bool mIgnoreGetMapUrl;
bool mIgnoreGetFeatureInfoUrl;
bool mIgnoreAxisOrientation;

//! supported formats for GetFeatureInfo in order of preference
QStringList mSupportedGetFeatureFormats;
Expand Down
Loading

0 comments on commit f3330e6

Please sign in to comment.