Skip to content

Commit

Permalink
When reprojecting a layer in geo coordinates onto a canvas with a
Browse files Browse the repository at this point in the history
projection that maps badly on it (ie. projecting the reprojected extent
back differs much from the input extent; eg. when using stereographic
projections), render the full layer (whole world).

Fixes #7596
  • Loading branch information
jef-n committed Oct 29, 2015
1 parent 08185c9 commit 51fe632
Showing 1 changed file with 50 additions and 17 deletions.
67 changes: 50 additions & 17 deletions src/core/qgsmaprendererjob.cpp
Expand Up @@ -81,26 +81,59 @@ bool QgsMapRendererJob::reprojectToLayerExtent( const QgsCoordinateTransform* ct

if ( layerCrsGeographic )
{
// Note: ll = lower left point
// and ur = upper right point
QgsPoint ll = ct->transform( extent.xMinimum(), extent.yMinimum(),
QgsCoordinateTransform::ReverseTransform );
if ( !ct->destCRS().geographicFlag() )
{
// if we transform from a projected coordinate system check
// check if transforming back roughly returns the input
// extend - otherwise render the world.
QgsRectangle extent1 = ct->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
QgsRectangle extent2 = ct->transformBoundingBox( extent1, QgsCoordinateTransform::ForwardTransform );

QgsDebugMsg( QString( "\n0:%1 %2x%3\n1:%4\n2:%5 %6x%7 (w:%8 h:%9)" )
.arg( extent.toString() ).arg( extent.width() ).arg( extent.height() )
.arg( extent1.toString() )
.arg( extent2.toString() ).arg( extent2.width() ).arg( extent2.height() )
.arg( fabs( 1.0 - extent2.width() / extent.width() ) )
.arg( fabs( 1.0 - extent2.height() / extent.height() ) )
);

if ( fabs( 1.0 - extent2.width() / extent.width() ) < 0.5 &&
fabs( 1.0 - extent2.height() / extent.height() ) < 0.5 )
{
extent = extent1;
}
else
{
extent = QgsRectangle( -180.0, -90.0, 180.0, 90.0 );
}
}
else
{
// Note: ll = lower left point
QgsPoint ll = ct->transform( extent.xMinimum(), extent.yMinimum(),
QgsCoordinateTransform::ReverseTransform );

QgsPoint ur = ct->transform( extent.xMaximum(), extent.yMaximum(),
QgsCoordinateTransform::ReverseTransform );
// and ur = upper right point
QgsPoint ur = ct->transform( extent.xMaximum(), extent.yMaximum(),
QgsCoordinateTransform::ReverseTransform );

extent = ct->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
QgsDebugMsg( QString( "in:%1 (ll:%2 ur:%3)" ).arg( extent.toString() ).arg( ll.toString() ).arg( ur.toString() ) );

if ( ll.x() > ur.x() )
{
// the coordinates projected in reverse order than what one would expect.
// we are probably looking at an area that includes longitude of 180 degrees.
// we need to take into account coordinates from two intervals: (-180,x1) and (x2,180)
// so let's use (-180,180). This hopefully does not add too much overhead. It is
// more straightforward than rendering with two separate extents and more consistent
// for rendering, labeling and caching as everything is rendered just in one go
extent.setXMinimum( -splitCoord );
extent.setXMaximum( splitCoord );
extent = ct->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );

QgsDebugMsg( QString( "out:%1 (w:%2 h:%3)" ).arg( extent.toString() ).arg( extent.width() ).arg( extent.height() ) );

if ( ll.x() > ur.x() )
{
// the coordinates projected in reverse order than what one would expect.
// we are probably looking at an area that includes longitude of 180 degrees.
// we need to take into account coordinates from two intervals: (-180,x1) and (x2,180)
// so let's use (-180,180). This hopefully does not add too much overhead. It is
// more straightforward than rendering with two separate extents and more consistent
// for rendering, labeling and caching as everything is rendered just in one go
extent.setXMinimum( -splitCoord );
extent.setXMaximum( splitCoord );
}
}

// TODO: the above rule still does not help if using a projection that covers the whole
Expand Down

1 comment on commit 51fe632

@blazek
Copy link
Member

@blazek blazek commented on 51fe632 Nov 12, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.