qgis / QGIS

QGIS is a free, open source, cross platform (lin/win/mac) geographical information system (GIS)
https://qgis.org
GNU General Public License v2.0
10.49k stars 2.99k forks source link

[processing] Unconsistent expression evaluation in modeler (conditional branch alg) #39119

Open luipir opened 4 years ago

luipir commented 4 years ago

Describe the bug I'm looking a way to execute a model depending if input is set or not (e.g. using conditional branch). But seems that expression is not correctly evaluated and is evaluated in a differ way respect expression condition in e.g. raise exception algorithm

tests_conditiona_branch_issues.zip

How to Reproduce

  1. Load attached algoritm that has a layer as OPTIONAL input
  2. run the algorithm without setting input layer result in:

Condition input is empty passed <- conditional branch OK Condition input is not empty failed <- conditional branch OK INPUT IS EMPTY: 1 <- conditional raise exception OK

  1. run the algorithm, this time, setting a input layer result in:

Condition input is empty passed <- conditional branch !!! NOT OK !!! Condition input is not empty failed <- conditional branch !!! NOT OK !!! INPUT IS NOT EMPTY: 1 <- conditional raise exception OK

  1. See error -->

QGIS and OS versions

QGIS version 3.15.0-Master QGIS code revision 5cd5922f5a
Compiled against Qt 5.9.5 Running against Qt 5.9.5
Compiled against GDAL/OGR 2.2.3 Running against GDAL/OGR 2.2.3
Compiled against GEOS 3.7.1-CAPI-1.11.1 Running against GEOS 3.7.1-CAPI-1.11.1 27a5e771
Compiled against SQLite 3.22.0 Running against SQLite 3.22.0
PostgreSQL Client Version 12.4 (Ubuntu 12.4-1.pgdg18.04+1) SpatiaLite Version 4.3.0a
QWT Version 6.1.3 QScintilla2 Version 2.10.2
PROJ.4 Version 493
OS Version Ubuntu 18.04.5 LTS This copy of QGIS writes debugging output.
Active python plugins plugin_reloader; IPyConsole; pluginbuilder3; copernicushub; firstaid; processing_workflow; epyris; db_manager; processing; MetaSearch

Additional context

None

luipir commented 4 years ago

FYI @andreasneumann this is one of features you financed to @nyalldawson in https://github.com/qgis/QGIS/pull/35808

luipir commented 4 years ago

temporally used a workaround using "Set Project Variable" where I can use an expression where setting a project variable depending if a input is set or not. Then I've a custom funcion that get the value of the project variable and use this function in the conditional branch expression where it works. Note for me: Would be better use scoped variables

nyalldawson commented 4 years ago

Actually not a bug, well, not a bug in processing at least! The "input()" function used here only retrieves the direct parameter values for each child algorithm, NOT for the model inputs. To access those you'd use the direct "@...." variables, in this case: "@input" (gets confusing here cos of the parameter name!!)

But in this case @input is a QgsMapLayer value, and the expression ( @input <> '' ) AND ( @input IS NOT NULL ) does not handle the case when @input is a map layer. So the bug here is that the expression engine isn't correctly comparing QgsMapLayer values, but that's debatable of whether it SHOULD or not!!

luipir commented 4 years ago

but that's debatable of whether it SHOULD or not!!

I understand... the use case a way to check mutual exclusive parameters that have polymorphic nature (from the user point of view) e.g. an extent is can be get from a layer, from an extent as from a wkt e.g. a layer can be a name string, a id string, a source string, a real map layer

not clear to me what would be the solution... a new operator, extend accepted types of current operator and comparing with what value?

PedroVenancio commented 3 years ago

Hi @nyalldawson and @luipir

I'm trying to use a Raise Exception to check if a polygon has an area greater than 175000 ha and stop if it's true.

The input layer is in a Vector Feature Parameter, called 'Area de Trabalho'.

So, if in the Pre-Calculated Value Condition of Raise Exception I use:

'((area(geometry( get_feature_by_id( @AreadeTrabalho , 1)))) / 10000) > 175000'

it stops when area is greater than 175000 ha.

However, this only works if the input has only one polygon.

So, I would like to make first a dissolve to @AreadeTrabalho and then run the Raise Exception with Condition:

'((area(geometry( get_feature_by_id( @Dissolve_OUTPUT , 1)))) / 10000) > 175000'

But this way it does not work, it passes, even if the condition is true.

So, the Raise Exception only works if the "input" layer referenced is an Input (Vector Feature or Vector Layer Parameter)? Or it is possible to reference an Output of an algorithm?

nyalldawson commented 3 years ago

@PedroVenancio The expression functions which reference layers by name or ID don't work well with models at the moment -- they'll only give results if the layer has been loaded into the project BEFORE the model is run, and can't be used with any intermediate outputs.

PedroVenancio commented 3 years ago

Oh ok, it's that then.

Thank you very much @nyalldawson !

aldenln commented 2 years ago

Hey @luipir @nyalldawson and @PedroVenancio

how do you then evaluate the intermediate result of an algorithm in the model builder?

In my case, I would like to evaluate if the algorithm's result has any features before saving the file to disk.

Any suggestion?