Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] create_ramp() expression function #4632

Merged
merged 2 commits into from May 29, 2017
Merged

Conversation

nirvn
Copy link
Contributor

@nirvn nirvn commented May 26, 2017

Description

This PR adds a useful expression function to create color ramps from scratch. It can be quite useful when a project in shared among many users as it does not rely on the presence of a saved ramp (let alone having that ramp having the same colors).

It's also simply useful to be able to quickly create ramps within expressions 馃槃

Checklist

Reviewing is a process done by project maintainers, mostly on a volunteer basis. We try to keep the overhead as small as possible and appreciate if you help us to do so by completing the following items. Feel free to ask in a comment if you have troubles with any of them.

  • Commit messages are descriptive and explain the rationale for changes
  • Commits which fix bugs include fixes #11111 in the commit message next to the description
  • Commits which add new features are tagged with [FEATURE] in the commit message
  • Commits which change the UI or existing user workflows are tagged with [needs-docs] in the commit message and containt sufficient information in the commit message to be documented
  • I have read the QGIS Coding Standards and this PR complies with them
  • This PR passes all existing unit tests (test results will be reported by travis-ci after opening this PR)
  • New unit tests have been added for core changes
  • I have run the scripts/prepare-commit.sh script before each commit

@nirvn
Copy link
Contributor Author

nirvn commented May 26, 2017

@nyalldawson , review appreciated.

@nirvn
Copy link
Contributor Author

nirvn commented May 26, 2017

Here's a practical example that can be achieved with this new function: graduate a polygon fill based on a numerical field against the field's maximum value: ramp_color(create_ramp(map(0,'255,255,255',1,'199,33,33')),scale_linear("my_field",0,maximum("my_field"),0,1))

@nyalldawson
Copy link
Collaborator

Looks good to me! My only thought - having a single function for both creation of the ramp AND retrieving a color from it is going to be inefficient for large number of calculations. If the functions were instead split into two separate functions then the ramp creation function would be considered static and compiled once (thanks for @m-kuhn's recent optimisations), meaning only one ramp creation instead of 1000s...

@nirvn
Copy link
Contributor Author

nirvn commented May 29, 2017

@nyalldawson , yeah , I thought of that too, but initially I was not warm to the idea of introducing a new type of returned value in the expression engine (ie, a "ramp" value/object).

@nyalldawson
Copy link
Collaborator

@nyalldawson , yeah , I thought of that too, but initially I was not warm to the idea of introducing a new type of returned value in the expression engine (ie, a "ramp" value/object).

I understand that. However - there's also a good benefit of having ramps as a datatype. At the moment if you use the color property assistant and set a property to get its value from a custom ramp, there's no way to map this across to an expression function. We need some way to store custom ramps in expression functions to allow this. So this change would also benefit that use case...

@nirvn
Copy link
Contributor Author

nirvn commented May 29, 2017

@nyalldawson , OK, following your request, I've updated this PR to allow for creation of ramps within the expression engine. The create_ramp() function creates a ramp, which can be used by the pre-existing ramp_color(). The latter was updated to take as its first parameter a ramp object in addition to a saved ramp name string.

The create_ramp() has two parameters: a required map() parameter, and an optional discrete boolean. This allows us to re-create all variants of the QgsGradientColorRamp ramp type. For e.g.:

  • create_ramp(map(0,'0,0,0',0.25,'255,0,0',1,'255,255,255'))
  • create_ramp(map(0,'0,0,0',0.5,'255,0,0'),true)
  • etc.

This practical example shows how a user can retrieve a color for a expression-created ramp:
ramp_color(create_ramp(map(0,'0,0,0',1,'255,0,0')),0.5)

The above would return '128,0,0,255'.

@nirvn nirvn changed the title [FEATURE] array_ramp_color() expression function [FEATURE] create_ramp() expression function May 29, 2017
const QgsColorRamp *mRamp = QgsStyle::defaultStyle()->colorRampRef( rampName );
if ( ! mRamp )
QgsGradientColorRamp expRamp;
const QgsColorRamp *mRamp;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be just ramp, not mRamp

if ( ! mRamp )
{
parent->setEvalErrorString( QObject::tr( "\"%1\" is not a valid color ramp" ).arg( rampName ) );
return QColor( 0, 0, 0 ).name();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is odd - i think it should return QVariant() instead

@@ -1010,6 +1010,8 @@ class TestQgsExpression: public QObject

// Color functions
QTest::newRow( "ramp color" ) << "ramp_color('Spectral',0.3)" << false << QVariant( "254,190,116,255" );
QTest::newRow( "create ramp color, two colors" ) << "ramp_color(create_ramp(map('0,0,0','255,0,0')),0.33)" << false << QVariant( "84,0,0,255" );
QTest::newRow( "create ramp color, three colors" ) << "ramp_color(create_ramp(map('0,0,0','0,255,0','0,0,255','255,0,0')),0.5)" << false << QVariant( "0,127,128,255" );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need some tests here for bad parameters - e.g. 0 stops, 1 stop, non-map values

@nyalldawson
Copy link
Collaborator

Looks good! Just some minor suggestions.

Also - should we explicitly say that this is a gradient ramp creator, in case we want to allow random/etc ramp creation functions in future?

@nirvn
Copy link
Contributor Author

nirvn commented May 29, 2017

@nyalldawson , as in updating the function name or adding a note in the documentation?

@nyalldawson
Copy link
Collaborator

I think just documentation

@nirvn nirvn force-pushed the array_ramp_color branch 2 times, most recently from 5e9d9ac to f7e78ee Compare May 29, 2017 07:04
@nirvn
Copy link
Contributor Author

nirvn commented May 29, 2017

@nyalldawson , your comments were all addressed. Thanks

{
"name": "create_ramp",
"type": "function",
"description": "Returns a gradient ramp from a an map of color strings and steps.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a an map

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oups, used to be an array -- thanks for spotting this.


// If we get here then we can't convert so we just error and return invalid.
if ( report_error )
parent->setEvalErrorString( QObject::tr( "Cannot convert '%1' to QgsGradientColorRamp" ).arg( value.toString() ) );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would the end user understand what QgsGradientColorRamp is?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DelazJ , trying to stick to what was established elsewhere (see getGeometry(), getFeature()).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should be fixed too - we shouldn't expose the class names to users. By the way - QgsExpression::formatPreviewString will need to be updated to show ramps too.

@nirvn
Copy link
Contributor Author

nirvn commented May 29, 2017

@DelazJ , QgsGradientColorRamp renamed to "gradient ramp".

@nyalldawson , QgsExpression::formatPreviewString updated, thanks for pointing this out.

@nirvn nirvn merged commit d996cf2 into qgis:master May 29, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants