[composer] Make atlas fixed and predefined scales options work correctly with geographic coordinate systems (fix #9839)

This commit is contained in:
Nyall Dawson 2014-06-11 22:29:59 +10:00
parent 8f5fe10fa0
commit ae875a0e87

View File

@ -444,7 +444,7 @@ void QgsAtlasComposition::prepareMap( QgsComposerMap* map )
double xa2 = mTransformedFeatureBounds.xMaximum();
double ya1 = mTransformedFeatureBounds.yMinimum();
double ya2 = mTransformedFeatureBounds.yMaximum();
QgsRectangle new_extent = mTransformedFeatureBounds;
QgsRectangle newExtent = mTransformedFeatureBounds;
QgsRectangle mOrigExtent = map->extent();
//sanity check - only allow fixed scale mode for point layers
@ -462,85 +462,96 @@ void QgsAtlasComposition::prepareMap( QgsComposerMap* map )
break;
}
if ( map->atlasScalingMode() == QgsComposerMap::Fixed || isPointLayer )
if ( map->atlasScalingMode() == QgsComposerMap::Fixed || map->atlasScalingMode() == QgsComposerMap::Predefined || isPointLayer )
{
// only translate, keep the original scale (i.e. width x height)
double geom_center_x = ( xa1 + xa2 ) / 2.0;
double geom_center_y = ( ya1 + ya2 ) / 2.0;
double xx = geom_center_x - mOrigExtent.width() / 2.0;
double yy = geom_center_y - mOrigExtent.height() / 2.0;
new_extent = QgsRectangle( xx,
yy,
xx + mOrigExtent.width(),
yy + mOrigExtent.height() );
}
else if ( map->atlasScalingMode() == QgsComposerMap::Predefined )
{
// choose one of the predefined scales
QgsScaleCalculator calc;
calc.setMapUnits( composition()->mapSettings().mapUnits() );
calc.setDpi( 25.4 );
double scale = calc.calculate( map->extent(), map->rect().width() );
QgsRectangle extent = map->extent();
double originalScale = calc.calculate( mOrigExtent, map->rect().width() );
double geomCenterX = ( xa1 + xa2 ) / 2.0;
double geomCenterY = ( ya1 + ya2 ) / 2.0;
double n_width = extent.width(), n_height = extent.height();
const QVector<double>& scales = mPredefinedScales;
for ( int i = 0; i < scales.size(); i++ )
if ( map->atlasScalingMode() == QgsComposerMap::Fixed || isPointLayer )
{
double ratio = scales[i] / scale;
n_width = extent.width() * ratio;
n_height = extent.height() * ratio;
if (( n_width >= new_extent.width() ) && ( n_height >= new_extent.height() ) )
// only translate, keep the original scale (i.e. width x height)
double xMin = geomCenterX - mOrigExtent.width() / 2.0;
double yMin = geomCenterY - mOrigExtent.height() / 2.0;
newExtent = QgsRectangle( xMin,
yMin,
xMin + mOrigExtent.width(),
yMin + mOrigExtent.height() );
//scale newExtent to match original scale of map
//this is required for geographic coordinate systems, where the scale varies by extent
double newScale = calc.calculate( newExtent, map->rect().width() );
newExtent.scale( originalScale / newScale );
}
else if ( map->atlasScalingMode() == QgsComposerMap::Predefined )
{
// choose one of the predefined scales
double newWidth = mOrigExtent.width();
double newHeight = mOrigExtent.height();
const QVector<double>& scales = mPredefinedScales;
for ( int i = 0; i < scales.size(); i++ )
{
// this is the smallest extent that embeds the feature, stop here
break;
double ratio = scales[i] / originalScale;
newWidth = mOrigExtent.width() * ratio;
newHeight = mOrigExtent.height() * ratio;
// compute new extent, centered on feature
double xMin = geomCenterX - newWidth / 2.0;
double yMin = geomCenterY - newHeight / 2.0;
newExtent = QgsRectangle( xMin,
yMin,
xMin + newWidth,
yMin + newHeight );
//scale newExtent to match desired map scale
//this is required for geographic coordinate systems, where the scale varies by extent
double newScale = calc.calculate( newExtent, map->rect().width() );
newExtent.scale( scales[i] / newScale );
if (( newExtent.width() >= mTransformedFeatureBounds.width() ) && ( newExtent.height() >= mTransformedFeatureBounds.height() ) )
{
// this is the smallest extent that embeds the feature, stop here
break;
}
}
}
// compute new extent, centered on feature
double geom_center_x = ( xa1 + xa2 ) / 2.0;
double geom_center_y = ( ya1 + ya2 ) / 2.0;
double xx = geom_center_x - n_width / 2.0;
double yy = geom_center_y - n_height / 2.0;
new_extent = QgsRectangle( xx,
yy,
xx + n_width,
yy + n_height );
}
else if ( map->atlasScalingMode() == QgsComposerMap::Auto )
{
// auto scale
double geom_ratio = mTransformedFeatureBounds.width() / mTransformedFeatureBounds.height();
double map_ratio = mOrigExtent.width() / mOrigExtent.height();
double geomRatio = mTransformedFeatureBounds.width() / mTransformedFeatureBounds.height();
double mapRatio = mOrigExtent.width() / mOrigExtent.height();
// geometry height is too big
if ( geom_ratio < map_ratio )
if ( geomRatio < mapRatio )
{
// extent the bbox's width
double adj_width = ( map_ratio * mTransformedFeatureBounds.height() - mTransformedFeatureBounds.width() ) / 2.0;
xa1 -= adj_width;
xa2 += adj_width;
double adjWidth = ( mapRatio * mTransformedFeatureBounds.height() - mTransformedFeatureBounds.width() ) / 2.0;
xa1 -= adjWidth;
xa2 += adjWidth;
}
// geometry width is too big
else if ( geom_ratio > map_ratio )
else if ( geomRatio > mapRatio )
{
// extent the bbox's height
double adj_height = ( mTransformedFeatureBounds.width() / map_ratio - mTransformedFeatureBounds.height() ) / 2.0;
ya1 -= adj_height;
ya2 += adj_height;
double adjHeight = ( mTransformedFeatureBounds.width() / mapRatio - mTransformedFeatureBounds.height() ) / 2.0;
ya1 -= adjHeight;
ya2 += adjHeight;
}
new_extent = QgsRectangle( xa1, ya1, xa2, ya2 );
newExtent = QgsRectangle( xa1, ya1, xa2, ya2 );
if ( map->atlasMargin() > 0.0 )
{
new_extent.scale( 1 + map->atlasMargin() );
newExtent.scale( 1 + map->atlasMargin() );
}
}
// set the new extent (and render)
map->setNewAtlasFeatureExtent( new_extent );
map->setNewAtlasFeatureExtent( newExtent );
}
const QString& QgsAtlasComposition::currentFilename() const