diff --git a/python/core/core.sip b/python/core/core.sip index b2e55342ebf..50a0ca06834 100644 --- a/python/core/core.sip +++ b/python/core/core.sip @@ -150,6 +150,7 @@ %Include raster/qgsrasterpipe.sip %Include raster/qgsrasterprojector.sip %Include raster/qgsrasterpyramid.sip +%Include raster/qgsrasterrange.sip %Include raster/qgsrasterrenderer.sip %Include raster/qgsrasterresamplefilter.sip %Include raster/qgsrasterresampler.sip diff --git a/python/core/raster/qgsrasterblock.sip b/python/core/raster/qgsrasterblock.sip index 1767aa12da4..769560c2ea6 100644 --- a/python/core/raster/qgsrasterblock.sip +++ b/python/core/raster/qgsrasterblock.sip @@ -6,13 +6,6 @@ class QgsRasterBlock %End public: - struct Range - { - double min; - double max; - bool operator==( const QgsRasterBlock::Range &o ) const; - }; - QgsRasterBlock(); QgsRasterBlock( QGis::DataType theDataType, int theWidth, int theHeight, double theNoDataValue ); @@ -65,8 +58,5 @@ class QgsRasterBlock bool convert( QGis::DataType destDataType ); QImage image() const; bool setImage( const QImage * image ); - - static bool valueInRange( double value, const QList &rangeList ); - }; diff --git a/python/core/raster/qgsrasterdataprovider.sip b/python/core/raster/qgsrasterdataprovider.sip index f201b37c83b..76fb4775440 100644 --- a/python/core/raster/qgsrasterdataprovider.sip +++ b/python/core/raster/qgsrasterdataprovider.sip @@ -156,10 +156,10 @@ class QgsRasterDataProvider : QgsDataProvider, QgsRasterInterface /** Value representing no data value. */ virtual double srcNoDataValue( int bandNo ) const; - virtual void setUserNoDataValue( int bandNo, QList noData ); + virtual void setUserNoDataValue( int bandNo, QgsRasterRangeList noData ); /** Get list of user no data value ranges */ - virtual QList userNoDataValue( int bandNo ) const; + virtual QgsRasterRangeList userNoDataValue( int bandNo ) const; virtual double minimumValue( int bandNo ) const; virtual double maximumValue( int bandNo ) const; diff --git a/python/core/raster/qgsrasteridentifyresult.sip b/python/core/raster/qgsrasteridentifyresult.sip index bc438f49573..2da165d6cc9 100644 --- a/python/core/raster/qgsrasteridentifyresult.sip +++ b/python/core/raster/qgsrasteridentifyresult.sip @@ -25,8 +25,5 @@ class QgsRasterIdentifyResult QgsError error() const; void setError( const QgsError & theError ); - - void appendError( const QgsErrorMessage & theMessage ); - }; diff --git a/python/core/raster/qgsrasterrange.sip b/python/core/raster/qgsrasterrange.sip new file mode 100644 index 00000000000..eea4bb36c9f --- /dev/null +++ b/python/core/raster/qgsrasterrange.sip @@ -0,0 +1,25 @@ +typedef QList QgsRasterRangeList; + +class QgsRasterRange +{ +%TypeHeaderCode +#include +%End + + public: + QgsRasterRange(); + + QgsRasterRange( double theMin, double theMax ); + + ~QgsRasterRange(); + + double min() const; + double max() const; + + double setMin( double theMin ); + double setMax( double theMax ); + + bool operator==( const QgsRasterRange &o ) const; + + bool contains( double value, const QgsRasterRangeList &rangeList ); +}; diff --git a/src/app/qgsrasterlayerproperties.cpp b/src/app/qgsrasterlayerproperties.cpp index 942109e19aa..0abbfa8bdcb 100644 --- a/src/app/qgsrasterlayerproperties.cpp +++ b/src/app/qgsrasterlayerproperties.cpp @@ -41,6 +41,7 @@ #include "qgsrasterlayer.h" #include "qgsrasterlayerproperties.h" #include "qgsrasterpyramid.h" +#include "qgsrasterrange.h" #include "qgsrasterrenderer.h" #include "qgsrasterrendererregistry.h" #include "qgsrastertransparency.h" @@ -624,11 +625,11 @@ void QgsRasterLayerProperties::sync() mSrcNoDataValueCheckBox->setEnabled( enableSrcNoData ); lblSrcNoDataValue->setEnabled( enableSrcNoData ); - QList noDataRangeList = mRasterLayer->dataProvider()->userNoDataValue( 1 ); + QgsRasterRangeList noDataRangeList = mRasterLayer->dataProvider()->userNoDataValue( 1 ); QgsDebugMsg( QString( "noDataRangeList.size = %1" ).arg( noDataRangeList.size() ) ); if ( noDataRangeList.size() > 0 ) { - leNoDataValue->insert( QgsRasterBlock::printValue( noDataRangeList.value( 0 ).min ) ); + leNoDataValue->insert( QgsRasterBlock::printValue( noDataRangeList.value( 0 ).min() ) ); } else { @@ -736,18 +737,14 @@ void QgsRasterLayerProperties::apply() */ //set NoDataValue - QList myNoDataRangeList; + QgsRasterRangeList myNoDataRangeList; if ( "" != leNoDataValue->text() ) { bool myDoubleOk = false; double myNoDataValue = leNoDataValue->text().toDouble( &myDoubleOk ); if ( myDoubleOk ) { - //mRasterLayer->setNoDataValue( myNoDataValue ); - QgsRasterBlock::Range myNoDataRange; - myNoDataRange.min = myNoDataValue; - myNoDataRange.max = myNoDataValue; - + QgsRasterRange myNoDataRange( myNoDataValue, myNoDataValue ); myNoDataRangeList << myNoDataRange; } } diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index de0bb3cfb1a..0b5b7f1614c 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -197,6 +197,7 @@ SET(QGIS_CORE_SRCS raster/qgsrasternuller.cpp raster/qgsrastertransparency.cpp raster/qgsrasterpipe.cpp + raster/qgsrasterrange.cpp raster/qgsrastershader.cpp raster/qgsrastershaderfunction.cpp @@ -477,6 +478,7 @@ SET(QGIS_CORE_HDRS raster/qgsrastertransparency.h raster/qgsrasterpipe.h raster/qgsrasterprojector.h + raster/qgsrasterrange.h raster/qgsrastershader.h raster/qgsrastershaderfunction.h raster/qgsrasterviewport.h diff --git a/src/core/raster/qgsrasterblock.cpp b/src/core/raster/qgsrasterblock.cpp index f5ac6b209fd..94788f1f3cc 100644 --- a/src/core/raster/qgsrasterblock.cpp +++ b/src/core/raster/qgsrasterblock.cpp @@ -27,8 +27,8 @@ #include "cpl_conv.h" QgsRasterBlock::QgsRasterBlock() -//mValid (false) - : mDataType( QGis::UnknownDataType ) + : mValid( true ) + , mDataType( QGis::UnknownDataType ) , mTypeSize( 0 ) , mWidth( 0 ) , mHeight( 0 ) @@ -39,8 +39,8 @@ QgsRasterBlock::QgsRasterBlock() } QgsRasterBlock::QgsRasterBlock( QGis::DataType theDataType, int theWidth, int theHeight, double theNoDataValue ) -//mValid(true) - : mDataType( theDataType ) + : mValid( true ) + , mDataType( theDataType ) , mTypeSize( 0 ) , mWidth( theWidth ) , mHeight( theHeight ) @@ -70,7 +70,7 @@ bool QgsRasterBlock::reset( QGis::DataType theDataType, int theWidth, int theHei mWidth = 0; mHeight = 0; mNoDataValue = std::numeric_limits::quiet_NaN(); - //mValid = false; + mValid = false; if ( typeIsNumeric( theDataType ) ) { @@ -96,7 +96,7 @@ bool QgsRasterBlock::reset( QGis::DataType theDataType, int theWidth, int theHei return false; } - //mValid = true; + mValid = true; mDataType = theDataType; mTypeSize = QgsRasterBlock::typeSize( mDataType ); mWidth = theWidth; @@ -410,7 +410,7 @@ bool QgsRasterBlock::convert( QGis::DataType destDataType ) return true; } -void QgsRasterBlock::applyNodataValues( const QList& rangeList ) +void QgsRasterBlock::applyNodataValues( const QgsRasterRangeList & rangeList ) { if ( rangeList.isEmpty() ) { @@ -421,7 +421,7 @@ void QgsRasterBlock::applyNodataValues( const QList& rangeList ) for ( size_t i = 0; i < size; ++i ) { double val = value( i ); - if ( valueInRange( val, rangeList ) ) + if ( QgsRasterRange::contains( val, rangeList ) ) { setValue( i, mNoDataValue ); } diff --git a/src/core/raster/qgsrasterblock.h b/src/core/raster/qgsrasterblock.h index 5f561399ce2..8d9b375d914 100644 --- a/src/core/raster/qgsrasterblock.h +++ b/src/core/raster/qgsrasterblock.h @@ -21,26 +21,17 @@ #include #include #include "qgis.h" +#include "qgserror.h" #include "qgslogger.h" +#include "qgsrasterrange.h" #include "qgsrectangle.h" /** \ingroup core * Raster data container. */ -// TODO: inherit from QObject? class CORE_EXPORT QgsRasterBlock { public: - struct Range - { - double min; - double max; - inline bool operator==( const Range &o ) const - { - return min == o.min && max == o.max; - } - }; - QgsRasterBlock(); /** \brief Constructor which allocates data block in memory @@ -64,7 +55,19 @@ class CORE_EXPORT QgsRasterBlock // TODO: consider if use isValid() at all, isEmpty() should be sufficient // and works also if block is valid but empty - difference between valid and empty? - //bool isValid() const { return mValid; } + /** \brief Returns true if the block is valid (correctly filled with data). + * An empty block may still be valid (if zero size block was requested). + * If the block is not valid, error may be retrieved by error() method. + */ + bool isValid() const { return mValid; } + + /** \brief Mark block as valid or invalid */ + void setValid( bool valid ) { mValid = valid; } + + /** Returns true if block is empty, i.e. its size is 0 (zero rows or cols). + * This method does not return true if size is not zero and all values are + * 'no data' (null). + */ bool isEmpty() const; // Return data type size in bytes @@ -247,14 +250,6 @@ class CORE_EXPORT QgsRasterBlock QImage image() const; bool setImage( const QImage * image ); - /** \brief Test if value is within the list of ranges - * @param value value - * @param rangeList list of ranges - * @return true if value is in at least one of ranges - * @note not available in python bindings - */ - inline static bool valueInRange( double value, const QList &rangeList ); - /** Create a new image with extraneous data, such data may be used * after the image is destroyed. The memory is not initialized. */ @@ -279,7 +274,13 @@ class CORE_EXPORT QgsRasterBlock inline static void writeValue( void *data, QGis::DataType type, size_t index, double value ); - void applyNodataValues( const QList& rangeList ); + void applyNodataValues( const QgsRasterRangeList & rangeList ); + + /** \brief Get error */ + QgsError error() const { return mError; } + + /** \brief Set error */ + void setError( const QgsError & theError ) { mError = theError;} private: @@ -287,7 +288,7 @@ class CORE_EXPORT QgsRasterBlock static QGis::DataType dataType( QImage::Format theFormat ); // Valid - //bool isValid; + bool mValid; // Data type QGis::DataType mDataType; @@ -310,6 +311,9 @@ class CORE_EXPORT QgsRasterBlock // Image for image data types, not used with numerical data types QImage *mImage; + + // Error + QgsError mError; }; inline double QgsRasterBlock::readValue( void *data, QGis::DataType type, size_t index ) @@ -393,20 +397,6 @@ inline void QgsRasterBlock::writeValue( void *data, QGis::DataType type, size_t } } -inline bool QgsRasterBlock::valueInRange( double value, const QList &rangeList ) -{ - foreach ( QgsRasterBlock::Range range, rangeList ) - { - if (( value >= range.min && value <= range.max ) || - doubleNear( value, range.min ) || - doubleNear( value, range.max ) ) - { - return true; - } - } - return false; -} - inline double QgsRasterBlock::value( size_t index ) const { /*if ( index >= ( size_t )mWidth*mHeight ) diff --git a/src/core/raster/qgsrasterdataprovider.cpp b/src/core/raster/qgsrasterdataprovider.cpp index 67f33d58be9..a7640806357 100644 --- a/src/core/raster/qgsrasterdataprovider.cpp +++ b/src/core/raster/qgsrasterdataprovider.cpp @@ -507,14 +507,14 @@ double QgsRasterDataProvider::readValue( void *data, int type, int index ) } #endif -void QgsRasterDataProvider::setUserNoDataValue( int bandNo, QList noData ) +void QgsRasterDataProvider::setUserNoDataValue( int bandNo, QgsRasterRangeList noData ) { //if ( bandNo > bandCount() ) return; if ( bandNo >= mUserNoDataValue.size() ) { for ( int i = mUserNoDataValue.size(); i < bandNo; i++ ) { - mUserNoDataValue.append( QList() ); + mUserNoDataValue.append( QgsRasterRangeList() ); } } QgsDebugMsg( QString( "set %1 band %1 no data ranges" ).arg( noData.size() ) ); diff --git a/src/core/raster/qgsrasterdataprovider.h b/src/core/raster/qgsrasterdataprovider.h index 2337f69515f..7d86a488ced 100644 --- a/src/core/raster/qgsrasterdataprovider.h +++ b/src/core/raster/qgsrasterdataprovider.h @@ -35,6 +35,7 @@ #include "qgscoordinatereferencesystem.h" #include "qgsrasterbandstats.h" #include "qgsrasterhistogram.h" +#include "qgsrasterrange.h" #include "cpl_conv.h" #include @@ -276,10 +277,10 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast /** Value representing no data value. */ virtual double srcNoDataValue( int bandNo ) const { return mSrcNoDataValue.value( bandNo -1 ); } - virtual void setUserNoDataValue( int bandNo, QList noData ); + virtual void setUserNoDataValue( int bandNo, QgsRasterRangeList noData ); /** Get list of user no data value ranges */ - virtual QList userNoDataValue( int bandNo ) const { return mUserNoDataValue.value( bandNo -1 ); } + virtual QgsRasterRangeList userNoDataValue( int bandNo ) const { return mUserNoDataValue.value( bandNo -1 ); } virtual double minimumValue( int bandNo ) const { Q_UNUSED( bandNo ); return 0; } virtual double maximumValue( int bandNo ) const { Q_UNUSED( bandNo ); return 0; } @@ -514,7 +515,7 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast /** \brief List of lists of user defined additional no data values * for each band, indexed from 0 */ - QList< QList > mUserNoDataValue; + QList< QgsRasterRangeList > mUserNoDataValue; QgsRectangle mExtent; diff --git a/src/core/raster/qgsrasteridentifyresult.h b/src/core/raster/qgsrasteridentifyresult.h index b785c66e20d..5e20f04785d 100644 --- a/src/core/raster/qgsrasteridentifyresult.h +++ b/src/core/raster/qgsrasteridentifyresult.h @@ -51,9 +51,9 @@ class CORE_EXPORT QgsRasterIdentifyResult /** \brief Get results. Results are different for each format: * IdentifyFormatValue: map of values for each band, keys are band numbers (from 1). * IdentifyFormatFeature: map of QgsRasterFeatureList for each sublayer (WMS) - * IdentifyFormatHtml: map of HTML strings for each sublayer (WMS). + * IdentifyFormatHtml: map of HTML strings for each sublayer (WMS). */ - QMap results() const { return mResults; } + QMap results() const { return mResults; } /** Set map of optional parameters */ void setParams( const QMap & theParams ) { mParams = theParams; } @@ -67,9 +67,6 @@ class CORE_EXPORT QgsRasterIdentifyResult /** \brief Set error */ void setError( const QgsError & theError ) { mError = theError;} - /** \brief Add error message */ - void appendError( const QgsErrorMessage & theMessage ) { mError.append( theMessage );} - private: /** \brief Is valid */ bool mValid; diff --git a/src/core/raster/qgsrasterlayer.cpp b/src/core/raster/qgsrasterlayer.cpp index 2024096d67d..8a5f3e38a7e 100644 --- a/src/core/raster/qgsrasterlayer.cpp +++ b/src/core/raster/qgsrasterlayer.cpp @@ -24,6 +24,7 @@ email : tim at linfiniti.com #include "qgsprojectfiletransform.h" #include "qgsproviderregistry.h" #include "qgsrasterlayer.h" +#include "qgsrasterrange.h" #include "qgsrasterrendererregistry.h" #include "qgsrectangle.h" #include "qgsrendercontext.h" @@ -2471,17 +2472,16 @@ bool QgsRasterLayer::readXml( const QDomNode& layer_node ) if ( ok && ( bandNo > 0 ) && ( bandNo <= mDataProvider->bandCount() ) ) { mDataProvider->setUseSrcNoDataValue( bandNo, bandElement.attribute( "useSrcNoData" ).toInt() ); - QList myNoDataRangeList; + QgsRasterRangeList myNoDataRangeList; QDomNodeList rangeList = bandElement.elementsByTagName( "noDataRange" ); for ( int j = 0; j < rangeList.size(); ++j ) { QDomElement rangeElement = rangeList.at( j ).toElement(); - QgsRasterBlock::Range myNoDataRange; - myNoDataRange.min = rangeElement.attribute( "min" ).toDouble(); - myNoDataRange.max = rangeElement.attribute( "max" ).toDouble(); - QgsDebugMsg( QString( "min = %1 %2" ).arg( rangeElement.attribute( "min" ) ).arg( myNoDataRange.min ) ); + QgsRasterRange myNoDataRange( rangeElement.attribute( "min" ).toDouble(), + rangeElement.attribute( "max" ).toDouble() ); + QgsDebugMsg( QString( "min = %1 %2" ).arg( rangeElement.attribute( "min" ) ).arg( myNoDataRange.min() ) ); myNoDataRangeList << myNoDataRange; } mDataProvider->setUserNoDataValue( bandNo, myNoDataRangeList ); @@ -2575,12 +2575,12 @@ bool QgsRasterLayer::writeXml( QDomNode & layer_node, noDataRangeList.setAttribute( "bandNo", bandNo ); noDataRangeList.setAttribute( "useSrcNoData", mDataProvider->useSrcNoDataValue( bandNo ) ); - foreach ( QgsRasterBlock::Range range, mDataProvider->userNoDataValue( bandNo ) ) + foreach ( QgsRasterRange range, mDataProvider->userNoDataValue( bandNo ) ) { QDomElement noDataRange = document.createElement( "noDataRange" ); - noDataRange.setAttribute( "min", range.min ); - noDataRange.setAttribute( "max", range.max ); + noDataRange.setAttribute( "min", range.min() ); + noDataRange.setAttribute( "max", range.max() ); noDataRangeList.appendChild( noDataRange ); } diff --git a/src/core/raster/qgsrasterrange.cpp b/src/core/raster/qgsrasterrange.cpp new file mode 100644 index 00000000000..4a06ce685ed --- /dev/null +++ b/src/core/raster/qgsrasterrange.cpp @@ -0,0 +1,51 @@ +/*************************************************************************** + qgsrasterrange.h + -------------------------------------- + Date : Oct 9, 2012 + Copyright : (C) 2012 by Radim Blazek + email : radim dot blazek at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include +#include "qgis.h" +#include "qgsrasterrange.h" + +QgsRasterRange::QgsRasterRange() + : mMin ( std::numeric_limits::quiet_NaN() ) + , mMax ( std::numeric_limits::quiet_NaN() ) +{ +} + +QgsRasterRange::QgsRasterRange( double theMin, double theMax ) + : mMin ( theMin ) + , mMax ( theMax ) +{ +} + +QgsRasterRange::~QgsRasterRange() +{ +} + +bool QgsRasterRange::contains( double value, const QgsRasterRangeList &rangeList ) +{ + foreach ( QgsRasterRange::QgsRasterRange range, rangeList ) + { + if (( value >= range.mMin && value <= range.mMax ) || + doubleNear( value, range.mMin ) || + doubleNear( value, range.mMax ) ) + { + return true; + } + } + return false; +} + diff --git a/src/core/raster/qgsrasterrange.h b/src/core/raster/qgsrasterrange.h new file mode 100644 index 00000000000..32c4b8dc0f2 --- /dev/null +++ b/src/core/raster/qgsrasterrange.h @@ -0,0 +1,72 @@ +/*************************************************************************** + qgsrasterrange.h + -------------------------------------- + Date : Oct 9, 2012 + Copyright : (C) 2012 by Radim Blazek + email : radim dot blazek at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSRASTERRANGE_H +#define QGSRASTERRANGE_H + +#include + +class QgsRasterRange; + +typedef QList QgsRasterRangeList; + +/** \ingroup core + * Raster values range container. Represents range of values between min and max + * including min and max value. + */ +class CORE_EXPORT QgsRasterRange +{ + public: + /** \brief Constructor. + */ + QgsRasterRange(); + + /** \brief Constructor + * @param theMin minimum value + * @param theMax max value + */ + QgsRasterRange( double theMin, double theMax ); + + ~QgsRasterRange(); + + double min() const { return mMin; } + double max() const { return mMax; } + + double setMin( double theMin ) { return mMin = theMin; } + double setMax( double theMax ) { return mMax = theMax; } + + inline bool operator==( const QgsRasterRange &o ) const + { + return mMin == o.mMin && mMax == o.mMax; + } + + /** \brief Test if value is within the list of ranges + * @param value value + * @param rangeList list of ranges + * @return true if value is in at least one of ranges + * @note not available in python bindings + */ + static bool contains( double value, const QgsRasterRangeList &rangeList ); + + private: + double mMin; + double mMax; +}; + +#endif + + diff --git a/src/providers/grass/qgsgrassrasterprovider.cpp b/src/providers/grass/qgsgrassrasterprovider.cpp index 57fa7a6525d..0e770e401e7 100644 --- a/src/providers/grass/qgsgrassrasterprovider.cpp +++ b/src/providers/grass/qgsgrassrasterprovider.cpp @@ -468,8 +468,8 @@ QgsRasterIdentifyResult QgsGrassRasterProvider::identify( const QgsPoint & thePo if ( qIsNaN( value ) ) value = noDataValue( 1 ); // Apply user no data - QList myNoDataRangeList = userNoDataValue( 1 ); - if ( QgsRasterBlock::valueInRange( value, myNoDataRangeList ) ) + QgsRasterRangeList myNoDataRangeList = userNoDataValue( 1 ); + if ( QgsRasterRange::contains( value, myNoDataRangeList ) ) { value = noDataValue( 1 ); } diff --git a/src/providers/wcs/qgswcsprovider.cpp b/src/providers/wcs/qgswcsprovider.cpp index da580a80ff2..b2a75c728c5 100644 --- a/src/providers/wcs/qgswcsprovider.cpp +++ b/src/providers/wcs/qgswcsprovider.cpp @@ -1695,8 +1695,8 @@ QgsRasterIdentifyResult QgsWcsProvider::identify( const QgsPoint & thePoint, Ide } // Apply user no data - QList myNoDataRangeList = userNoDataValue( i ); - if ( QgsRasterBlock::valueInRange( value, myNoDataRangeList ) ) + QgsRasterRangeList myNoDataRangeList = userNoDataValue( i ); + if ( QgsRasterRange::contains( value, myNoDataRangeList ) ) { value = noDataValue( i ); }