Skip to content

Commit

Permalink
Server WFS: handle axis orientation
Browse files Browse the repository at this point in the history
Fixes #36584

Cherry-picked from master 84f61ff.
  • Loading branch information
elpaso authored and nyalldawson committed Feb 19, 2021
1 parent f1b056b commit c2bf502
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 8 deletions.
21 changes: 20 additions & 1 deletion src/core/qgsogcutils.cpp
Expand Up @@ -141,9 +141,28 @@ QgsGeometry QgsOgcUtils::geometryFromGML( const QDomNode &geometryNode, const Co

if ( geometryTypeElement.hasAttribute( QStringLiteral( "srsName" ) ) )
{
geomSrs.createFromString( geometryTypeElement.attribute( QStringLiteral( "srsName" ) ) );
QString srsName { geometryTypeElement.attribute( QStringLiteral( "srsName" ) ) };

// The logic here follows WFS GeoServer conventions from https://docs.geoserver.org/latest/en/user/services/wfs/axis_order.html
const bool ignoreAxisOrientation { srsName.startsWith( QStringLiteral( "http://www.opengis.net/gml/srs/" ) ) || srsName.startsWith( QStringLiteral( "EPSG:" ) ) };

// GDAL does not recognise http://www.opengis.net/gml/srs/epsg.xml#4326 but it does
// http://www.opengis.net/def/crs/EPSG/0/4326 so, let's try that
if ( srsName.startsWith( QStringLiteral( "http://www.opengis.net/gml/srs/" ) ) )
{
const auto parts { srsName.split( QRegularExpression( QStringLiteral( R"raw(/|#|\.)raw" ) ) ) };
if ( parts.length() == 10 )
{
srsName = QStringLiteral( "http://www.opengis.net/def/crs/%1/0/%2" ).arg( parts[ 7 ].toUpper(), parts[ 9 ] );
}
}
geomSrs.createFromUserInput( srsName );
if ( geomSrs.isValid() && geomSrs != context.layer->crs() )
{
if ( geomSrs.hasAxisInverted() && ! ignoreAxisOrientation )
{
geometry.get()->swapXy();
}
const QgsCoordinateTransform transformer { geomSrs, context.layer->crs(), context.transformContext };
try
{
Expand Down
2 changes: 1 addition & 1 deletion src/server/services/wfs/qgswfstransaction.cpp
Expand Up @@ -716,7 +716,7 @@ namespace QgsWfs
catch ( QgsOgcServiceException &ex )
{
action.error = true;
action.errorMsg = QStringLiteral( "%1 '%2'" ).arg( ex.message() ).arg( typeName );
action.errorMsg = QStringLiteral( "%1 '%2'" ).arg( ex.message(), typeName );
continue;
}

Expand Down
12 changes: 8 additions & 4 deletions src/server/services/wfs/qgswfstransaction_1_0_0.cpp
Expand Up @@ -687,12 +687,12 @@ namespace QgsWfs
QgsFeatureList featureList;
try
{
featureList = featuresFromGML( action.featureNodeList, provider );
featureList = featuresFromGML( action.featureNodeList, vlayer );
}
catch ( QgsOgcServiceException &ex )
{
action.error = true;
action.errorMsg = QStringLiteral( "%1 '%2'" ).arg( ex.message() ).arg( typeName );
action.errorMsg = QStringLiteral( "%1 '%2'" ).arg( ex.message(), typeName );
continue;
}

Expand Down Expand Up @@ -762,11 +762,14 @@ namespace QgsWfs
filterRestorer.reset();
}

QgsFeatureList featuresFromGML( QDomNodeList featureNodeList, QgsVectorDataProvider *provider )
QgsFeatureList featuresFromGML( QDomNodeList featureNodeList, QgsVectorLayer *layer )
{
// Store the inserted features
QgsFeatureList featList;

const auto provider { layer->dataProvider() };
Q_ASSERT( provider );

// Get Layer Field Information
QgsFields fields = provider->fields();
const QMap<QString, int> fieldMap = provider->fieldNameMap();
Expand Down Expand Up @@ -815,7 +818,8 @@ namespace QgsWfs
}
else //a geometry attribute
{
QgsGeometry g = QgsOgcUtils::geometryFromGML( currentAttributeElement );
const QgsOgcUtils::Context context { layer, provider->transformContext() };
QgsGeometry g = QgsOgcUtils::geometryFromGML( currentAttributeElement, context );
if ( g.isNull() )
{
throw QgsRequestNotWellFormedException( QStringLiteral( "Geometry from GML error on layer insert" ) );
Expand Down
2 changes: 1 addition & 1 deletion src/server/services/wfs/qgswfstransaction_1_0_0.h
Expand Up @@ -110,7 +110,7 @@ namespace QgsWfs
/**
* Transform GML feature nodes to features
*/
QgsFeatureList featuresFromGML( QDomNodeList featureNodeList, QgsVectorDataProvider *provider );
QgsFeatureList featuresFromGML( QDomNodeList featureNodeList, QgsVectorLayer *layer );

/**
* Perform the transaction
Expand Down
2 changes: 1 addition & 1 deletion tests/src/python/test_qgsserver_wfs.py
Expand Up @@ -724,7 +724,7 @@ def _test(version, srsName, lat_lon=False):
query_string, requestMethod=QgsServerRequest.PostMethod, data=request.encode('utf-8'))
feature = next(vl.getFeatures(QgsFeatureRequest(QgsExpression('"name" = \'%s\'' % name))))
geom = feature.geometry()
self.assertEqual(geom.asWkt(0), geom_4326.asWkt(0), "Transaction Failed: %s , %s, lat_lon=%s" % (version, srsName, lat_lon))
self.assertEqual(geom.asWkt(0), geom_4326.asWkt(0), "Failed: %s , %s, lat_lon=%s" % (version, srsName, lat_lon))

_test('1.1.0', 'urn:ogc:def:crs:EPSG::4326', lat_lon=True)
_test('1.1.0', 'http://www.opengis.net/def/crs/EPSG/0/4326', lat_lon=True)
Expand Down
Binary file modified tests/testdata/qgis_server/test_project_wms_grouped_layers.gpkg
Binary file not shown.

0 comments on commit c2bf502

Please sign in to comment.