Skip to content
Permalink
Browse files

Increase precision of georeferencing coordinates used when creating G…

…eoPDF composition file

Fixes shift in geopdf feature positions when using geographic CRS at large scales

Fixes #37755
  • Loading branch information
nyalldawson committed Sep 22, 2020
1 parent 1f74f0e commit 0b77f187ec5a14651457fd07f306cba2511fb854
Showing with 20 additions and 18 deletions.
  1. +11 −11 src/core/qgsabstractgeopdfexporter.cpp
  2. +9 −7 tests/src/core/testqgsgeopdfexport.cpp
@@ -408,16 +408,16 @@ QString QgsAbstractGeoPdfExporter::createCompositionXml( const QList<ComponentLa
// pages
QDomElement page = doc.createElement( QStringLiteral( "Page" ) );
QDomElement dpi = doc.createElement( QStringLiteral( "DPI" ) );
dpi.appendChild( doc.createTextNode( QString::number( details.dpi ) ) );
dpi.appendChild( doc.createTextNode( qgsDoubleToString( details.dpi ) ) );
page.appendChild( dpi );
// assumes DPI of 72, which is an assumption on GDALs/PDF side. It's only related to the PDF coordinate space and doesn't affect the actual output DPI!
QDomElement width = doc.createElement( QStringLiteral( "Width" ) );
const double pageWidthPdfUnits = std::ceil( details.pageSizeMm.width() / 25.4 * 72 );
width.appendChild( doc.createTextNode( QString::number( pageWidthPdfUnits ) ) );
width.appendChild( doc.createTextNode( qgsDoubleToString( pageWidthPdfUnits ) ) );
page.appendChild( width );
QDomElement height = doc.createElement( QStringLiteral( "Height" ) );
const double pageHeightPdfUnits = std::ceil( details.pageSizeMm.height() / 25.4 * 72 );
height.appendChild( doc.createTextNode( QString::number( pageHeightPdfUnits ) ) );
height.appendChild( doc.createTextNode( qgsDoubleToString( pageHeightPdfUnits ) ) );
page.appendChild( height );


@@ -475,20 +475,20 @@ QString QgsAbstractGeoPdfExporter::createCompositionXml( const QList<ComponentLa
the whole PDF page will be assumed to be georeferenced.
*/
QDomElement boundingBox = doc.createElement( QStringLiteral( "BoundingBox" ) );
boundingBox.setAttribute( QStringLiteral( "x1" ), QString::number( section.pageBoundsMm.xMinimum() / 25.4 * 72 ) );
boundingBox.setAttribute( QStringLiteral( "y1" ), QString::number( section.pageBoundsMm.yMinimum() / 25.4 * 72 ) );
boundingBox.setAttribute( QStringLiteral( "x2" ), QString::number( section.pageBoundsMm.xMaximum() / 25.4 * 72 ) );
boundingBox.setAttribute( QStringLiteral( "y2" ), QString::number( section.pageBoundsMm.yMaximum() / 25.4 * 72 ) );
boundingBox.setAttribute( QStringLiteral( "x1" ), qgsDoubleToString( section.pageBoundsMm.xMinimum() / 25.4 * 72 ) );
boundingBox.setAttribute( QStringLiteral( "y1" ), qgsDoubleToString( section.pageBoundsMm.yMinimum() / 25.4 * 72 ) );
boundingBox.setAttribute( QStringLiteral( "x2" ), qgsDoubleToString( section.pageBoundsMm.xMaximum() / 25.4 * 72 ) );
boundingBox.setAttribute( QStringLiteral( "y2" ), qgsDoubleToString( section.pageBoundsMm.yMaximum() / 25.4 * 72 ) );
georeferencing.appendChild( boundingBox );
}

for ( const ControlPoint &point : section.controlPoints )
{
QDomElement cp1 = doc.createElement( QStringLiteral( "ControlPoint" ) );
cp1.setAttribute( QStringLiteral( "x" ), QString::number( point.pagePoint.x() / 25.4 * 72 ) );
cp1.setAttribute( QStringLiteral( "y" ), QString::number( ( details.pageSizeMm.height() - point.pagePoint.y() ) / 25.4 * 72 ) );
cp1.setAttribute( QStringLiteral( "GeoX" ), QString::number( point.geoPoint.x() ) );
cp1.setAttribute( QStringLiteral( "GeoY" ), QString::number( point.geoPoint.y() ) );
cp1.setAttribute( QStringLiteral( "x" ), qgsDoubleToString( point.pagePoint.x() / 25.4 * 72 ) );
cp1.setAttribute( QStringLiteral( "y" ), qgsDoubleToString( ( details.pageSizeMm.height() - point.pagePoint.y() ) / 25.4 * 72 ) );
cp1.setAttribute( QStringLiteral( "GeoX" ), qgsDoubleToString( point.geoPoint.x() ) );
cp1.setAttribute( QStringLiteral( "GeoY" ), qgsDoubleToString( point.geoPoint.y() ) );
georeferencing.appendChild( cp1 );
}

@@ -352,7 +352,7 @@ void TestQgsGeoPdfExport::testGeoref()
doc.setContent( composition );
QCOMPARE( doc.elementsByTagName( QStringLiteral( "SRS" ) ).at( 0 ).toElement().text(), QStringLiteral( "EPSG:4283" ) );
QCOMPARE( doc.elementsByTagName( QStringLiteral( "BoundingBox" ) ).at( 0 ).toElement().attribute( QStringLiteral( "x1" ) ), QStringLiteral( "0" ) );
QCOMPARE( doc.elementsByTagName( QStringLiteral( "BoundingBox" ) ).at( 0 ).toElement().attribute( QStringLiteral( "x2" ) ), QStringLiteral( "717.732" ) );
QCOMPARE( doc.elementsByTagName( QStringLiteral( "BoundingBox" ) ).at( 0 ).toElement().attribute( QStringLiteral( "x2" ) ).left( 9 ), QStringLiteral( "717.73228" ) );
QCOMPARE( doc.elementsByTagName( QStringLiteral( "BoundingBox" ) ).at( 0 ).toElement().attribute( QStringLiteral( "y1" ) ), QStringLiteral( "0" ) );
QCOMPARE( doc.elementsByTagName( QStringLiteral( "BoundingBox" ) ).at( 0 ).toElement().attribute( QStringLiteral( "y2" ) ), QStringLiteral( "630" ) );

@@ -361,16 +361,17 @@ void TestQgsGeoPdfExport::testGeoref()
QDomElement cp1;
for ( int i = 0; i < 4; ++i )
{
if ( cps.at( i ).toElement().attribute( QStringLiteral( "GeoX" ) ) == QStringLiteral( "-122.4" )
&& cps.at( i ).toElement().attribute( QStringLiteral( "GeoY" ) ) == QStringLiteral( "53.6" ) )
const QString x = cps.at( i ).toElement().attribute( QStringLiteral( "GeoX" ) ).left( 10 );
const QString y = cps.at( i ).toElement().attribute( QStringLiteral( "GeoY" ) ).left( 10 );
if ( x == QStringLiteral( "-122.40000" ) && y == QStringLiteral( "53.6000000" ) )
{
cp1 = cps.at( i ).toElement();
break;
}
}
QVERIFY( !cp1.isNull() );
QCOMPARE( cp1.attribute( QStringLiteral( "x" ) ), QStringLiteral( "0" ) );
QCOMPARE( cp1.attribute( QStringLiteral( "y" ) ), QStringLiteral( "-2.83465" ) );
QCOMPARE( cp1.attribute( QStringLiteral( "y" ) ).left( 10 ), QStringLiteral( "-2.8346456" ) );
}

