void QgsAtlasComposition::prepareMap( QgsComposerMap* map ) { if ( !map->atlasDriven() || mCoverageLayer->wkbType() == QgsWkbTypes::NoGeometry ) { return; } if ( mTransformedFeatureBounds.isEmpty() ) { //transformed extent of current feature hasn't been calculated yet. This can happen if //a map has been set to be atlas controlled after prepare feature was called computeExtent( map ); } double xa1 = mTransformedFeatureBounds.xMinimum(); double xa2 = mTransformedFeatureBounds.xMaximum(); double ya1 = mTransformedFeatureBounds.yMinimum(); double ya2 = mTransformedFeatureBounds.yMaximum(); QgsRectangle newExtent = mTransformedFeatureBounds; QgsRectangle mOrigExtent( map->extent() ); //sanity check - only allow fixed scale mode for point layers bool isPointLayer = false; switch ( mCoverageLayer->wkbType() ) { case QgsWkbTypes::Point: case QgsWkbTypes::Point25D: case QgsWkbTypes::MultiPoint: case QgsWkbTypes::MultiPoint25D: isPointLayer = true; break; default: isPointLayer = false; break; } if ( map->atlasScalingMode() == QgsComposerMap::Fixed || map->atlasScalingMode() == QgsComposerMap::Predefined || isPointLayer ) { QgsScaleCalculator calc; calc.setMapUnits( composition()->mapSettings().mapUnits() ); calc.setDpi( 25.4 ); double originalScale = calc.calculate( mOrigExtent, map->rect().width() ); double geomCenterX = ( xa1 + xa2 ) / 2.0; double geomCenterY = ( ya1 + ya2 ) / 2.0; if ( map->atlasScalingMode() == QgsComposerMap::Fixed || isPointLayer ) { // 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<qreal>& scales = mPredefinedScales; for ( int i = 0; i < scales.size(); i++ ) { 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; } } } } else if ( map->atlasScalingMode() == QgsComposerMap::Auto ) { // auto scale double geomRatio = mTransformedFeatureBounds.width() / mTransformedFeatureBounds.height(); double mapRatio = mOrigExtent.width() / mOrigExtent.height(); // geometry height is too big if ( geomRatio < mapRatio ) { // extent the bbox's width double adjWidth = ( mapRatio * mTransformedFeatureBounds.height() - mTransformedFeatureBounds.width() ) / 2.0; xa1 -= adjWidth; xa2 += adjWidth; } // geometry width is too big else if ( geomRatio > mapRatio ) { // extent the bbox's height double adjHeight = ( mTransformedFeatureBounds.width() / mapRatio - mTransformedFeatureBounds.height() ) / 2.0; ya1 -= adjHeight; ya2 += adjHeight; } newExtent = QgsRectangle( xa1, ya1, xa2, ya2 ); if ( map->atlasMargin() > 0.0 ) { newExtent.scale( 1 + map->atlasMargin() ); } } // set the new extent (and render) map->setNewAtlasFeatureExtent( newExtent ); }
void QgsAtlasComposition::prepareMap( QgsComposerMap* map ) { if ( !map->atlasDriven() ) { return; } if ( mTransformedFeatureBounds.isEmpty() ) { //transformed extent of current feature hasn't been calculated yet. This can happen if //a map has been set to be atlas controlled after prepare feature was called computeExtent( map ); } double xa1 = mTransformedFeatureBounds.xMinimum(); double xa2 = mTransformedFeatureBounds.xMaximum(); double ya1 = mTransformedFeatureBounds.yMinimum(); double ya2 = mTransformedFeatureBounds.yMaximum(); QgsRectangle new_extent = mTransformedFeatureBounds; QgsRectangle mOrigExtent = map->extent(); if ( map->atlasScalingMode() == QgsComposerMap::Fixed ) { // 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 n_width = extent.width(), n_height = extent.height(); const QVector<double>& scales = mPredefinedScales; for ( int i = 0; i < scales.size(); i++ ) { 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()) ) { // 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(); // geometry height is too big if ( geom_ratio < map_ratio ) { // extent the bbox's width double adj_width = ( map_ratio * mTransformedFeatureBounds.height() - mTransformedFeatureBounds.width() ) / 2.0; xa1 -= adj_width; xa2 += adj_width; } // geometry width is too big else if ( geom_ratio > map_ratio ) { // extent the bbox's height double adj_height = ( mTransformedFeatureBounds.width() / map_ratio - mTransformedFeatureBounds.height() ) / 2.0; ya1 -= adj_height; ya2 += adj_height; } new_extent = QgsRectangle( xa1, ya1, xa2, ya2 ); if ( map->atlasMargin() > 0.0 ) { new_extent.scale( 1 + map->atlasMargin() ); } } // set the new extent (and render) map->setNewAtlasFeatureExtent( new_extent ); }