23 #include "cpl_string.h" 
   24 #include <QProgressDialog> 
   28 #include <QTextStream> 
   30 #if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1800 
   31 #define TO8F(x) (x).toUtf8().constData() 
   33 #define TO8F(x) QFile::encodeName( x ).constData() 
   36 QgsRelief::QgsRelief( 
const QString& inputFile, 
const QString& outputFile, 
const QString& outputFormat ): \
 
   37     mInputFile( inputFile ), mOutputFile( outputFile ), mOutputFormat( outputFormat ), mZFactor( 1.0 )
 
   84   if ( inputDataset == NULL )
 
   91   if ( outputDriver == 0 )
 
   96   GDALDatasetH outputDataset = 
openOutputFile( inputDataset, outputDriver );
 
   97   if ( outputDataset == NULL )
 
  120   GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset, 1 );
 
  121   if ( rasterBand == NULL )
 
  123     GDALClose( inputDataset );
 
  124     GDALClose( outputDataset );
 
  134   GDALRasterBandH outputRedBand = GDALGetRasterBand( outputDataset, 1 );
 
  135   GDALRasterBandH outputGreenBand = GDALGetRasterBand( outputDataset, 2 );
 
  136   GDALRasterBandH outputBlueBand = GDALGetRasterBand( outputDataset, 3 );
 
  138   if ( outputRedBand == NULL || outputGreenBand == NULL || outputBlueBand == NULL )
 
  140     GDALClose( inputDataset );
 
  141     GDALClose( outputDataset );
 
  145   GDALSetRasterNoDataValue( outputRedBand, -9999 );
 
  146   GDALSetRasterNoDataValue( outputGreenBand, -9999 );
 
  147   GDALSetRasterNoDataValue( outputBlueBand, -9999 );
 
  157     GDALClose( inputDataset );
 
  158     GDALClose( outputDataset );
 
  163   float* scanLine1 = ( 
float * ) CPLMalloc( 
sizeof( 
float ) * xSize );
 
  164   float* scanLine2 = ( 
float * ) CPLMalloc( 
sizeof( 
float ) * xSize );
 
  165   float* scanLine3 = ( 
float * ) CPLMalloc( 
sizeof( 
float ) * xSize );
 
  167   unsigned char* resultRedLine = ( 
unsigned char * ) CPLMalloc( 
sizeof( 
unsigned char ) * xSize );
 
  168   unsigned char* resultGreenLine = ( 
unsigned char * ) CPLMalloc( 
sizeof( 
unsigned char ) * xSize );
 
  169   unsigned char* resultBlueLine = ( 
unsigned char * ) CPLMalloc( 
sizeof( 
unsigned char ) * xSize );
 
  173     p->setMaximum( ySize );
 
  179   for ( 
int i = 0; i < ySize; ++i )
 
  186     if ( p && p->wasCanceled() )
 
  194       for ( 
int a = 0; a < xSize; ++a )
 
  198       GDALRasterIO( rasterBand, GF_Read, 0, 0, xSize, 1, scanLine2, xSize, 1, GDT_Float32, 0, 0 );
 
  203       CPLFree( scanLine1 );
 
  204       scanLine1 = scanLine2;
 
  205       scanLine2 = scanLine3;
 
  206       scanLine3 = ( 
float * ) CPLMalloc( 
sizeof( 
float ) * xSize );
 
  209     if ( i == ySize - 1 ) 
 
  211       for ( 
int a = 0; a < xSize; ++a )
 
  218       GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, scanLine3, xSize, 1, GDT_Float32, 0, 0 );
 
  221     for ( 
int j = 0; j < xSize; ++j )
 
  227                                           &resultRedLine[j], &resultGreenLine[j], &resultBlueLine[j] );
 
  229       else if ( j == xSize - 1 )
 
  233                                           &resultRedLine[j], &resultGreenLine[j], &resultBlueLine[j] );
 
  237         resultOk = 
processNineCellWindow( &scanLine1[j-1], &scanLine1[j], &scanLine1[j+1], &scanLine2[j-1], &scanLine2[j], \
 
  238                                           &scanLine2[j+1], &scanLine3[j-1], &scanLine3[j], &scanLine3[j+1], \
 
  239                                           &resultRedLine[j], &resultGreenLine[j], &resultBlueLine[j] );
 
  250     GDALRasterIO( outputRedBand, GF_Write, 0, i, xSize, 1, resultRedLine, xSize, 1, GDT_Byte, 0, 0 );
 
  251     GDALRasterIO( outputGreenBand, GF_Write, 0, i, xSize, 1, resultGreenLine, xSize, 1, GDT_Byte, 0, 0 );
 
  252     GDALRasterIO( outputBlueBand, GF_Write, 0, i, xSize, 1, resultBlueLine, xSize, 1, GDT_Byte, 0, 0 );
 
  257     p->setValue( ySize );
 
  260   CPLFree( resultRedLine );
 
  261   CPLFree( resultBlueLine );
 
  262   CPLFree( resultGreenLine );
 
  263   CPLFree( scanLine1 );
 
  264   CPLFree( scanLine2 );
 
  265   CPLFree( scanLine3 );
 
  267   GDALClose( inputDataset );
 
  269   if ( p && p->wasCanceled() )
 
  275   GDALClose( outputDataset );
 
  281                                        unsigned char* red, 
unsigned char* green, 
unsigned char* blue )
 
  293       r = hillShadeValue300;
 
  294       g = hillShadeValue300;
 
  295       b = hillShadeValue300;
 
  299       r = r / 2.0 + hillShadeValue300 / 2.0;
 
  300       g = g / 2.0 + hillShadeValue300 / 2.0;
 
  301       b = b / 2.0 + hillShadeValue300 / 2.0;
 
  313       r2 = 0 / 2.0 + hillShadeValue315 / 2.0;
 
  314       g2 = 0 / 2.0 + hillShadeValue315 / 2.0;
 
  315       b2 = 0 / 2.0 + hillShadeValue315 / 2.0;
 
  317     else if ( slope >= 1 )
 
  319       int slopeValue = 255 - ( slope / 15.0 * 255.0 );
 
  320       r2 = slopeValue / 2.0 + hillShadeValue315 / 2.0;
 
  321       g2 = slopeValue / 2.0 + hillShadeValue315 / 2.0;
 
  322       b2 = slopeValue / 2.0 + hillShadeValue315 / 2.0;
 
  326       r2 = hillShadeValue315; g2 = hillShadeValue315; b2 = hillShadeValue315;
 
  330     r = r * 0.7 + r2 * 0.3;
 
  331     g = g * 0.7 + g2 * 0.3;
 
  332     b = b * 0.7 + b2 * 0.3;
 
  340     double angle_diff = qAbs( 285 - aspect );
 
  341     if ( angle_diff > 180 )
 
  347     if ( angle_diff < 90 )
 
  349       int aspectVal = ( 1 - cos( angle_diff * 
M_PI / 180 ) ) * 255;
 
  350       r3 = 0.5 * 255 + hillShadeValue315 * 0.5;
 
  351       g3 = 0.5 * 255 + hillShadeValue315 * 0.5;
 
  352       b3 = 0.5 * aspectVal + hillShadeValue315 * 0.5;
 
  356       r3 = 0.5 * 255 + hillShadeValue315 * 0.5;
 
  357       g3 = 0.5 * 255 + hillShadeValue315 * 0.5;
 
  358       b3 = 0.5 * 255 + hillShadeValue315 * 0.5;
 
  361     r = r3 * 0.1 + r * 0.9;
 
  362     g = g3 * 0.1 + g * 0.9;
 
  363     b = b3 * 0.1 + b * 0.9;
 
  366   *red = ( 
unsigned char )r;
 
  367   *green = ( 
unsigned char )g;
 
  368   *blue = ( 
unsigned char )b;
 
  374   QList< ReliefColor >::const_iterator reliefColorIt =  
