Skip to content

Commit f3330e6

Browse files
committedMay 17, 2012
wmts fixes:
- [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
1 parent e454c5f commit f3330e6

File tree

7 files changed

+164
-41
lines changed

7 files changed

+164
-41
lines changed
 

‎src/core/qgscoordinatereferencesystem.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,29 @@ bool QgsCoordinateReferenceSystem::createFromOgcWmsCrs( QString theCrs )
150150
if ( loadFromDb( QgsApplication::srsDbFilePath(), "lower(auth_name||':'||auth_id)", theCrs.toLower() ) )
151151
return true;
152152

153+
// NAD27
154+
if ( theCrs.compare( "CRS:27", Qt::CaseInsensitive ) == 0 ||
155+
theCrs.compare( "OGC:CRS27", Qt::CaseInsensitive ) == 0 )
156+
{
157+
// TODO: verify same axis orientation
158+
return createFromEpsg( 4267 );
159+
}
160+
161+
// NAD83
162+
if ( theCrs.compare( "CRS:83", Qt::CaseInsensitive ) == 0 ||
163+
theCrs.compare( "OGC:CRS83", Qt::CaseInsensitive ) == 0 )
164+
{
165+
// TODO: verify same axis orientation
166+
return createFromEpsg( 4269 );
167+
}
168+
169+
// WGS84
153170
if ( theCrs.compare( "CRS:84", Qt::CaseInsensitive ) == 0 ||
154171
theCrs.compare( "OGC:CRS84", Qt::CaseInsensitive ) == 0 )
155172
{
156-
createFromSrsId( GEOCRS_ID );
157-
return true;
173+
createFromEpsg( 4326 );
174+
mAxisInverted = 0;
175+
return mIsValidFlag;
158176
}
159177

160178
return false;

‎src/gui/qgsmanageconnectionsdialog.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ QDomDocument QgsManageConnectionsDialog::saveWMSConnections( const QStringList &
305305
el.setAttribute( "url", settings.value( path + connections[ i ] + "/url", "" ).toString() );
306306
el.setAttribute( "ignoreGetMapURI", settings.value( path + connections[i] + "/ignoreGetMapURI", false ).toBool() ? "true" : "false" );
307307
el.setAttribute( "ignoreGetFeatureInfoURI", settings.value( path + connections[i] + "/ignoreGetFeatureInfoURI", false ).toBool() ? "true" : "false" );
308+
el.setAttribute( "ignoreAxisOrientation", settings.value( path + connections[i] + "/ignoreAxisOrientation", false ).toBool() ? "true" : "false" );
308309

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

496498
if ( !child.attribute( "username" ).isEmpty() )

‎src/gui/qgsnewhttpconnection.cpp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,13 @@ QgsNewHttpConnection::QgsNewHttpConnection(
5252
{
5353
cbxIgnoreGetMapURI->setChecked( settings.value( key + "/ignoreGetMapURI", false ).toBool() );
5454
cbxIgnoreGetFeatureInfoURI->setChecked( settings.value( key + "/ignoreGetFeatureInfoURI", false ).toBool() );
55+
cbxIgnoreAxisOrientation->setChecked( settings.value( key + "/ignoreAxisOrientation", false ).toBool() );
5556
}
5657
else
5758
{
5859
cbxIgnoreGetMapURI->setVisible( false );
5960
cbxIgnoreGetFeatureInfoURI->setVisible( false );
61+
cbxIgnoreAxisOrientation->setVisible( false );
6062
}
6163

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

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

104-
QList< QPair<QByteArray, QByteArray> > params = url.encodedQueryItems();
105-
for ( int i = 0; i < params.size(); i++ )
112+
if ( params["SERVICE"].second.toUpper() == "WMS" )
106113
{
107-
if ( params[i].first.toUpper() == "SERVICE" ||
108-
params[i].first.toUpper() == "REQUEST" ||
109-
params[i].first.toUpper() == "FORMAT" )
110-
{
111-
params.removeAt( i-- );
112-
}
114+
params.remove( "SERVICE" );
115+
params.remove( "REQUEST" );
116+
params.remove( "FORMAT" );
113117
}
114-
url.setEncodedQueryItems( params );
118+
119+
url.setEncodedQueryItems( params.values() );
115120

116121
settings.setValue( key + "/url", url.toString() );
117122
if ( mBaseKey == "/Qgis/connections-wms/" )
118123
{
119124
settings.setValue( key + "/ignoreGetMapURI", cbxIgnoreGetMapURI->isChecked() );
120125
settings.setValue( key + "/ignoreGetFeatureInfoURI", cbxIgnoreGetFeatureInfoURI->isChecked() );
126+
settings.setValue( key + "/ignoreAxisOrientation", cbxIgnoreAxisOrientation->isChecked() );
121127
}
122128

123129
settings.setValue( credentialsKey + "/username", txtUserName->text() );

‎src/providers/wms/qgswmsconnection.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,29 @@ QgsWMSConnection::QgsWMSConnection( QString theConnName ) :
6262

6363
bool ignoreGetMap = settings.value( key + "/ignoreGetMapURI", false ).toBool();
6464
bool ignoreGetFeatureInfo = settings.value( key + "/ignoreGetFeatureInfoURI", false ).toBool();
65-
if ( ignoreGetMap || ignoreGetFeatureInfo )
65+
bool ignoreAxisOrientation = settings.value( key + "/ignoreAxisOrientation", false ).toBool();
66+
if ( ignoreGetMap || ignoreGetFeatureInfo || ignoreAxisOrientation )
6667
{
6768
QString connArgs = "ignoreUrl=";
69+
6870
if ( ignoreGetMap )
6971
{
7072
connArgs += "GetMap";
71-
if ( ignoreGetFeatureInfo )
72-
connArgs += ";";
7373
}
74+
7475
if ( ignoreGetFeatureInfo )
76+
{
77+
if ( !connArgs.endsWith( "=" ) )
78+
connArgs += ";";
7579
connArgs += "GetFeatureInfo";
80+
}
81+
82+
if ( ignoreAxisOrientation )
83+
{
84+
if ( !connArgs.endsWith( "=" ) )
85+
connArgs += ";";
86+
connArgs += "AxisOrientation";
87+
}
7688

7789
if ( mConnectionInfo.startsWith( "username=" ) )
7890
{

‎src/providers/wms/qgswmsprovider.cpp

Lines changed: 102 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ void QgsWmsProvider::parseUri( QString uri )
137137

138138
mIgnoreGetMapUrl = false;
139139
mIgnoreGetFeatureInfoUrl = false;
140+
mIgnoreAxisOrientation = false;
140141

141142
QString layer;
142143

@@ -182,6 +183,10 @@ void QgsWmsProvider::parseUri( QString uri )
182183
{
183184
mIgnoreGetFeatureInfoUrl = true;
184185
}
186+
else if ( param == "AxisOrientation" )
187+
{
188+
mIgnoreAxisOrientation = true;
189+
}
185190
}
186191
}
187192
else if ( item.startsWith( "tileMatrixSet=" ) )
@@ -337,13 +342,6 @@ size_t QgsWmsProvider::layerCount() const
337342
return 1; // XXX properly return actual number of layers
338343
} // QgsWmsProvider::layerCount()
339344

340-
#if 0
341-
bool QgsWmsProvider::hasTiles() const
342-
{
343-
return mCapabilities.capability.tileSetProfiles.size() > 0;
344-
}
345-
#endif
346-
347345
QString QgsWmsProvider::baseUrl() const
348346
{
349347
return mBaseUrl;
@@ -534,7 +532,7 @@ QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, i
534532

535533
//according to the WMS spec for 1.3, some CRS have inverted axis
536534
bool changeXY = false;
537-
if ( mCapabilities.version == "1.3.0" || mCapabilities.version == "1.3" )
535+
if ( !mIgnoreAxisOrientation && ( mCapabilities.version == "1.3.0" || mCapabilities.version == "1.3" ) )
538536
{
539537
//create CRS from string
540538
QgsCoordinateReferenceSystem theSrs;
@@ -1070,10 +1068,10 @@ void QgsWmsProvider::tileReplyFinished()
10701068
r.width() / cr,
10711069
r.height() / cr );
10721070

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

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

10781076
if ( !myLocalImage.isNull() )
10791077
{
@@ -1092,7 +1090,10 @@ void QgsWmsProvider::tileReplyFinished()
10921090
{
10931091
QgsMessageLog::logMessage( tr( "Returned image is flawed [%1]" ).arg( reply->url().toString() ), tr( "WMS" ) );
10941092
}
1095-
1093+
}
1094+
else
1095+
{
1096+
QgsMessageLog::logMessage( tr( "Reply to earlier tile request received too late [%1]" ).arg( reply->url().toString() ), tr( "WMS" ) );
10961097
}
10971098

10981099
mTileReplies.removeOne( reply );
@@ -1106,9 +1107,18 @@ void QgsWmsProvider::tileReplyFinished()
11061107
}
11071108
else
11081109
{
1110+
mErrors++;
1111+
if ( mErrors < 100 )
1112+
{
1113+
QgsMessageLog::logMessage( tr( "Tile request failed [error:%1 url:%2]" ).arg( reply->errorString() ).arg( reply->url().toString() ), tr( "WMS" ) );
1114+
}
1115+
else if ( mErrors == 100 )
1116+
{
1117+
QgsMessageLog::logMessage( tr( "Not logging more than 100 request errors." ), tr( "WMS" ) );
1118+
}
1119+
11091120
mTileReplies.removeOne( reply );
11101121
reply->deleteLater();
1111-
mErrors++;
11121122
}
11131123

11141124
#ifdef QGISDEBUG
@@ -1200,9 +1210,18 @@ void QgsWmsProvider::cacheReplyFinished()
12001210
}
12011211
else
12021212
{
1213+
mErrors++;
1214+
if ( mErrors < 100 )
1215+
{
1216+
QgsMessageLog::logMessage( tr( "Map request failed [error:%1 url:%2]" ).arg( mCacheReply->errorString() ).arg( mCacheReply->url().toString() ), tr( "WMS" ) );
1217+
}
1218+
else if ( mErrors == 100 )
1219+
{
1220+
QgsMessageLog::logMessage( tr( "Not logging more than 100 request errors." ), tr( "WMS" ) );
1221+
}
1222+
12031223
mCacheReply->deleteLater();
12041224
mCacheReply = 0;
1205-
mErrors++;
12061225
}
12071226
}
12081227

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

