To access the input layer in the expression, use the @layer
variable.
To access the id of the feature, use the function $id
.
You can calculate the difference between the x values of the following id feature and the current feature with the following expression:
attribute(
get_feature_by_id(
@layer,
$id + 1),
'x') -
attribute(
$currentfeature,
'x')
Note than the $currentfeature
parameter is not necessary, you can use the attribute('x')
variant.
Here is the model to test the x difference:
<!DOCTYPE model>
<Option type="Map">
<Option type="Map" name="children">
<Option type="Map" name="native:addxyfields_2">
<Option value="true" type="bool" name="active"/>
<Option name="alg_config"/>
<Option value="native:addxyfields" type="QString" name="alg_id"/>
<Option value="Add X/Y fields to KP" type="QString" name="component_description"/>
<Option value="351.7406720872316" type="double" name="component_pos_x"/>
<Option value="504.71744827318093" type="double" name="component_pos_y"/>
<Option name="dependencies"/>
<Option value="native:addxyfields_2" type="QString" name="id"/>
<Option name="outputs"/>
<Option value="false" type="bool" name="outputs_collapsed"/>
<Option value="true" type="bool" name="parameters_collapsed"/>
<Option type="Map" name="params">
<Option type="List" name="CRS">
<Option type="Map">
<Option value="2" type="int" name="source"/>
<Option value="ProjectCrs" type="QString" name="static_value"/>
</Option>
</Option>
<Option type="List" name="INPUT">
<Option type="Map">
<Option value="kppoints" type="QString" name="parameter_name"/>
<Option value="0" type="int" name="source"/>
</Option>
</Option>
<Option type="List" name="PREFIX">
<Option type="Map">
<Option value="2" type="int" name="source"/>
<Option value="" type="QString" name="static_value"/>
</Option>
</Option>
</Option>
</Option>
<Option type="Map" name="qgis:fieldcalculator_1">
<Option value="true" type="bool" name="active"/>
<Option name="alg_config"/>
<Option value="qgis:fieldcalculator" type="QString" name="alg_id"/>
<Option value="Field calculator dx" type="QString" name="component_description"/>
<Option value="526.7406720872316" type="double" name="component_pos_x"/>
<Option value="623.7174482731809" type="double" name="component_pos_y"/>
<Option name="dependencies"/>
<Option value="qgis:fieldcalculator_1" type="QString" name="id"/>
<Option type="Map" name="outputs">
<Option type="Map" name="dx">
<Option value="qgis:fieldcalculator_1" type="QString" name="child_id"/>
<Option value="dx" type="QString" name="component_description"/>
<Option value="716.7406720872316" type="double" name="component_pos_x"/>
<Option value="698.7174482731809" type="double" name="component_pos_y"/>
<Option type="invalid" name="default_value"/>
<Option value="false" type="bool" name="mandatory"/>
<Option value="dx" type="QString" name="name"/>
<Option value="OUTPUT" type="QString" name="output_name"/>
</Option>
</Option>
<Option value="true" type="bool" name="outputs_collapsed"/>
<Option value="true" type="bool" name="parameters_collapsed"/>
<Option type="Map" name="params">
<Option type="List" name="FIELD_LENGTH">
<Option type="Map">
<Option value="2" type="int" name="source"/>
<Option value="0" type="int" name="static_value"/>
</Option>
</Option>
<Option type="List" name="FIELD_NAME">
<Option type="Map">
<Option value="2" type="int" name="source"/>
<Option value="dx" type="QString" name="static_value"/>
</Option>
</Option>
<Option type="List" name="FIELD_PRECISION">
<Option type="Map">
<Option value="2" type="int" name="source"/>
<Option value="0" type="int" name="static_value"/>
</Option>
</Option>
<Option type="List" name="FIELD_TYPE">
<Option type="Map">
<Option value="2" type="int" name="source"/>
<Option value="0" type="int" name="static_value"/>
</Option>
</Option>
<Option type="List" name="FORMULA">
<Option type="Map">
<Option value="2" type="int" name="source"/>
<Option value="attribute(
 get_feature_by_id(
 @layer,
	$id + 1),
 'x') - 
attribute(
 $currentfeature,
 'x') " type="QString" name="static_value"/>
</Option>
</Option>
<Option type="List" name="INPUT">
<Option type="Map">
<Option value="native:addxyfields_2" type="QString" name="child_id"/>
<Option value="OUTPUT" type="QString" name="output_name"/>
<Option value="1" type="int" name="source"/>
</Option>
</Option>
<Option type="List" name="NEW_FIELD">
<Option type="Map">
<Option value="2" type="int" name="source"/>
<Option value="true" type="bool" name="static_value"/>
</Option>
</Option>
</Option>
</Option>
</Option>
<Option name="help"/>
<Option name="modelVariables"/>
<Option value="" type="QString" name="model_group"/>
<Option value="difference_against_next_feature_attribute" type="QString" name="model_name"/>
<Option type="Map" name="parameterDefinitions">
<Option type="Map" name="kppoints">
<Option type="List" name="data_types">
<Option value="0" type="int"/>
</Option>
<Option type="invalid" name="default"/>
<Option value="KP points" type="QString" name="description"/>
<Option value="0" type="int" name="flags"/>
<Option name="metadata"/>
<Option value="kppoints" type="QString" name="name"/>
<Option value="vector" type="QString" name="parameter_type"/>
</Option>
<Option type="Map" name="qgis:fieldcalculator_1:dx">
<Option value="true" type="bool" name="create_by_default"/>
<Option value="-1" type="int" name="data_type"/>
<Option type="invalid" name="default"/>
<Option value="dx" type="QString" name="description"/>
<Option value="0" type="int" name="flags"/>
<Option name="metadata"/>
<Option value="qgis:fieldcalculator_1:dx" type="QString" name="name"/>
<Option value="sink" type="QString" name="parameter_type"/>
<Option value="true" type="bool" name="supports_non_file_outputs"/>
</Option>
</Option>
<Option type="Map" name="parameters">
<Option type="Map" name="kppoints">
<Option value="kppoints" type="QString" name="component_description"/>
<Option value="188" type="double" name="component_pos_x"/>
<Option value="397" type="double" name="component_pos_y"/>
<Option value="kppoints" type="QString" name="name"/>
</Option>
</Option>
</Option>
Best Answer
Here is a PyQGIS solution (in the form of a custom processing script) which should do what you are asking.
This script algorithm has two optional input parameters. The first is a
QgsProcessingParameterVectorLayer
, the second aQgsProcessingParameterExtent
. Therefore the input can either be a polygon vector layer, or an extent (layer, canvas, or draw on canvas). If both inputs are filled, the layer will be used and the extent ignored, if neither are filled, a helpful error dialog will be shown.If a layer input is used, a
processing.run()
call is made to"native:randompointsinpolygons"
as a child algorithm.if an extent is used, the call is made to
"native:randompointsinextent"
as a child algorithm.In this way your requirement is satisfied, that the user can select either an input layer or file, or draw a rectangle extent on the canvas, and the script will handle and process the input accordingly.
If you save this script as a
.py
file, you can add it to the Processing Toolbox by clicking the Python icon on the toolbar at the top of the Processing Toolbox dock widget, and selecting 'Add Script to Toolbox...'. You can then find and run the algorithm under Scripts -> Examples.The dialog for the algorithm will look like this:
The full processing script is shown below: