mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-07 00:15:48 -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;
|
return geometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle srsName if context has information about the layer and the transformation context
|
// Handle srsName
|
||||||
if ( context.layer )
|
// 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" ) ) };
|
const auto parts { srsName.split( QRegularExpression( QStringLiteral( R"raw(/|#|\.)raw" ) ) ) };
|
||||||
|
if ( parts.length() == 10 )
|
||||||
// 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" ) ) ) };
|
srsName = QStringLiteral( "http://www.opengis.net/def/crs/%1/0/%2" ).arg( parts[ 7 ].toUpper(), parts[ 9 ] );
|
||||||
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() )
|
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 )
|
QgsDebugMsgLevel( QStringLiteral( "Error transforming geometry: %1" ).arg( qgsEnumValueToKey( result ) ), 2 );
|
||||||
{
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch ( QgsCsException & )
|
||||||
|
{
|
||||||
|
QgsDebugMsgLevel( QStringLiteral( "CS error transforming geometry" ), 2 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return geometry;
|
return geometry;
|
||||||
|
@ -105,6 +105,13 @@ void TestQgsOgcUtils::testGeometryFromGML()
|
|||||||
QVERIFY( !geomBox.isNull() );
|
QVERIFY( !geomBox.isNull() );
|
||||||
QVERIFY( geomBox.wkbType() == Qgis::WkbType::Polygon );
|
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
|
// Test GML3
|
||||||
geom = QgsOgcUtils::geometryFromGML( QStringLiteral( "<Point><pos>123 456</pos></Point>" ) );
|
geom = QgsOgcUtils::geometryFromGML( QStringLiteral( "<Point><pos>123 456</pos></Point>" ) );
|
||||||
@ -133,6 +140,21 @@ void TestQgsOgcUtils::testGeometryFromGML()
|
|||||||
QVERIFY( !geom.isNull() );
|
QVERIFY( !geom.isNull() );
|
||||||
QVERIFY( geom.wkbType() == Qgis::WkbType::LineStringZ );
|
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)" ) ) ) );
|
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()
|
void TestQgsOgcUtils::testGeometryFromGMLWithZ_data()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user