Skip to content

Commit

Permalink
[composer] Make atlas fixed and predefined scales options work correc…
Browse files Browse the repository at this point in the history
…tly with geographic coordinate systems (fix #9839)
  • Loading branch information
nyalldawson committed Jun 11, 2014
1 parent 8f5fe10 commit ae875a0
Showing 1 changed file with 61 additions and 50 deletions.
111 changes: 61 additions & 50 deletions src/core/composer/qgsatlascomposition.cpp
Expand Up @@ -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
Expand All @@ -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
Expand Down

0 comments on commit ae875a0

Please sign in to comment.