2468+
QString supportedCRS = n0.firstChildElement( "ows:SupportedCRS" ).text();
2469+
24492470
QgsCoordinateReferenceSystem crs;
2450-
crs.createFromOgcWmsCrs( n0.firstChildElement( "ows:SupportedCRS" ).text() );
2471+
crs.createFromOgcWmsCrs( supportedCRS );
24512472

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

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

24772498
s.crs = crs.authid();
24782499

2479-
QgsDebugMsg( QString( "tilematrix set: %1 (crs:%2; metersPerUnit:%3)" ).arg( s.identifier ).arg( s.crs ).arg( metersPerUnit, 0, 'f' ) );
2500+
QgsDebugMsg( QString( "tilematrix set: %1 (supportedCRS:%2 crs:%3; metersPerUnit:%4 axisInverted:%5)" )
2501+
.arg( s.identifier )
2502+
.arg( supportedCRS )
2503+
.arg( s.crs )
2504+
.arg( metersPerUnit, 0, 'f' )
2505+
.arg( !mIgnoreAxisOrientation && crs.axisInverted() ? "yes" : "no" )
2506+
);
24802507

24812508
for ( QDomNode n1 = n0.firstChildElement( "TileMatrix" );
24822509
!n1.isNull();
@@ -2494,7 +2521,14 @@ void QgsWmsProvider::parseWMTSContents( QDomElement const &e )
24942521
QStringList topLeft = n1.firstChildElement( "TopLeftCorner" ).text().split( " " );
24952522
if ( topLeft.size() == 2 )
24962523
{
2497-
m.topLeft.set( topLeft[1].toDouble(), topLeft[0].toDouble() );
2524+
if ( !mIgnoreAxisOrientation && crs.axisInverted() )
2525+
{
2526+
m.topLeft.set( topLeft[1].toDouble(), topLeft[0].toDouble() );
2527+
}
2528+
else
2529+
{
2530+
m.topLeft.set( topLeft[0].toDouble(), topLeft[1].toDouble() );
2531+
}
24982532
}
24992533
else
25002534
{
@@ -2509,11 +2543,13 @@ void QgsWmsProvider::parseWMTSContents( QDomElement const &e )
25092543

25102544
double res = m.scaleDenom * 0.00028 / metersPerUnit;
25112545

2512-
QgsDebugMsg( QString( " %1: scale=%2 res=%3 tile=%4x%5 matrix=%6x%7" )
2546+
QgsDebugMsg( QString( " %1: scale=%2 res=%3 tile=%4x%5 matrix=%6x%7 topLeft=%8" )
25132547
.arg( m.identifier )
25142548
.arg( m.scaleDenom ).arg( res )
25152549
.arg( m.tileWidth ).arg( m.tileHeight )
2516-
.arg( m.matrixWidth ).arg( m.matrixHeight ) );
2550+
.arg( m.matrixWidth ).arg( m.matrixHeight )
2551+
.arg( m.topLeft.toString() )
2552+
);
25172553

25182554
s.tileMatrices.insert( res, m );
25192555
}
@@ -2635,6 +2671,8 @@ void QgsWmsProvider::parseWMTSContents( QDomElement const &e )
26352671
continue;
26362672
}
26372673

