1 /***************************************************************************
2                               qgsgridfilewriter.cpp
3                               ---------------------
4   begin                : Marco 10, 2008
5   copyright            : (C) 2008 by Marco Hugentobler
6   email                : marco dot hugentobler at karto dot baug dot ethz dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "qgsgridfilewriter.h"
19 #include "qgsinterpolator.h"
20 #include "qgsvectorlayer.h"
21 #include "qgsfeedback.h"
22 #include <QFile>
23 #include <QFileInfo>
24 
QgsGridFileWriter(QgsInterpolator * i,const QString & outputPath,const QgsRectangle & extent,int nCols,int nRows)25 QgsGridFileWriter::QgsGridFileWriter( QgsInterpolator *i, const QString &outputPath, const QgsRectangle &extent, int nCols, int nRows )
26   : mInterpolator( i )
27   , mOutputFilePath( outputPath )
28   , mInterpolationExtent( extent )
29   , mNumColumns( nCols )
30   , mNumRows( nRows )
31   , mCellSizeX( extent.width() / nCols )
32   , mCellSizeY( extent.height() / nRows )
33 {}
34 
writeFile(QgsFeedback * feedback)35 int QgsGridFileWriter::writeFile( QgsFeedback *feedback )
36 {
37   QFile outputFile( mOutputFilePath );
38 
39   if ( !outputFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
40   {
41     return 1;
42   }
43 
44   if ( !mInterpolator )
45   {
46     outputFile.remove();
47     return 2;
48   }
49 
50   QTextStream outStream( &outputFile );
51   outStream.setRealNumberPrecision( 8 );
52   writeHeader( outStream );
53 
54   double currentYValue = mInterpolationExtent.yMaximum() - mCellSizeY / 2.0; //calculate value in the center of the cell
55   double currentXValue;
56   double interpolatedValue;
57 
58   for ( int i = 0; i < mNumRows; ++i )
59   {
60     currentXValue = mInterpolationExtent.xMinimum() + mCellSizeX / 2.0; //calculate value in the center of the cell
61     for ( int j = 0; j < mNumColumns; ++j )
62     {
63       if ( mInterpolator->interpolatePoint( currentXValue, currentYValue, interpolatedValue, feedback ) == 0 )
64       {
65         outStream << interpolatedValue << ' ';
66       }
67       else
68       {
69         outStream << "-9999 ";
70       }
71       currentXValue += mCellSizeX;
72     }
73     outStream << endl;
74     currentYValue -= mCellSizeY;
75 
76     if ( feedback )
77     {
78       if ( feedback->isCanceled() )
79       {
80         outputFile.remove();
81         return 3;
82       }
83       feedback->setProgress( 100.0 * i / static_cast< double >( mNumRows ) );
84     }
85   }
86 
87   // create prj file
88   QgsInterpolator::LayerData ld;
89   ld = mInterpolator->layerData().at( 0 );
90   QgsFeatureSource *source = ld.source;
91   QString crs = source->sourceCrs().toWkt();
92   QFileInfo fi( mOutputFilePath );
93   QString fileName = fi.absolutePath() + '/' + fi.completeBaseName() + ".prj";
94   QFile prjFile( fileName );
95   if ( !prjFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
96   {
97     return 1;
98   }
99   QTextStream prjStream( &prjFile );
100   prjStream << crs;
101   prjStream << endl;
102   prjFile.close();
103 
104   return 0;
105 }
106 
writeHeader(QTextStream & outStream)107 int QgsGridFileWriter::writeHeader( QTextStream &outStream )
108 {
109   outStream << "NCOLS " << mNumColumns << endl;
110   outStream << "NROWS " << mNumRows << endl;
111   outStream << "XLLCORNER " << mInterpolationExtent.xMinimum() << endl;
112   outStream << "YLLCORNER " <<  mInterpolationExtent.yMinimum() << endl;
113   if ( mCellSizeX == mCellSizeY ) //standard way
114   {
115     outStream << "CELLSIZE " << mCellSizeX << endl;
116   }
117   else //this is supported by GDAL but probably not by other products
118   {
119     outStream << "DX " << mCellSizeX << endl;
120     outStream << "DY " << mCellSizeY << endl;
121   }
122   outStream << "NODATA_VALUE -9999" << endl;
123 
124   return 0;
125 }
126