mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-06 00:07:29 -04:00
qgsogcutils: Fix axis inversion in geometryFromGML
`QgsOgcUtils::geometryFromGML` converts a GML to a QgsGeometry. in the GML3 case, this checks if the X/Y coordinates need to be inverted only if a context is provided and the destination crs is different from the source crs. However, the check for axis inversion should be done whether a context is provided or not. This issue is fixed by the moving the `srsName` and `swapXy` logic before the context check.
This commit is contained in:
parent
41ad493cbd
commit
9f64afe421
@ -156,50 +156,49 @@ QgsGeometry QgsOgcUtils::geometryFromGML( const QDomNode &geometryNode, const Co
|
||||
return geometry;
|
||||
}
|
||||
|
||||
// Handle srsName if context has information about the layer and the transformation context
|
||||
if ( context.layer )
|
||||
// Handle srsName
|
||||
// Check if the XY coordinates of geometry need to be swapped by checking the srs from the GML
|
||||
QgsCoordinateReferenceSystem geomSrs;
|
||||
if ( geometryTypeElement.hasAttribute( QStringLiteral( "srsName" ) ) )
|
||||
{
|
||||
QgsCoordinateReferenceSystem geomSrs;
|
||||
QString srsName { geometryTypeElement.attribute( QStringLiteral( "srsName" ) ) };
|
||||
|
||||
if ( geometryTypeElement.hasAttribute( 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( QLatin1String( "http://www.opengis.net/gml/srs/" ) ) || srsName.startsWith( QLatin1String( "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( QLatin1String( "http://www.opengis.net/gml/srs/" ) ) )
|
||||
{
|
||||
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( QLatin1String( "http://www.opengis.net/gml/srs/" ) ) || srsName.startsWith( QLatin1String( "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( QLatin1String( "http://www.opengis.net/gml/srs/" ) ) )
|
||||
const auto parts { srsName.split( QRegularExpression( QStringLiteral( R"raw(/|#|\.)raw" ) ) ) };
|
||||
if ( parts.length() == 10 )
|
||||
{
|
||||
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 ] );
|
||||
}
|
||||
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() )
|
||||
}
|
||||
geomSrs.createFromUserInput( srsName );
|
||||
if ( geomSrs.isValid() && geomSrs.hasAxisInverted() && !ignoreAxisOrientation )
|
||||
{
|
||||
geometry.get()->swapXy();
|
||||
}
|
||||
}
|
||||
|
||||
// Apply a coordinate transformation if context has information about the layer and the transformation context
|
||||
if ( geomSrs.isValid() && context.layer && geomSrs != context.layer->crs() )
|
||||
{
|
||||
const QgsCoordinateTransform transformer { geomSrs, context.layer->crs(), context.transformContext };
|
||||
try
|
||||
{
|
||||
const Qgis::GeometryOperationResult result = geometry.transform( transformer );
|
||||
if ( result != Qgis::GeometryOperationResult::Success )
|
||||
{
|
||||
if ( geomSrs.hasAxisInverted() && ! ignoreAxisOrientation )
|
||||
{
|
||||
geometry.get()->swapXy();
|
||||
}
|
||||
const QgsCoordinateTransform transformer { geomSrs, context.layer->crs(), context.transformContext };
|
||||
try
|
||||
{
|
||||
const Qgis::GeometryOperationResult result = geometry.transform( transformer );
|
||||
if ( result != Qgis::GeometryOperationResult::Success )
|
||||
{
|
||||
QgsDebugMsgLevel( QStringLiteral( "Error transforming geometry: %1" ).arg( qgsEnumValueToKey( result ) ), 2 );
|
||||
}
|
||||
}
|
||||
catch ( QgsCsException & )
|
||||
{
|
||||
QgsDebugMsgLevel( QStringLiteral( "CS error transforming geometry" ), 2 );
|
||||
}
|
||||
QgsDebugMsgLevel( QStringLiteral( "Error transforming geometry: %1" ).arg( qgsEnumValueToKey( result ) ), 2 );
|
||||
}
|
||||
}
|
||||
catch ( QgsCsException & )
|
||||
{
|
||||
QgsDebugMsgLevel( QStringLiteral( "CS error transforming geometry" ), 2 );
|
||||
}
|
||||
}
|
||||
|
||||
return geometry;
|
||||
|
@ -105,6 +105,13 @@ void TestQgsOgcUtils::testGeometryFromGML()
|
||||
QVERIFY( !geomBox.isNull() );
|
||||
QVERIFY( geomBox.wkbType() == Qgis::WkbType::Polygon );
|
||||
|
||||
// Test point GML2 with EPSG:4326
|
||||
// X/Y coordinates are not inverted
|
||||
geom = QgsOgcUtils::geometryFromGML( QStringLiteral( "<gml:Point srsName=\"EPSG:4326\"><gml:coordinates>4,45</gml:coordinates></gml:Point>" ) );
|
||||
QVERIFY( !geom.isNull() );
|
||||
QVERIFY( geom.wkbType() == Qgis::WkbType::Point );
|
||||
QVERIFY( geom.equals( QgsGeometry::fromWkt( QStringLiteral( "POINT (4 45)" ) ) ) );
|
||||
|
||||
|
||||
// Test GML3
|
||||
geom = QgsOgcUtils::geometryFromGML( QStringLiteral( "<Point><pos>123 456</pos></Point>" ) );
|
||||
@ -133,6 +140,21 @@ void TestQgsOgcUtils::testGeometryFromGML()
|
||||
QVERIFY( !geom.isNull() );
|
||||
QVERIFY( geom.wkbType() == Qgis::WkbType::LineStringZ );
|
||||
QVERIFY( geom.equals( QgsGeometry::fromWkt( QStringLiteral( "LINESTRINGZ(0 0 1200, 0 1 1250, 1 1 1230, 1 0 1210)" ) ) ) );
|
||||
|
||||
// Test point GML3 with urn:ogc:def:crs:EPSG::4326
|
||||
// X/Y coordinates are inverted
|
||||
geom = QgsOgcUtils::geometryFromGML( QStringLiteral( "<gml:Point srsName=\"urn:ogc:def:crs:EPSG::4326\"><gml:pos>45 4</gml:pos></gml:Point>" ) );
|
||||
QVERIFY( !geom.isNull() );
|
||||
QVERIFY( geom.wkbType() == Qgis::WkbType::Point );
|
||||
QVERIFY( geom.equals( QgsGeometry::fromWkt( QStringLiteral( "POINT (4 45)" ) ) ) );
|
||||
|
||||
|
||||
// Test point GML3 with urn:ogc:def:crs:EPSG::3857
|
||||
// X/Y coordinates are not inverted
|
||||
geom = QgsOgcUtils::geometryFromGML( QStringLiteral( "<gml:Point srsName=\"urn:ogc:def:crs:EPSG::3857\"><gml:pos>32 2</gml:pos></gml:Point>" ) );
|
||||
QVERIFY( !geom.isNull() );
|
||||
QVERIFY( geom.wkbType() == Qgis::WkbType::Point );
|
||||
QVERIFY( geom.equals( QgsGeometry::fromWkt( QStringLiteral( "POINT (32 2)" ) ) ) );
|
||||
}
|
||||
|
||||
void TestQgsOgcUtils::testGeometryFromGMLWithZ_data()
|
||||
|
Loading…
x
Reference in New Issue
Block a user