2674+
const QgsWmtsTileMatrixSet &tms = mTileMatrixSets[ sl.tileMatrixSet ];
2675+
26382676
for ( QDomElement e2 = e1.firstChildElement( "TileMatrixSetLimits" ); !e2.isNull(); e2 = e2.nextSiblingElement( "TileMatrixSetLimits" ) )
26392677
{
26402678
for ( QDomElement e3 = e2.firstChildElement( "TileMatrixLimits" ); !e3.isNull(); e3 = e3.nextSiblingElement( "TileMatrixLimits" ) )
@@ -2643,17 +2681,56 @@ void QgsWmsProvider::parseWMTSContents( QDomElement const &e )
26432681

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

2646-
limit.minTileRow = e3.firstChildElement( "MinTileRow" ).text().toInt();
2647-
limit.maxTileRow = e3.firstChildElement( "MaxTileRow" ).text().toInt();
2648-
limit.minTileCol = e3.firstChildElement( "MinTileCol" ).text().toInt();
2649-
limit.maxTileCol = e3.firstChildElement( "MaxTileCol" ).text().toInt();
2684+
bool isValid = false;
2685+
int matrixWidth = -1, matrixHeight = -1;
2686+
foreach( const QgsWmtsTileMatrix &m, tms.tileMatrices )
2687+
{
2688+
isValid = m.identifier == id;
2689+
if ( isValid )
2690+
{
2691+
matrixWidth = m.matrixWidth;
2692+
matrixHeight = m.matrixHeight;
2693+
break;
2694+
}
2695+
}
26502696

2651-
QgsDebugMsg( QString( " TileMatrix id:%1 row:%2-%3 col:%4-%5" )
2697+
if ( isValid )
2698+
{
2699+
limit.minTileRow = e3.firstChildElement( "MinTileRow" ).text().toInt();
2700+
limit.maxTileRow = e3.firstChildElement( "MaxTileRow" ).text().toInt();
2701+
limit.minTileCol = e3.firstChildElement( "MinTileCol" ).text().toInt();
2702+
limit.maxTileCol = e3.firstChildElement( "MaxTileCol" ).text().toInt();
2703+
2704+
isValid =
2705+
limit.minTileCol >= 0 && limit.minTileCol < matrixWidth &&
2706+
limit.maxTileCol >= 0 && limit.maxTileCol < matrixWidth &&
2707+
limit.minTileCol <= limit.maxTileCol &&
2708+
limit.minTileRow >= 0 && limit.minTileRow < matrixHeight &&
2709+
limit.maxTileRow >= 0 && limit.maxTileRow < matrixHeight &&
2710+
limit.minTileRow <= limit.maxTileRow;
2711+
}
2712+
else
2713+
{
2714+
QgsDebugMsg( QString( " TileMatrix id:%1 not found." ).arg( id ) );
2715+
}
2716+
2717+
QgsDebugMsg( QString( " TileMatrixLimit id:%1 row:%2-%3 col:%4-%5 %6" )
26522718
.arg( id )
26532719
.arg( limit.minTileRow ).arg( limit.maxTileRow )
26542720
.arg( limit.minTileCol ).arg( limit.maxTileCol )
2721+
.arg( isValid ? "valid" : "INVALID" )
26552722
);
2656-
sl.limits.insert( id, limit );
2723+
2724+
if ( isValid )
2725+
{
2726+
sl.limits.insert( id, limit );
2727+
}
2728+
else
2729+
{
2730+
QgsDebugMsg( QString( "Limit of tileset %1 of matrix set %2 of layer %3 is invalid - ignored" )
2731+
.arg( id ).arg( sl.tileMatrixSet ).arg( l.identifier )
2732+
);
2733+
}
26572734
}
26582735
}
26592736

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

