QgsRasterBlock::Range to QgsRasterRange

This commit is contained in:
Radim Blazek 2013-04-10 18:58:19 +02:00
parent a7e1d40e8a
commit 094a5d8275
17 changed files with 212 additions and 89 deletions

View File

@ -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

View File

@ -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<QgsRasterBlock::Range> &rangeList );
};

View File

@ -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<QgsRasterBlock::Range> noData );
virtual void setUserNoDataValue( int bandNo, QgsRasterRangeList noData );
/** Get list of user no data value ranges */
virtual QList<QgsRasterBlock::Range> userNoDataValue( int bandNo ) const;
virtual QgsRasterRangeList userNoDataValue( int bandNo ) const;
virtual double minimumValue( int bandNo ) const;
virtual double maximumValue( int bandNo ) const;

View File

@ -25,8 +25,5 @@ class QgsRasterIdentifyResult
QgsError error() const;
void setError( const QgsError & theError );
void appendError( const QgsErrorMessage & theMessage );
};

View File

@ -0,0 +1,25 @@
typedef QList<QgsRasterRange> QgsRasterRangeList;
class QgsRasterRange
{
%TypeHeaderCode
#include <qgsrasterrange.h>
%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 );
};

View File

@ -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<QgsRasterBlock::Range> 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<QgsRasterBlock::Range> 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;
}
}

View File

@ -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

View File

@ -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<double>::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<Range>& rangeList )
void QgsRasterBlock::applyNodataValues( const QgsRasterRangeList & rangeList )
{
if ( rangeList.isEmpty() )
{
@ -421,7 +421,7 @@ void QgsRasterBlock::applyNodataValues( const QList<Range>& 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 );
}

View File

@ -21,26 +21,17 @@
#include <limits>
#include <QImage>
#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<QgsRasterBlock::Range> &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<Range>& 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<QgsRasterBlock::Range> &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 )

View File

@ -507,14 +507,14 @@ double QgsRasterDataProvider::readValue( void *data, int type, int index )
}
#endif
void QgsRasterDataProvider::setUserNoDataValue( int bandNo, QList<QgsRasterBlock::Range> 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<QgsRasterBlock::Range>() );
mUserNoDataValue.append( QgsRasterRangeList() );
}
}
QgsDebugMsg( QString( "set %1 band %1 no data ranges" ).arg( noData.size() ) );

View File

@ -35,6 +35,7 @@
#include "qgscoordinatereferencesystem.h"
#include "qgsrasterbandstats.h"
#include "qgsrasterhistogram.h"
#include "qgsrasterrange.h"
#include "cpl_conv.h"
#include <cmath>
@ -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<QgsRasterBlock::Range> noData );
virtual void setUserNoDataValue( int bandNo, QgsRasterRangeList noData );
/** Get list of user no data value ranges */
virtual QList<QgsRasterBlock::Range> 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<QgsRasterBlock::Range> > mUserNoDataValue;
QList< QgsRasterRangeList > mUserNoDataValue;
QgsRectangle mExtent;

View File

@ -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<int, QVariant> results() const { return mResults; }
QMap<int, QVariant> results() const { return mResults; }
/** Set map of optional parameters */
void setParams( const QMap<QString, QVariant> & 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;

View File

@ -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<QgsRasterBlock::Range> 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 );
}

View File

@ -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 <limits>
#include "qgis.h"
#include "qgsrasterrange.h"
QgsRasterRange::QgsRasterRange()
: mMin ( std::numeric_limits<double>::quiet_NaN() )
, mMax ( std::numeric_limits<double>::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;
}

View File

@ -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 <QList>
class QgsRasterRange;
typedef QList<QgsRasterRange> 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

View File

@ -468,8 +468,8 @@ QgsRasterIdentifyResult QgsGrassRasterProvider::identify( const QgsPoint & thePo
if ( qIsNaN( value ) ) value = noDataValue( 1 );
// Apply user no data
QList<QgsRasterBlock::Range> myNoDataRangeList = userNoDataValue( 1 );
if ( QgsRasterBlock::valueInRange( value, myNoDataRangeList ) )
QgsRasterRangeList myNoDataRangeList = userNoDataValue( 1 );
if ( QgsRasterRange::contains( value, myNoDataRangeList ) )
{
value = noDataValue( 1 );
}

View File

@ -1695,8 +1695,8 @@ QgsRasterIdentifyResult QgsWcsProvider::identify( const QgsPoint & thePoint, Ide
}
// Apply user no data
QList<QgsRasterBlock::Range> myNoDataRangeList = userNoDataValue( i );
if ( QgsRasterBlock::valueInRange( value, myNoDataRangeList ) )
QgsRasterRangeList myNoDataRangeList = userNoDataValue( i );
if ( QgsRasterRange::contains( value, myNoDataRangeList ) )
{
value = noDataValue( i );
}