mReliefColors.constBegin();
 
  375   for ( ; reliefColorIt != 
mReliefColors.constEnd(); ++reliefColorIt )
 
  377     if ( elevation >= reliefColorIt->minElevation && elevation <= reliefColorIt->maxElevation )
 
  379       const QColor& c = reliefColorIt->color;
 
  393   GDALDatasetH inputDataset = GDALOpen( 
TO8F( 
mInputFile ), GA_ReadOnly );
 
  394   if ( inputDataset != NULL )
 
  396     nCellsX = GDALGetRasterXSize( inputDataset );
 
  397     nCellsY = GDALGetRasterYSize( inputDataset );
 
  400     if ( GDALGetRasterCount( inputDataset ) < 1 )
 
  402       GDALClose( inputDataset );
 
  411   char **driverMetadata;
 
  414   GDALDriverH outputDriver = GDALGetDriverByName( 
mOutputFormat.toLocal8Bit().data() );
 
  416   if ( outputDriver == NULL )
 
  421   driverMetadata = GDALGetMetadata( outputDriver, NULL );
 
  422   if ( !CSLFetchBoolean( driverMetadata, GDAL_DCAP_CREATE, 
false ) )
 
  432   if ( inputDataset == NULL )
 
  437   int xSize = GDALGetRasterXSize( inputDataset );
 
  438   int ySize = GDALGetRasterYSize( inputDataset );;
 
  441   char **papszOptions = NULL;
 
  444   papszOptions = CSLSetNameValue( papszOptions, 
"COMPRESS", 
"PACKBITS" );
 
  447   GDALDatasetH outputDataset = GDALCreate( outputDriver, 
TO8F( 
mOutputFile ), xSize, ySize, 3, GDT_Byte, papszOptions );
 
  448   if ( outputDataset == NULL )
 
  450     return outputDataset;
 
  454   double geotransform[6];
 
  455   if ( GDALGetGeoTransform( inputDataset, geotransform ) != CE_None )
 
  457     GDALClose( outputDataset );
 
  460   GDALSetGeoTransform( outputDataset, geotransform );
 
  474   const char* projection = GDALGetProjectionRef( inputDataset );
 
  475   GDALSetProjection( outputDataset, projection );
 
  477   return outputDataset;
 
  483   int nCellsX, nCellsY;
 
  484   GDALDatasetH inputDataset = 