36193696
//according to the WMS spec for 1.3, the order of x - and y - coordinates is inverted for geographical CRS
36203697
bool changeXY = false;
3621-
if ( mCapabilities.version == "1.3.0" || mCapabilities.version == "1.3" )
3698+
if ( !mIgnoreAxisOrientation && ( mCapabilities.version == "1.3.0" || mCapabilities.version == "1.3" ) )
36223699
{
36233700
//create CRS from string
36243701
QgsCoordinateReferenceSystem theSrs;

‎src/providers/wms/qgswmsprovider.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,7 @@ class QgsWmsProvider : public QgsRasterDataProvider
11061106
// the given base urls for GetMap and GetFeatureInfo
11071107
bool mIgnoreGetMapUrl;
11081108
bool mIgnoreGetFeatureInfoUrl;
1109+
bool mIgnoreAxisOrientation;
11091110

11101111
//! supported formats for GetFeatureInfo in order of preference
11111112
QStringList mSupportedGetFeatureFormats;

‎src/ui/qgsnewhttpconnectionbase.ui

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,20 +128,27 @@
128128
</property>
129129
</widget>
130130
</item>
131-
<item row="8" column="0" colspan="2">
131+
<item row="9" column="0" colspan="2">
132132
<widget class="QCheckBox" name="cbxIgnoreGetFeatureInfoURI">
133133
<property name="text">
134134
<string>Ignore GetFeatureInfo URI reported in capabilities</string>
135135
</property>
136136
</widget>
137137
</item>
138-
<item row="7" column="0" colspan="2">
138+
<item row="8" column="0" colspan="2">
139139
<widget class="QCheckBox" name="cbxIgnoreGetMapURI">
140140
<property name="text">
141141
<string>Ignore GetMap URI reported in capabilities</string>
142142
</property>
143143
</widget>
144144
</item>
145+
<item row="10" column="0" colspan="2">
146+
<widget class="QCheckBox" name="cbxIgnoreAxisOrientation">
147+
<property name="text">
148+
<string>Ignore axis orientation (WMS 1.3/WMTS)</string>
149+
</property>
150+
</widget>
151+
</item>
145152
</layout>
146153
</widget>
147154
</item>

0 commit comments

Comments
 (0)
Please sign in to comment.