void TestQgsGeoPdfExport::testGeorefPolygon()
@@ -406,16 +407,17 @@ void TestQgsGeoPdfExport::testGeorefPolygon()
QDomElement cp1;
for ( int i = 0; i < 4; ++i )
{
if ( cps.at( i ).toElement().attribute( QStringLiteral( "GeoX" ) ) == QStringLiteral( "-122.4" )
&& cps.at( i ).toElement().attribute( QStringLiteral( "GeoY" ) ) == QStringLiteral( "53.6" ) )
const QString x = cps.at( i ).toElement().attribute( QStringLiteral( "GeoX" ) ).left( 10 );
const QString y = cps.at( i ).toElement().attribute( QStringLiteral( "GeoY" ) ).left( 10 );
if ( x == QStringLiteral( "-122.40000" ) && y == QStringLiteral( "53.6000000" ) )
{
cp1 = cps.at( i ).toElement();
break;
}
}
QVERIFY( !cp1.isNull() );
QCOMPARE( cp1.attribute( QStringLiteral( "x" ) ), QStringLiteral( "0" ) );
QCOMPARE( cp1.attribute( QStringLiteral( "y" ) ), QStringLiteral( "-2.83465" ) );
QCOMPARE( cp1.attribute( QStringLiteral( "y" ) ).left( 10 ), QStringLiteral( "-2.8346456" ) );
}

void TestQgsGeoPdfExport::testGroups()

0 comments on commit 0b77f18

Please sign in to comment.
You can’t perform that action at this time.