コード例 #1
0
ファイル: qgsrasterinterface.cpp プロジェクト: Aladar64/QGIS
void QgsRasterInterface::cumulativeCut( int theBandNo,
                                        double theLowerCount, double theUpperCount,
                                        double &theLowerValue, double &theUpperValue,
                                        const QgsRectangle & theExtent,
                                        int theSampleSize )
{
  QgsDebugMsg( QString( "theBandNo = %1 theLowerCount = %2 theUpperCount = %3 theSampleSize = %4" ).arg( theBandNo ).arg( theLowerCount ).arg( theUpperCount ).arg( theSampleSize ) );

  int mySrcDataType = srcDataType( theBandNo );

  //get band stats to specify real histogram min/max (fix #9793 Byte bands)
  QgsRasterBandStats stats =  bandStatistics( theBandNo, QgsRasterBandStats::Min, theExtent, theSampleSize );
  // for byte bands make sure bin count == actual range
  int myBinCount = ( mySrcDataType == QGis::Byte ) ? int( ceil( stats.maximumValue - stats.minimumValue + 1 ) ) : 0;
  QgsRasterHistogram myHistogram = histogram( theBandNo, myBinCount, stats.minimumValue, stats.maximumValue, theExtent, theSampleSize );
  //QgsRasterHistogram myHistogram = histogram( theBandNo, 0, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), theExtent, theSampleSize );

  // Init to NaN is better than histogram min/max to catch errors
  theLowerValue = std::numeric_limits<double>::quiet_NaN();
  theUpperValue = std::numeric_limits<double>::quiet_NaN();

  double myBinXStep = ( myHistogram.maximum - myHistogram.minimum ) / myHistogram.binCount;
  int myCount = 0;
  int myMinCount = ( int ) qRound( theLowerCount * myHistogram.nonNullCount );
  int myMaxCount = ( int ) qRound( theUpperCount * myHistogram.nonNullCount );
  bool myLowerFound = false;
  QgsDebugMsg( QString( "binCount = %1 minimum = %2 maximum = %3 myBinXStep = %4" ).arg( myHistogram.binCount ).arg( myHistogram.minimum ).arg( myHistogram.maximum ).arg( myBinXStep ) );
  QgsDebugMsg( QString( "myMinCount = %1 myMaxCount = %2" ).arg( myMinCount ).arg( myMaxCount ) );

  for ( int myBin = 0; myBin < myHistogram.histogramVector.size(); myBin++ )
  {
    int myBinValue = myHistogram.histogramVector.value( myBin );
    myCount += myBinValue;
    if ( !myLowerFound && myCount > myMinCount )
    {
      theLowerValue = myHistogram.minimum + myBin * myBinXStep;
      myLowerFound = true;
      QgsDebugMsg( QString( "found lowerValue %1 at bin %2" ).arg( theLowerValue ).arg( myBin ) );
    }
    if ( myCount >= myMaxCount )
    {
      theUpperValue = myHistogram.minimum + myBin * myBinXStep;
      QgsDebugMsg( QString( "found upperValue %1 at bin %2" ).arg( theUpperValue ).arg( myBin ) );
      break;
    }
  }

  // fix integer data - round down/up
  if ( mySrcDataType == QGis::Byte ||
       mySrcDataType == QGis::Int16 || mySrcDataType == QGis::Int32 ||
       mySrcDataType == QGis::UInt16 || mySrcDataType == QGis::UInt32 )
  {
    if ( theLowerValue != std::numeric_limits<double>::quiet_NaN() )
      theLowerValue = floor( theLowerValue );
    if ( theUpperValue != std::numeric_limits<double>::quiet_NaN() )
      theUpperValue = ceil( theUpperValue );
  }
}
コード例 #2
0
ファイル: qgsrasterinterface.cpp プロジェクト: Aladar64/QGIS
void QgsRasterInterface::initHistogram( QgsRasterHistogram &theHistogram,
                                        int theBandNo,
                                        int theBinCount,
                                        double theMinimum, double theMaximum,
                                        const QgsRectangle & theExtent,
                                        int theSampleSize,
                                        bool theIncludeOutOfRange )
{
  theHistogram.bandNumber = theBandNo;
  theHistogram.minimum = theMinimum;
  theHistogram.maximum = theMaximum;
  theHistogram.includeOutOfRange = theIncludeOutOfRange;

  int mySrcDataType = srcDataType( theBandNo );

  if ( qIsNaN( theHistogram.minimum ) )
  {
    // TODO: this was OK when stats/histogram were calced in provider,
    // but what TODO in other interfaces? Check for mInput for now.
    if ( !mInput && mySrcDataType == QGis::Byte )
    {
      theHistogram.minimum = 0; // see histogram() for shift for rounding
    }
    else
    {
      // We need statistics -> avoid histogramDefaults in hasHistogram if possible
      // TODO: use approximated statistics if aproximated histogram is requested
      // (theSampleSize > 0)
      QgsRasterBandStats stats =  bandStatistics( theBandNo, QgsRasterBandStats::Min, theExtent, theSampleSize );
      theHistogram.minimum = stats.minimumValue;
    }
  }
  if ( qIsNaN( theHistogram.maximum ) )
  {
    if ( !mInput && mySrcDataType == QGis::Byte )
    {
      theHistogram.maximum = 255;
    }
    else
    {
      QgsRasterBandStats stats =  bandStatistics( theBandNo, QgsRasterBandStats::Max, theExtent, theSampleSize );
      theHistogram.maximum = stats.maximumValue;
    }
  }

  QgsRectangle myExtent;
  if ( theExtent.isEmpty() )
  {
    myExtent = extent();
  }
  else
  {
    myExtent = extent().intersect( &theExtent );
  }
  theHistogram.extent = myExtent;

  if ( theSampleSize > 0 )
  {
    // Calc resolution from theSampleSize
    double xRes, yRes;
    xRes = yRes = sqrt(( myExtent.width() * myExtent.height() ) / theSampleSize );

    // But limit by physical resolution
    if ( capabilities() & Size )
    {
      double srcXRes = extent().width() / xSize();
      double srcYRes = extent().height() / ySize();
      if ( xRes < srcXRes ) xRes = srcXRes;
      if ( yRes < srcYRes ) yRes = srcYRes;
    }
    QgsDebugMsg( QString( "xRes = %1 yRes = %2" ).arg( xRes ).arg( yRes ) );

    theHistogram.width = static_cast <int>( myExtent.width() / xRes );
    theHistogram.height = static_cast <int>( myExtent.height() / yRes );
  }
  else
  {
    if ( capabilities() & Size )
    {
      theHistogram.width = xSize();
      theHistogram.height = ySize();
    }
    else
    {
      theHistogram.width = 1000;
      theHistogram.height = 1000;
    }
  }
  QgsDebugMsg( QString( "theHistogram.width = %1 theHistogram.height = %2" ).arg( theHistogram.width ).arg( theHistogram.height ) );

  int myBinCount = theBinCount;
  if ( myBinCount == 0 )
  {
    // TODO: this was OK when stats/histogram were calced in provider,
    // but what TODO in other interfaces? Check for mInput for now.
    if ( !mInput && mySrcDataType == QGis::Byte )
    {
      myBinCount = 256; // Cannot store more values in byte
    }
    else
    {
      // There is no best default value, to display something reasonable in histogram chart, binCount should be small, OTOH, to get precise data for cumulative cut, the number should be big. Because it is easier to define fixed lower value for the chart, we calc optimum binCount for higher resolution (to avoid calculating that where histogram() is used. In any any case, it does not make sense to use more than width*height;
      myBinCount = theHistogram.width * theHistogram.height;
      if ( myBinCount > 1000 )  myBinCount = 1000;

      // for Int16/Int32 make sure bin count <= actual range, because there is no sense in having
      // bins at fractional values
      if ( !mInput && (
             mySrcDataType == QGis::Int16 || mySrcDataType == QGis::Int32 ||
             mySrcDataType == QGis::UInt16 || mySrcDataType == QGis::UInt32 ) )
      {
        if ( myBinCount > theHistogram.maximum - theHistogram.minimum + 1 )
          myBinCount = int( ceil( theHistogram.maximum - theHistogram.minimum + 1 ) );
      }
    }
  }
  theHistogram.binCount = myBinCount;
  QgsDebugMsg( QString( "theHistogram.binCount = %1" ).arg( theHistogram.binCount ) );
}
コード例 #3
0
void QgsRasterInterface::cumulativeCut( int bandNo,
                                        double lowerCount, double upperCount,
                                        double &lowerValue, double &upperValue,
                                        const QgsRectangle &extent,
                                        int sampleSize )
{
  QgsDebugMsgLevel( QString( "theBandNo = %1 lowerCount = %2 upperCount = %3 sampleSize = %4" ).arg( bandNo ).arg( lowerCount ).arg( upperCount ).arg( sampleSize ), 4 );

  int mySrcDataType = sourceDataType( bandNo );

  // Init to NaN is better than histogram min/max to catch errors
  lowerValue = std::numeric_limits<double>::quiet_NaN();
  upperValue = std::numeric_limits<double>::quiet_NaN();

  //get band stats to specify real histogram min/max (fix #9793 Byte bands)
  QgsRasterBandStats stats = bandStatistics( bandNo, QgsRasterBandStats::Min, extent, sampleSize );
  if ( stats.maximumValue < stats.minimumValue )
    return;

  // for byte bands make sure bin count == actual range
  int myBinCount = ( mySrcDataType == Qgis::Byte ) ? int( std::ceil( stats.maximumValue - stats.minimumValue + 1 ) ) : 0;
  QgsRasterHistogram myHistogram = histogram( bandNo, myBinCount, stats.minimumValue, stats.maximumValue, extent, sampleSize );
  //QgsRasterHistogram myHistogram = histogram( bandNo, 0, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), extent, sampleSize );

  double myBinXStep = ( myHistogram.maximum - myHistogram.minimum ) / myHistogram.binCount;
  int myCount = 0;
  int myMinCount = static_cast< int >( std::round( lowerCount * myHistogram.nonNullCount ) );
  int myMaxCount = static_cast< int >( std::round( upperCount * myHistogram.nonNullCount ) );
  bool myLowerFound = false;
  QgsDebugMsgLevel( QString( "binCount = %1 minimum = %2 maximum = %3 myBinXStep = %4" ).arg( myHistogram.binCount ).arg( myHistogram.minimum ).arg( myHistogram.maximum ).arg( myBinXStep ), 4 );
  QgsDebugMsgLevel( QString( "myMinCount = %1 myMaxCount = %2" ).arg( myMinCount ).arg( myMaxCount ), 4 );

  for ( int myBin = 0; myBin < myHistogram.histogramVector.size(); myBin++ )
  {
    int myBinValue = myHistogram.histogramVector.value( myBin );
    myCount += myBinValue;
    if ( !myLowerFound && myCount > myMinCount )
    {
      lowerValue = myHistogram.minimum + myBin * myBinXStep;
      myLowerFound = true;
      QgsDebugMsgLevel( QString( "found lowerValue %1 at bin %2" ).arg( lowerValue ).arg( myBin ), 4 );
    }
    if ( myCount >= myMaxCount )
    {
      upperValue = myHistogram.minimum + myBin * myBinXStep;
      QgsDebugMsgLevel( QString( "found upperValue %1 at bin %2" ).arg( upperValue ).arg( myBin ), 4 );
      break;
    }
  }

  // fix integer data - round down/up
  if ( mySrcDataType == Qgis::Byte ||
       mySrcDataType == Qgis::Int16 || mySrcDataType == Qgis::Int32 ||
       mySrcDataType == Qgis::UInt16 || mySrcDataType == Qgis::UInt32 )
  {
    if ( lowerValue != std::numeric_limits<double>::quiet_NaN() )
      lowerValue = std::floor( lowerValue );
    if ( upperValue != std::numeric_limits<double>::quiet_NaN() )
      upperValue = std::ceil( upperValue );
  }
}