Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #4488 from nirvn/saveasimage_fix_rotated
  • Loading branch information
nirvn committed May 3, 2017
2 parents a2327d3 + 747c2e2 commit dc7198a
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 22 deletions.
8 changes: 0 additions & 8 deletions src/app/qgisapp.cpp
Expand Up @@ -5804,14 +5804,6 @@ void QgisApp::saveMapAsImage()
QPair< QString, QString> myFileNameAndFilter = QgisGui::getSaveAsImageName( this, tr( "Choose a file name to save the map image as" ) );
if ( myFileNameAndFilter.first != QLatin1String( "" ) )
{
QSize size = mMapCanvas->size();
if ( dlg.extent() != mMapCanvas->extent() )
{
size.setWidth( mMapCanvas->size().width() * dlg.extent().width() / mMapCanvas->extent().width() );
size.setHeight( mMapCanvas->size().height() * dlg.extent().height() / mMapCanvas->extent().height() );
}
size *= dlg.dpi() / qt_defaultDpiX();

QgsMapSettings ms = QgsMapSettings();
ms.setDestinationCrs( QgsProject::instance()->crs() );
ms.setExtent( dlg.extent() );
Expand Down
16 changes: 10 additions & 6 deletions src/app/qgsmapsavedialog.cpp
Expand Up @@ -31,19 +31,23 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();

QgsMapSaveDialog::QgsMapSaveDialog( QWidget *parent, QgsMapCanvas *mapCanvas, const QString &activeDecorations )
: QDialog( parent )
, mExtent( mapCanvas->mapSettings().visibleExtent() )
, mDpi( mapCanvas->mapSettings().outputDpi() )
, mSize( mapCanvas->mapSettings().outputSize() )
{
setupUi( this );

// Use unrotated visible extent to insure output size and scale matches canvas
QgsMapSettings ms = mapCanvas->mapSettings();
ms.setRotation( 0 );
mExtent = ms.visibleExtent();
mDpi = ms.outputDpi();
mSize = ms.outputSize();

mResolutionSpinBox->setValue( qt_defaultDpiX() );

mExtentGroupBox->setOutputCrs( mapCanvas->mapSettings().destinationCrs() );
mExtentGroupBox->setCurrentExtent( mExtent, mapCanvas->mapSettings().destinationCrs() );
mExtentGroupBox->setOutputCrs( ms.destinationCrs() );
mExtentGroupBox->setCurrentExtent( mExtent, ms.destinationCrs() );
mExtentGroupBox->setOutputExtentFromCurrent();

mScaleWidget->setScale( 1 / mapCanvas->mapSettings().scale() );
mScaleWidget->setScale( 1 / ms.scale() );
mScaleWidget->setMapCanvas( mapCanvas );
mScaleWidget->setShowCurrentScaleButton( true );

Expand Down
53 changes: 45 additions & 8 deletions src/core/qgsmapsettingsutils.cpp
Expand Up @@ -22,23 +22,60 @@

QString QgsMapSettingsUtils::worldFileContent( const QgsMapSettings &mapSettings )
{
double xOrigin = mapSettings.visiblePolygon().at( 0 ).x() + ( mapSettings.mapUnitsPerPixel() / 2 );
double yOrigin = mapSettings.visiblePolygon().at( 0 ).y() - ( mapSettings.mapUnitsPerPixel() / 2 );
QgsMapSettings ms = mapSettings;

double rotation = ms.rotation();
double alpha = rotation / 180 * M_PI;

// reset rotation to 0 to calculate world file parameters
ms.setRotation( 0 );

double xOrigin = ms.visibleExtent().xMinimum() + ( ms.mapUnitsPerPixel() / 2 );
double yOrigin = ms.visibleExtent().yMaximum() - ( ms.mapUnitsPerPixel() / 2 );

double xCenter = ms.visibleExtent().center().x();
double yCenter = ms.visibleExtent().center().y();

// scaling matrix
double s[6];
s[0] = ms.mapUnitsPerPixel();
s[1] = 0;
s[2] = xOrigin;
s[3] = 0;
s[4] = ms.mapUnitsPerPixel();
s[5] = yOrigin;

// rotation matrix
double r[6];
r[0] = cos( alpha );
r[1] = -sin( alpha );
r[2] = xCenter * ( 1 - cos( alpha ) ) + yCenter * sin( alpha );
r[3] = sin( alpha );
r[4] = cos( alpha );
r[5] = - xCenter * sin( alpha ) + yCenter * ( 1 - cos( alpha ) );

// result = rotation x scaling = rotation(scaling(X))
double a = r[0] * s[0] + r[1] * s[3];
double b = r[0] * s[1] + r[1] * s[4];
double c = r[0] * s[2] + r[1] * s[5] + r[2];
double d = r[3] * s[0] + r[4] * s[3];
double e = r[3] * s[1] + r[4] * s[4];
double f = r[3] * s[2] + r[4] * s[5] + r[5];

QString content;
// Pixel XDim
content += qgsDoubleToString( mapSettings.mapUnitsPerPixel() ) + "\r\n";
content += qgsDoubleToString( a ) + "\r\n";
// Rotation on y axis
content += QString( "%1\r\n" ).arg( mapSettings.rotation() );
content += qgsDoubleToString( d ) + "\r\n";
// Rotation on x axis
content += QString( "%1\r\n" ).arg( mapSettings.rotation() );
content += qgsDoubleToString( -b ) + "\r\n";
// Pixel YDim - almost always negative
// See https://en.wikipedia.org/wiki/World_file#cite_ref-3
content += '-' + qgsDoubleToString( mapSettings.mapUnitsPerPixel() ) + "\r\n";
content += "-" + qgsDoubleToString( e ) + "\r\n";
// Origin X (center of top left cell)
content += qgsDoubleToString( xOrigin ) + "\r\n";
content += qgsDoubleToString( c ) + "\r\n";
// Origin Y (center of top left cell)
content += qgsDoubleToString( yOrigin ) + "\r\n";
content += qgsDoubleToString( f ) + "\r\n";

return content;
}
4 changes: 4 additions & 0 deletions tests/src/core/testqgsmapsettingsutils.cpp
Expand Up @@ -43,11 +43,15 @@ class TestQgsMapSettingsUtils : public QObject
void TestQgsMapSettingsUtils::initTestCase()
{
mMapSettings.setExtent( QgsRectangle( 0, 0, 1, 1 ) );
mMapSettings.setOutputSize( QSize( 1, 1 ) );
}

void TestQgsMapSettingsUtils::createWorldFileContent()
{
QCOMPARE( QgsMapSettingsUtils::worldFileContent( mMapSettings ), QString( "1\r\n0\r\n0\r\n-1\r\n0.5\r\n0.5\r\n" ) );

mMapSettings.setRotation( 45 );
QCOMPARE( QgsMapSettingsUtils::worldFileContent( mMapSettings ), QString( "0.70710678118654757\r\n0.70710678118654746\r\n0.70710678118654746\r\n-0.70710678118654757\r\n0.5\r\n0.49999999999999994\r\n" ) );
}

QGSTEST_MAIN( TestQgsMapSettingsUtils )
Expand Down

0 comments on commit dc7198a

Please sign in to comment.