Permalink
Browse files

Add world file generation option. Work funded by Tuscany Region - SI…

…TA. Contract Support to the use of GFOSS \(Geographic Free and Open Source Software\) Desktop tools \(CIG Z3B06FA6D7\)
  • Loading branch information...
mhugo authored and mhugent committed Jun 12, 2013
1 parent f66f9aa commit 387c88de24a3363f8c29be4706a4fb1f84473f73
@@ -995,6 +995,22 @@ void QgsComposer::on_mActionExportAsImage_triggered()
image.save( outputFilePath, fileNExt.second.toLocal8Bit().constData() );
}
}
//
// Write the world file if asked to
if ( mComposition->generateWorldFile() )
{
double params[6];
mComposition->computeWorldFileParameters( params );
QFileInfo fi( fileNExt.first );
// build the world file name
QString worldFileName = fi.absolutePath() + "/" + fi.baseName() + "."
+ fi.suffix()[0] + fi.suffix()[fi.suffix().size()-1] + "w";
writeWorldFile( worldFileName, params );
}
mView->setPaintingEnabled( true );
}
else
@@ -1137,6 +1153,21 @@ void QgsComposer::on_mActionExportAsImage_triggered()
image.save( outputFilePath, format.toLocal8Bit().constData() );
}
}
//
// Write the world file if asked to
if ( mComposition->generateWorldFile() )
{
double params[6];
mComposition->computeWorldFileParameters( params );
QFileInfo fi( filename );
// build the world file name
QString worldFileName = fi.absolutePath() + "/" + fi.baseName() + "."
+ fi.suffix()[0] + fi.suffix()[fi.suffix().size()-1] + "w";
writeWorldFile( worldFileName, params );
}
}
atlasMap->endRender();
mView->setPaintingEnabled( true );
@@ -1881,6 +1912,24 @@ void QgsComposer::readXML( const QDomElement& composerElem, const QDomDocument&
mComposition->addItemsFromXML( composerElem, doc, &mMapsToRestore );
}
// look for world file composer map, if needed
// Note: this must be done after maps have been added by addItemsFromXML
if ( mComposition->generateWorldFile() )
{
QDomElement compositionElem = compositionNodeList.at( 0 ).toElement();
QgsComposerMap* worldFileMap = 0;
QList<const QgsComposerMap*> maps = mComposition->composerMapItems();
for ( QList<const QgsComposerMap*>::const_iterator it = maps.begin(); it != maps.end(); ++it )
{
if (( *it )->id() == compositionElem.attribute( "worldFileMap" ).toInt() )
{
worldFileMap = const_cast<QgsComposerMap*>( *it );
break;
}
}
mComposition->setWorldFileMap( worldFileMap );
}
mComposition->sortZList();
mView->setComposition( mComposition );
@@ -2304,3 +2353,22 @@ void QgsComposer::createComposerView()
mView->setVerticalRuler( mVerticalRuler );
mViewLayout->addWidget( mView, 1, 1 );
}
void QgsComposer::writeWorldFile( QString worldFileName, double p[6] ) const
{
QFile worldFile( worldFileName );
if ( !worldFile.open( QIODevice::WriteOnly | QIODevice::Text ) )
{
return;
}
QTextStream fout( &worldFile );
// QString::number does not use locale settings (for the decimal point)
// which is what we want here
fout << QString::number( p[0] ) << "\r\n";
fout << QString::number( p[3] ) << "\r\n";
fout << QString::number( p[1] ) << "\r\n";
fout << QString::number( p[4] ) << "\r\n";
fout << QString::number( p[2] ) << "\r\n";
fout << QString::number( p[5] ) << "\r\n";
}
@@ -334,6 +334,9 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase
//! Create composer view and rulers
void createComposerView();
//! Write a world file
void writeWorldFile( QString fileName, double params[6] ) const;
/**Composer title*/
QString mTitle;
@@ -17,6 +17,8 @@
#include <qgis.h>
#include "qgscompositionwidget.h"
#include "qgscomposition.h"
#include "qgscomposermap.h"
#include "qgscomposeritem.h"
#include <QColorDialog>
#include <QWidget>
#include <QPrinter> //for screen resolution
@@ -49,6 +51,29 @@ QgsCompositionWidget::QgsCompositionWidget( QWidget* parent, QgsComposition* c )
//print as raster
mPrintAsRasterCheckBox->setChecked( mComposition->printAsRaster() );
// world file generation
mGenerateWorldFileCheckBox->setChecked( mComposition->generateWorldFile() );
// populate the map list
mWorldFileMapComboBox->clear();
QList<const QgsComposerMap*> availableMaps = mComposition->composerMapItems();
QList<const QgsComposerMap*>::const_iterator mapItemIt = availableMaps.constBegin();
for ( ; mapItemIt != availableMaps.constEnd(); ++mapItemIt )
{
mWorldFileMapComboBox->addItem( tr( "Map %1" ).arg(( *mapItemIt )->id() ), qVariantFromValue(( void* )*mapItemIt ) );
}
int idx = mWorldFileMapComboBox->findData( qVariantFromValue(( void* )mComposition->worldFileMap() ) );
if ( idx != -1 )
{
mWorldFileMapComboBox->setCurrentIndex( idx );
}
// Connect to addition / removal of maps
connect( mComposition, SIGNAL( composerMapAdded( QgsComposerMap* ) ), this, SLOT( onComposerMapAdded( QgsComposerMap* ) ) );
connect( mComposition, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SLOT( onItemRemoved( QgsComposerItem* ) ) );
mAlignmentSnapGroupCheckBox->setChecked( mComposition->alignmentSnap() );
mAlignmentToleranceSpinBox->setValue( mComposition->alignmentSnapTolerance() );
@@ -412,6 +437,70 @@ void QgsCompositionWidget::on_mPrintAsRasterCheckBox_toggled( bool state )
mComposition->setPrintAsRaster( state );
}
void QgsCompositionWidget::on_mGenerateWorldFileCheckBox_toggled( bool state )
{
if ( !mComposition )
{
return;
}
mComposition->setGenerateWorldFile( state );
mWorldFileMapComboBox->setEnabled( state );
}
void QgsCompositionWidget::onComposerMapAdded( QgsComposerMap* map )
{
if ( !mComposition )
{
return;
}
mWorldFileMapComboBox->addItem( tr( "Map %1" ).arg( map->id() ), qVariantFromValue(( void* )map ) );
if ( mWorldFileMapComboBox->count() == 1 )
{
mComposition->setWorldFileMap( map );
}
}
void QgsCompositionWidget::onItemRemoved( QgsComposerItem* item )
{
if ( !mComposition )
{
return;
}
QgsComposerMap* map = dynamic_cast<QgsComposerMap*>( item );
if ( map )
{
int idx = mWorldFileMapComboBox->findData( qVariantFromValue(( void* )map ) );
if ( idx != -1 )
{
mWorldFileMapComboBox->removeItem( idx );
}
}
if ( mWorldFileMapComboBox->count() == 0 )
{
mComposition->setWorldFileMap( 0 );
}
}
void QgsCompositionWidget::on_mWorldFileMapComboBox_currentIndexChanged( int index )
{
if ( !mComposition )
{
return;
}
if ( index == -1 )
{
mComposition->setWorldFileMap( 0 );
}
else
{
QgsComposerMap* map = reinterpret_cast<QgsComposerMap*>( mWorldFileMapComboBox->itemData( index ).value<void*>() );
mComposition->setWorldFileMap( map );
}
}
void QgsCompositionWidget::on_mSnapToGridGroupCheckBox_toggled( bool state )
{
if ( mComposition )
@@ -17,6 +17,8 @@
#include "ui_qgscompositionwidgetbase.h"
class QgsComposition;
class QgsComposerMap;
class QgsComposerItem;
/** \ingroup MapComposer
* Struct to hold map composer paper properties.
@@ -48,6 +50,8 @@ class QgsCompositionWidget: public QWidget, private Ui::QgsCompositionWidgetBase
void on_mNumPagesSpinBox_valueChanged( int value );
void on_mResolutionSpinBox_valueChanged( const int value );
void on_mPrintAsRasterCheckBox_toggled( bool state );
void on_mGenerateWorldFileCheckBox_toggled( bool state );
void on_mWorldFileMapComboBox_currentIndexChanged( int index );
void on_mSnapToGridGroupCheckBox_toggled( bool state );
void on_mGridResolutionSpinBox_valueChanged( double d );
@@ -65,6 +69,12 @@ class QgsCompositionWidget: public QWidget, private Ui::QgsCompositionWidgetBase
/**Sets Print as raster checkbox value*/
void setPrintAsRasterCheckBox( bool state );
private slots:
/* when a new map is added */
void onComposerMapAdded( QgsComposerMap* );
/* when a map is deleted */
void onItemRemoved( QgsComposerItem* );
private:
QgsComposition* mComposition;
QMap<QString, QgsCompositionPaper> mPaperMap;
@@ -54,6 +54,8 @@ QgsComposition::QgsComposition( QgsMapRenderer* mapRenderer )
, mPageHeight( 210 )
, mSpaceBetweenPages( 10 )
, mPrintAsRaster( false )
, mGenerateWorldFile( false )
, mWorldFileMap( 0 )
, mUseAdvancedEffects( true )
, mSelectionTolerance( 0.0 )
, mSnapToGrid( false )
@@ -81,6 +83,8 @@ QgsComposition::QgsComposition()
mPageHeight( 210 ),
mSpaceBetweenPages( 10 ),
mPrintAsRaster( false ),
mGenerateWorldFile( false ),
mWorldFileMap( 0 ),
mUseAdvancedEffects( true ),
mSelectionTolerance( 0.0 ),
mSnapToGrid( false ),
@@ -420,6 +424,12 @@ bool QgsComposition::writeXML( QDomElement& composerElem, QDomDocument& doc )
compositionElem.setAttribute( "printResolution", mPrintResolution );
compositionElem.setAttribute( "printAsRaster", mPrintAsRaster );
compositionElem.setAttribute( "generateWorldFile", mGenerateWorldFile ? 1 : 0 );
if ( mGenerateWorldFile && mWorldFileMap )
{
compositionElem.setAttribute( "worldFileMap", mWorldFileMap->id() );
}
compositionElem.setAttribute( "alignmentSnap", mAlignmentSnap ? 1 : 0 );
compositionElem.setAttribute( "alignmentSnapTolerance", mAlignmentSnapTolerance );
@@ -505,6 +515,8 @@ bool QgsComposition::readXML( const QDomElement& compositionElem, const QDomDocu
mPrintAsRaster = compositionElem.attribute( "printAsRaster" ).toInt();
mPrintResolution = compositionElem.attribute( "printResolution", "300" ).toInt();
mGenerateWorldFile = compositionElem.attribute( "generateWorldFile", "0" ).toInt() == 1 ? true : false;
updatePaperItems();
return true;
@@ -2174,3 +2186,64 @@ bool QgsComposition::nearestItem( const QMap< double, const QgsComposerItem* >&
}
}
void QgsComposition::computeWorldFileParameters( double p[6] ) const
{
//
// Word file parameters : affine transformation parameters from pixel coordinates to map coordinates
if ( !mWorldFileMap )
{
return;
}
QRectF brect = mWorldFileMap->boundingRect();
QgsRectangle extent = mWorldFileMap->extent();
double alpha = mWorldFileMap->rotation() / 180 * M_PI;
double xr = extent.width() / brect.width();
double yr = extent.height() / brect.height();
double XC = extent.center().x();
double YC = extent.center().y();
// get the extent for the page
double xmin = extent.xMinimum() - mWorldFileMap->transform().dx() * xr;
double ymax = extent.yMaximum() + mWorldFileMap->transform().dy() * yr;
QgsRectangle paperExtent( xmin, ymax - paperHeight() * yr, xmin + paperWidth() * xr, ymax );
double X0 = paperExtent.xMinimum();
double Y0 = paperExtent.yMinimum();
int widthPx = ( int )( printResolution() * paperWidth() / 25.4 );
int heightPx = ( int )( printResolution() * paperHeight() / 25.4 );
double Ww = paperExtent.width() / widthPx;
double Hh = paperExtent.height() / heightPx;
// scaling matrix
double s[6];
s[0] = Ww;
s[1] = 0;
s[2] = X0;
s[3] = 0;
s[4] = -Hh;
s[5] = Y0 + paperExtent.height();
// rotation matrix
double r[6];
r[0] = cos( alpha );
r[1] = -sin( alpha );
r[2] = XC * ( 1 - cos( alpha ) ) + YC * sin( alpha );
r[3] = sin( alpha );
r[4] = cos( alpha );
r[5] = - XC * sin( alpha ) + YC * ( 1 - cos( alpha ) );
// result = rotation x scaling = rotation(scaling(X))
p[0] = r[0] * s[0] + r[1] * s[3];
p[1] = r[0] * s[1] + r[1] * s[4];
p[2] = r[0] * s[2] + r[1] * s[5] + r[2];
p[3] = r[3] * s[0] + r[4] * s[3];
p[4] = r[3] * s[1] + r[4] * s[4];
p[5] = r[3] * s[2] + r[4] * s[5] + r[5];
}
@@ -182,6 +182,12 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
bool printAsRaster() const {return mPrintAsRaster;}
void setPrintAsRaster( bool enabled ) { mPrintAsRaster = enabled; }
bool generateWorldFile() const { return mGenerateWorldFile; }
void setGenerateWorldFile( bool enabled ) { mGenerateWorldFile = enabled; }
QgsComposerMap* worldFileMap() const { return mWorldFileMap; }
void setWorldFileMap( QgsComposerMap* map ) { mWorldFileMap = map; }
/**Returns true if a composition should use advanced effects such as blend modes
@note added in 1.9*/
bool useAdvancedEffects() const {return mUseAdvancedEffects;}
@@ -357,6 +363,9 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
@note added in version 1.9*/
void renderPage( QPainter* p, int page );
/** Compute world file parameters */
void computeWorldFileParameters( double p[6] ) const;
QgsAtlasComposition& atlasComposition() { return mAtlasComposition; }
public slots:
@@ -384,6 +393,11 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
/**Flag if map should be printed as a raster (via QImage). False by default*/
bool mPrintAsRaster;
/**Flag if a world file should be generated on raster export */
bool mGenerateWorldFile;
/** Composer map to use for the world file generation */
QgsComposerMap* mWorldFileMap;
/**Flag if advanced visual effects such as blend modes should be used. True by default*/
bool mUseAdvancedEffects;
Oops, something went wrong.

0 comments on commit 387c88d

Please sign in to comment.