Permalink
Browse files

Improved raster singleband pseudocolor classification GUI

  • Loading branch information...
1 parent 7a82041 commit 9fce669ba20529ce9822268268cb0e5b4cf73300 @blazek blazek committed Dec 18, 2012
@@ -16,6 +16,10 @@ class QgsVectorColorRampV2
public:
virtual ~QgsVectorColorRampV2();
+ virtual int count() const = 0;
+
+ virtual double value( int index ) const = 0;
+
virtual QColor color( double value ) const = 0;
virtual QString type() const = 0;
@@ -169,22 +169,25 @@ bool QgsColorRampShader::interpolatedColor( double theValue, int*
QgsColorRampShader::ColorRampItem myPreviousColorRampItem = mColorRampItemList.value( mCurrentColorRampItemIndex - 1 );
myCurrentRampRange = myColorRampItem.value - myPreviousColorRampItem.value;
myOffsetInRange = theValue - myPreviousColorRampItem.value;
+ double scale = myOffsetInRange / myCurrentRampRange;
- *theReturnRedValue = ( int )(( double ) myPreviousColorRampItem.color.red() + ((( double )( myColorRampItem.color.red() - myPreviousColorRampItem.color.red() ) / myCurrentRampRange ) * myOffsetInRange ) );
- *theReturnGreenValue = ( int )(( double ) myPreviousColorRampItem.color.green() + ((( double )( myColorRampItem.color.green() - myPreviousColorRampItem.color.green() ) / myCurrentRampRange ) * myOffsetInRange ) );
- *theReturnBlueValue = ( int )(( double ) myPreviousColorRampItem.color.blue() + ((( double )( myColorRampItem.color.blue() - myPreviousColorRampItem.color.blue() ) / myCurrentRampRange ) * myOffsetInRange ) );
+ *theReturnRedValue = ( int )(( double ) myPreviousColorRampItem.color.red() + (( double )( myColorRampItem.color.red() - myPreviousColorRampItem.color.red() ) * scale ) ) ;
+ *theReturnGreenValue = ( int )(( double ) myPreviousColorRampItem.color.green() + (( double )( myColorRampItem.color.green() - myPreviousColorRampItem.color.green() ) * scale ) );
+ *theReturnBlueValue = ( int )(( double ) myPreviousColorRampItem.color.blue() + (( double )( myColorRampItem.color.blue() - myPreviousColorRampItem.color.blue() ) * scale ) );
if ( mMaximumColorCacheSize >= mColorCache.size() )
{
QColor myNewColor( *theReturnRedValue, *theReturnGreenValue, *theReturnBlueValue );
mColorCache.insert( theValue, myNewColor );
}
return true;
}
- else if ( mCurrentColorRampItemIndex == 0 && theValue <= myColorRampItem.value )
+ // Values outside total range are rendered if mClip is false
+ else if (( mCurrentColorRampItemIndex == 0 && ( myTinyDiff <= DOUBLE_DIFF_THRESHOLD || ( !mClip && theValue <= myColorRampItem.value ) ) )
+ || ( mCurrentColorRampItemIndex == myColorRampItemCount - 1 && ( myTinyDiff <= DOUBLE_DIFF_THRESHOLD || ( !mClip && theValue >= myColorRampItem.value ) ) ) )
{
- QgsColorRampShader::ColorRampItem myPreviousColorRampItem = mColorRampItemList.value( mCurrentColorRampItemIndex - 1 );
- myCurrentRampRange = myColorRampItem.value - myPreviousColorRampItem.value;
- myOffsetInRange = theValue - myPreviousColorRampItem.value;
+ //QgsColorRampShader::ColorRampItem myPreviousColorRampItem = mColorRampItemList.value( mCurrentColorRampItemIndex - 1 );
+ //myCurrentRampRange = myColorRampItem.value - myPreviousColorRampItem.value;
+ //myOffsetInRange = theValue - myPreviousColorRampItem.value;
*theReturnRedValue = myColorRampItem.color.red();
*theReturnGreenValue = myColorRampItem.color.green();
@@ -93,6 +93,9 @@ class CORE_EXPORT QgsColorRampShader : public QgsRasterShaderFunction
void legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const;
+ void setClip( bool clip ) { mClip = clip; }
+ bool clip() const { return mClip; }
+
private:
/** Current index from which to start searching the color table*/
int mCurrentColorRampItemIndex;
@@ -129,6 +132,9 @@ class CORE_EXPORT QgsColorRampShader : public QgsRasterShaderFunction
* mValueClassification. Interpolates the color between two class breaks
* linearly.*/
bool interpolatedColor( double, int*, int*, int* );
+
+ /** Do not render values out of range */
+ bool mClip;
};
#endif
@@ -140,6 +140,7 @@ void QgsRasterShader::writeXML( QDomDocument& doc, QDomElement& parent ) const
{
QDomElement colorRampShaderElem = doc.createElement( "colorrampshader" );
colorRampShaderElem.setAttribute( "colorRampType", colorRampShader->colorRampTypeAsQString() );
+ colorRampShaderElem.setAttribute( "clip", colorRampShader->clip() );
//items
QList<QgsColorRampShader::ColorRampItem> itemList = colorRampShader->colorRampItemList();
QList<QgsColorRampShader::ColorRampItem>::const_iterator itemIt = itemList.constBegin();
@@ -164,6 +165,7 @@ void QgsRasterShader::readXML( const QDomElement& elem )
{
QgsColorRampShader* colorRampShader = new QgsColorRampShader();
colorRampShader->setColorRampType( colorRampShaderElem.attribute( "colorRampType", "INTERPOLATED" ) );
+ colorRampShader->setClip( colorRampShaderElem.attribute( "clip", "0" ) == "1" );
QList<QgsColorRampShader::ColorRampItem> itemList;
QDomElement itemElem;
@@ -91,6 +91,22 @@ QgsVectorColorRampV2* QgsVectorGradientColorRampV2::create( const QgsStringMap&
return r;
}
+double QgsVectorGradientColorRampV2::value( int index ) const
+{
+ if ( index <= 0 )
+ {
+ return 0;
+ }
+ else if ( index >= mStops.size() + 1 )
+ {
+ return 1;
+ }
+ else
+ {
+ return mStops[index-1].offset;
+ }
+}
+
QColor QgsVectorGradientColorRampV2::color( double value ) const
{
if ( mStops.isEmpty() )
@@ -232,6 +248,12 @@ QgsVectorColorRampV2* QgsVectorRandomColorRampV2::create( const QgsStringMap& pr
return new QgsVectorRandomColorRampV2( count, hueMin, hueMax, satMin, satMax, valMin, valMax );
}
+double QgsVectorRandomColorRampV2::value( int index ) const
+{
+ if ( mColors.size() < 1 ) return 0;
+ return index / mColors.size() - 1;
+}
+
QColor QgsVectorRandomColorRampV2::color( double value ) const
{
int colorCnt = mColors.count();
@@ -312,6 +334,12 @@ QList<int> QgsVectorColorBrewerColorRampV2::listSchemeVariants( QString schemeNa
return QgsColorBrewerPalette::listSchemeVariants( schemeName );
}
+double QgsVectorColorBrewerColorRampV2::value( int index ) const
+{
+ if ( mPalette.size() < 1 ) return 0;
+ return index / mPalette.size() - 1;
+}
+
QColor QgsVectorColorBrewerColorRampV2::color( double value ) const
{
if ( mPalette.isEmpty() || value < 0 || value > 1 )
@@ -26,6 +26,12 @@ class CORE_EXPORT QgsVectorColorRampV2
public:
virtual ~QgsVectorColorRampV2() {}
+ // Number of defined colors
+ virtual int count() const = 0;
+
+ // Relative value (0,1) of color at index
+ virtual double value( int index ) const = 0;
+
virtual QColor color( double value ) const = 0;
virtual QString type() const = 0;
@@ -38,7 +44,7 @@ class CORE_EXPORT QgsVectorColorRampV2
struct QgsGradientStop
{
- double offset;
+ double offset; // relative (0,1)
QColor color;
QgsGradientStop( double o, const QColor& c ) : offset( o ), color( c ) { }
};
@@ -58,6 +64,10 @@ class CORE_EXPORT QgsVectorGradientColorRampV2 : public QgsVectorColorRampV2
static QgsVectorColorRampV2* create( const QgsStringMap& properties = QgsStringMap() );
+ virtual int count() const { return mStops.count() + 2; }
+
+ virtual double value( int index ) const;
+
virtual QColor color( double value ) const;
virtual QString type() const { return "gradient"; }
@@ -106,6 +116,8 @@ class CORE_EXPORT QgsVectorRandomColorRampV2 : public QgsVectorColorRampV2
static QgsVectorColorRampV2* create( const QgsStringMap& properties = QgsStringMap() );
+ virtual double value( int index ) const;
+
virtual QColor color( double value ) const;
virtual QString type() const { return "random"; }
@@ -150,6 +162,8 @@ class CORE_EXPORT QgsVectorColorBrewerColorRampV2 : public QgsVectorColorRampV2
static QgsVectorColorRampV2* create( const QgsStringMap& properties = QgsStringMap() );
+ virtual double value( int index ) const;
+
virtual QColor color( double value ) const;
virtual QString type() const { return "colorbrewer"; }
@@ -159,6 +173,7 @@ class CORE_EXPORT QgsVectorColorBrewerColorRampV2 : public QgsVectorColorRampV2
virtual QgsStringMap properties() const;
QString schemeName() const { return mSchemeName; }
+ virtual int count() const { return mColors; }
int colors() const { return mColors; }
void setSchemeName( QString schemeName ) { mSchemeName = schemeName; loadPalette(); }
@@ -212,7 +227,6 @@ class CORE_EXPORT QgsCptCityColorRampV2 : public QgsVectorGradientColorRampV2
void loadPalette() { loadFile(); }
bool hasMultiStops() const { return mMultiStops; }
- int count() const { return mStops.count() + 2; }
QString fileName() const;
bool loadFile();
@@ -33,6 +33,9 @@ class GUI_EXPORT QgsRasterMinMaxWidget: public QWidget, private Ui::QgsRasterMin
void setBands( const QList<int> & theBands ) { mBands = theBands; }
+ // Load programmaticaly with current values
+ void load() { on_mLoadPushButton_clicked(); }
+
signals:
void load( int theBandNo, double theMin, double theMax, int origin );
@@ -32,12 +32,19 @@
QgsSingleBandPseudoColorRendererWidget::QgsSingleBandPseudoColorRendererWidget( QgsRasterLayer* layer, const QgsRectangle &extent ):
QgsRasterRendererWidget( layer, extent )
{
+ QSettings settings;
+
setupUi( this );
mColormapTreeWidget->setColumnWidth( 1, 50 );
+ QString defaultPalette = settings.value( "/Raster/defaultPalette", "Spectral" ).toString();
+
mColorRampComboBox->populate( QgsStyleV2::defaultStyle() );
+ QgsDebugMsg( "defaultPalette = " + defaultPalette );
+ mColorRampComboBox->setCurrentIndex( mColorRampComboBox->findText( defaultPalette ) );
+
if ( !mRasterLayer )
{
return;
@@ -74,13 +81,22 @@ QgsSingleBandPseudoColorRendererWidget::QgsSingleBandPseudoColorRendererWidget(
mColorInterpolationComboBox->addItem( tr( "Linear" ), 1 );
mColorInterpolationComboBox->addItem( tr( "Exact" ), 2 );
mColorInterpolationComboBox->setCurrentIndex( 1 );
- mClassificationModeComboBox->addItem( tr( "Equal interval" ) );
+ mClassificationModeComboBox->addItem( tr( "Continuous" ), Continuous );
+ mClassificationModeComboBox->addItem( tr( "Equal interval" ), EqualInterval );
//quantile would be nice as well
mNumberOfEntriesSpinBox->setValue( 5 ); // some default
setFromRenderer( layer->renderer() );
+ // If there is currently no min/max, load default with user current default options
+ if ( mMinLineEdit->text().isEmpty() || mMaxLineEdit->text().isEmpty() )
+ {
+ mMinMaxWidget->load();
+ }
+
+ on_mClassificationModeComboBox_currentIndexChanged( 0 );
+
resetClassifyButton();
}
@@ -92,6 +108,7 @@ QgsRasterRenderer* QgsSingleBandPseudoColorRendererWidget::renderer()
{
QgsRasterShader* rasterShader = new QgsRasterShader();
QgsColorRampShader* colorRampShader = new QgsColorRampShader();
+ colorRampShader->setClip( mClipCheckBox->isChecked() );
//iterate through mColormapTreeWidget and set colormap info of layer
QList<QgsColorRampShader::ColorRampItem> colorRampItems;
@@ -217,16 +234,31 @@ void QgsSingleBandPseudoColorRendererWidget::on_mClassifyButton_clicked()
//int bandNr = mBandComboBox->itemData( bandComboIndex ).toInt();
//QgsRasterBandStats myRasterBandStats = mRasterLayer->dataProvider()->bandStatistics( bandNr );
- int numberOfEntries = mNumberOfEntriesSpinBox->value();
+ int numberOfEntries = 0;
QList<double> entryValues;
QList<QColor> entryColors;
double min = lineEditValue( mMinLineEdit );
double max = lineEditValue( mMaxLineEdit );
- if ( mClassificationModeComboBox->currentText() == tr( "Equal interval" ) )
+ QgsVectorColorRampV2* colorRamp = mColorRampComboBox->currentColorRamp();
+
+ if ( mClassificationModeComboBox->itemData( mClassificationModeComboBox->currentIndex() ).toInt() == Continuous )
+ {
+ if ( colorRamp )
+ {
+ numberOfEntries = colorRamp->count();
+ for ( int i = 0; i < colorRamp->count(); ++i )
+ {
+ double value = colorRamp->value( i );
+ entryValues.push_back( min + value * ( max - min ) );
+ }
+ }
+ }
+ else // EqualInterval
{
+ numberOfEntries = mNumberOfEntriesSpinBox->value();
//double currentValue = myRasterBandStats.minimumValue;
double currentValue = min;
double intervalDiff;
@@ -265,7 +297,6 @@ void QgsSingleBandPseudoColorRendererWidget::on_mClassifyButton_clicked()
}
#endif
- QgsVectorColorRampV2* colorRamp = mColorRampComboBox->currentColorRamp();
if ( ! colorRamp )
{
//hard code color range from blue -> red (previous default)
@@ -307,6 +338,18 @@ void QgsSingleBandPseudoColorRendererWidget::on_mClassifyButton_clicked()
}
}
+void QgsSingleBandPseudoColorRendererWidget::on_mClassificationModeComboBox_currentIndexChanged( int index )
+{
+ mNumberOfEntriesSpinBox->setEnabled( mClassificationModeComboBox->itemData( index ).toInt() == EqualInterval );
+}
+
+void QgsSingleBandPseudoColorRendererWidget::on_mColorRampComboBox_currentIndexChanged( int index )
+{
+ Q_UNUSED( index );
+ QSettings settings;
+ settings.setValue( "/Raster/defaultPalette", mColorRampComboBox->currentText() );
+}
+
void QgsSingleBandPseudoColorRendererWidget::populateColormapTreeWidget( const QList<QgsColorRampShader::ColorRampItem>& colorRampItems )
{
mColormapTreeWidget->clear();
@@ -545,6 +588,7 @@ void QgsSingleBandPseudoColorRendererWidget::setFromRenderer( const QgsRasterRen
newItem->setBackground( 1, QBrush( it->color ) );
newItem->setText( 2, it->label );
}
+ mClipCheckBox->setChecked( colorRampShader->clip() );
}
}
setLineEditValue( mMinLineEdit, pr->classificationMin() );
@@ -28,6 +28,12 @@ class GUI_EXPORT QgsSingleBandPseudoColorRendererWidget: public QgsRasterRendere
{
Q_OBJECT
public:
+ enum Mode
+ {
+ Continuous = 1, // Using breaks from color palette
+ EqualInterval = 2
+ };
+
QgsSingleBandPseudoColorRendererWidget( QgsRasterLayer* layer, const QgsRectangle &extent = QgsRectangle() );
~QgsSingleBandPseudoColorRendererWidget();
@@ -56,6 +62,8 @@ class GUI_EXPORT QgsSingleBandPseudoColorRendererWidget: public QgsRasterRendere
void on_mMaxLineEdit_textChanged( const QString & text ) { Q_UNUSED( text ); resetClassifyButton(); }
void on_mMinLineEdit_textEdited( const QString & text ) { Q_UNUSED( text ); mMinMaxOrigin = QgsRasterRenderer::MinMaxUser; showMinMaxOrigin(); }
void on_mMaxLineEdit_textEdited( const QString & text ) { Q_UNUSED( text ); mMinMaxOrigin = QgsRasterRenderer::MinMaxUser; showMinMaxOrigin(); }
+ void on_mClassificationModeComboBox_currentIndexChanged( int index );
+ void on_mColorRampComboBox_currentIndexChanged( int index );
private:
void setLineEditValue( QLineEdit *theLineEdit, double theValue );
Oops, something went wrong.

0 comments on commit 9fce669

Please sign in to comment.