openInputFile( nCellsX, nCellsY );
 
  485   if ( inputDataset == NULL )
 
  491   GDALRasterBandH elevationBand = GDALGetRasterBand( inputDataset, 1 );
 
  492   if ( elevationBand == NULL )
 
  494     GDALClose( inputDataset );
 
  501   minMax[0] = GDALGetRasterMinimum( elevationBand, &minOk );
 
  502   minMax[1] = GDALGetRasterMaximum( elevationBand, &maxOk );
 
  504   if ( !minOk || !maxOk )
 
  506     GDALComputeRasterMinMax( elevationBand, TRUE, minMax );
 
  512   double frequency[252];
 
  513   double frequencyClassRange = ( minMax[1] - minMax[0] ) / 252.0;
 
  515   for ( 
int i = 0; i < 252; ++i )
 
  520   float* scanLine = ( 
float * ) CPLMalloc( 
sizeof( 
float ) *  nCellsX );
 
  521   int elevationClass = -1;
 
  523   for ( 
int i = 0; i < nCellsY; ++i )
 
  525     GDALRasterIO( elevationBand, GF_Read, 0, i, nCellsX, 1,
 
  526                   scanLine, nCellsX, 1, GDT_Float32,
 
  528     for ( 
int j = 0; j < nCellsX; ++j )
 
  531       if ( elevationClass >= 0 )
 
  533         frequency[elevationClass] += 1.0;
 
  541   for ( 
int i = 0; i < 252; ++i )
 
  543     frequency[i] = log10( frequency[i] );
 
  547   QFile outFile( file );
 
  548   if ( !outFile.open( QIODevice::WriteOnly ) )
 
  553   QTextStream outstream( &outFile );
 
  554   for ( 
int i = 0; i < 252; ++i )
 
  556     outstream << QString::number( i ) + 
"," + QString::number( frequency[i] ) << endl;
 
  564   QList< QgsRelief::ReliefColor > resultList;
 
  566   int nCellsX, nCellsY;
 
  567   GDALDatasetH inputDataset = 
openInputFile( nCellsX, nCellsY );
 
  568   if ( inputDataset == NULL )
 
  574   GDALRasterBandH elevationBand = GDALGetRasterBand( inputDataset, 1 );
 
  575   if ( elevationBand == NULL )
 
  577     GDALClose( inputDataset );
 
  584   minMax[0] = GDALGetRasterMinimum( elevationBand, &minOk );
 
  585   minMax[1] = GDALGetRasterMaximum( elevationBand, &maxOk );
 
  587   if ( !minOk || !maxOk )
 
  589     GDALComputeRasterMinMax( elevationBand, TRUE, minMax );
 
  595   double frequency[252];
 
  596   double frequencyClassRange = ( minMax[1] - minMax[0] ) / 252.0;
 
  598   for ( 
int i = 0; i < 252; ++i )
 
  603   float* scanLine = ( 
float * ) CPLMalloc( 
sizeof( 
float ) *  nCellsX );
 
  604   int elevationClass = -1;
 
  606   for ( 
int i = 0; i < nCellsY; ++i )
 
  608     GDALRasterIO( elevationBand, GF_Read, 0, i, nCellsX, 1,
 
  609                   scanLine, nCellsX, 1, GDT_Float32,
 
  611     for ( 
int j = 0; j < nCellsX; ++j )
 
  614       if ( elevationClass < 0 )
 
  618       else if ( elevationClass >= 252 )
 
  620         elevationClass = 251;
 
  622       frequency[elevationClass] += 1.0;
 
  629   for ( 
int i = 0; i < 252; ++i )
 
  631     frequency[i] = log10( frequency[i] );
 
  635   QList<int> classBreaks;
 
  636   classBreaks.append( 0 );
 
  637   classBreaks.append( 28 );
 
  638   classBreaks.append( 56 );
 
  639   classBreaks.append( 84 );
 
  640   classBreaks.append( 112 );
 
  641   classBreaks.append( 140 );
 
  642   classBreaks.append( 168 );
 
  643   classBreaks.append( 196 );
 
  644   classBreaks.append( 224 );
 
  645   classBreaks.append( 252 );
 
  647   for ( 
int i = 0; i < 10; ++i )
 
  653   for ( 
int i = 0; i < classBreaks.size(); ++i )
 
  655     qWarning( 
"%d", classBreaks[i] );
 
  659   QList<QColor> colorList;
 
  660   colorList.push_back( QColor( 7, 165, 144 ) );
 
  661   colorList.push_back( QColor( 12, 221, 162 ) );
 
  662   colorList.push_back( QColor( 33, 252, 183 ) );
 
  663   colorList.push_back( QColor( 247, 252, 152 ) );
 
  664   colorList.push_back( QColor( 252, 196, 8 ) );
 
  665   colorList.push_back( QColor( 252, 166, 15 ) );
 
  666   colorList.push_back( QColor( 175, 101, 15 ) );
 
  667   colorList.push_back( QColor( 255, 133, 92 ) );
 
  668   colorList.push_back( QColor( 204, 204, 204 ) );
 
  670   for ( 
int i = 1; i < classBreaks.size(); ++i )
 
  672     double minElevation = minMax[0] + classBreaks[i - 1] * frequencyClassRange;
 
  673     double maxElevation = minMax[0] + classBreaks[i] * frequencyClassRange;
 
  682   int nClasses = breaks.size() - 1;
 
  683   double* a = 
new double[nClasses]; 
 
  684   double* b = 
new double[nClasses]; 
 
  686   for ( 
int i = 0; i < nClasses; ++i )
 
  689     QList< QPair < int, double > > regressionInput;
 
  690     for ( 
int j = breaks.at( i ); j < breaks.at( i + 1 ); ++j )
 
  692       regressionInput.push_back( qMakePair( j, frequencies[j] ) );
 
  695     double aParam, bParam;
 
  696     if ( regressionInput.size() > 0 && 
calculateRegression( regressionInput, aParam, bParam ) )
 
  708   QList<int> classesToRemove;
 
  711   for ( 
int i = 1; i < nClasses ; ++i )
 
  713     if ( breaks[i] == breaks[ i - 1 ] )
 
  724       int newX = ( b[i - 1] - b[ i ] ) / ( a[ i ] - a[ i - 1 ] );
 
  726       if ( newX <= breaks[i - 1] )
 
  728         newX = breaks[i - 1];
 
  731       else if ( i < nClasses - 1 && newX >= breaks[i + 1] )
 
  733         newX = breaks[i + 1];
 
  741   for ( 
int i = classesToRemove.size() - 1; i >= 0; --i )
 
  743     breaks.removeAt( classesToRemove.at( i ) );
 
  752   return ( elevation - minElevation ) / elevationClassRange;
 
  760   QList< QPair < int, double > >::const_iterator inputIt = input.constBegin();
 
  761   for ( ; inputIt != input.constEnd(); ++inputIt )
 
  763     xSum += inputIt->first;
 
  764     ySum += inputIt->second;
 
  766   xMean = xSum / input.size();
 
  767   yMean = ySum / input.size();
 
  769   double sumCounter = 0;
 
  770   double sumDenominator = 0;
 
  771   inputIt = input.constBegin();
 
  772   for ( ; inputIt != input.constEnd(); ++inputIt )
 
  774     sumCounter += (( inputIt->first - xMean ) * ( inputIt->second - yMean ) );
 
  775     sumDenominator += (( inputIt->first - xMean ) * ( inputIt->first - xMean ) );
 
  778   a = sumCounter / sumDenominator;
 
  779   b = yMean - a * xMean;