Skip to content

Commit

Permalink
Improved raster singleband pseudocolor classification GUI
Browse files Browse the repository at this point in the history
  • Loading branch information
blazek committed Dec 18, 2012
1 parent 7a82041 commit 9fce669
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 49 deletions.
4 changes: 4 additions & 0 deletions python/core/symbology-ng/qgsvectorcolorrampv2.sip
Expand Up @@ -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;
Expand Down
17 changes: 10 additions & 7 deletions src/core/raster/qgscolorrampshader.cpp
Expand Up @@ -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();
Expand Down
6 changes: 6 additions & 0 deletions src/core/raster/qgscolorrampshader.h
Expand Up @@ -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;
Expand Down Expand Up @@ -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
2 changes: 2 additions & 0 deletions src/core/raster/qgsrastershader.cpp
Expand Up @@ -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();
Expand All @@ -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;
Expand Down
28 changes: 28 additions & 0 deletions src/core/symbology-ng/qgsvectorcolorrampv2.cpp
Expand Up @@ -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() )
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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 )
Expand Down
18 changes: 16 additions & 2 deletions src/core/symbology-ng/qgsvectorcolorrampv2.h
Expand Up @@ -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;
Expand All @@ -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 ) { }
};
Expand All @@ -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"; }
Expand Down Expand Up @@ -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"; }
Expand Down Expand Up @@ -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"; }
Expand All @@ -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(); }
Expand Down Expand Up @@ -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();
Expand Down
3 changes: 3 additions & 0 deletions src/gui/raster/qgsrasterminmaxwidget.h
Expand Up @@ -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 );

Expand Down
52 changes: 48 additions & 4 deletions src/gui/raster/qgssinglebandpseudocolorrendererwidget.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}

Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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() );
Expand Down
8 changes: 8 additions & 0 deletions src/gui/raster/qgssinglebandpseudocolorrendererwidget.h
Expand Up @@ -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();

Expand Down Expand Up @@ -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 );
Expand Down

0 comments on commit 9fce669

Please sign in to comment.