Como sugirió MrXsquared en su comentario, podría utilizar PyQGIS para crear una herramienta de procesamiento que puede utilizar en su modelo.
Ejemplo de caja de herramientas
from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (
QgsField,
QgsFeatureRequest,
QgsProcessingParameterField,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterString,
QgsProcessingAlgorithm,
)
from PyQt5.QtCore import QVariant
def calculate_distance(layer, sorting_field, field_name="DISTANCE"):
""" Calculates distance between points along a path """
layer.startEditing()
try:
layer_provider = layer.dataProvider()
if field_name not in layer.fields().names():
layer_provider.addAttributes(
[QgsField(field_name, QVariant.Double)]
)
layer.updateFields()
fields = layer.fields().names()
field_index = fields.index(field_name)
sort_request = QgsFeatureRequest().addOrderBy(
sorting_field,
True, # sorted by asc
False, # None value at the end
)
feature_iterator = layer.getFeatures(sort_request)
changes = {}
last = None
for current in feature_iterator:
distance = 0
if last:
distance = last.geometry().distance(current.geometry())
changes[current.id()] = {
field_index: distance
}
last = current
layer_provider.changeAttributeValues(changes)
layer.commitChanges()
except Exception:
layer.rollBack()
raise Exception("Script failed")
class CalculateDistance(QgsProcessingAlgorithm):
LAYER = "LAYER"
SORTING_FIELD = "SORTING_FIELD"
FIELD_NAME = "FIELD_NAME"
def __init__(self):
super().__init__()
def tr(self, string):
return QCoreApplication.translate("Processing", string)
def name(self):
return "CalculateDistance"
def displayName(self):
return "Calculates distance between points along a path"
def group(self):
return "Example Scripts"
def groupId(self):
return "playground"
def createInstance(self):
return type(self)()
def initAlgorithm(self, config=None):
self.addParameter(
QgsProcessingParameterVectorLayer(
self.LAYER,
self.tr("Layer"),
optional=False
)
)
self.addParameter(
QgsProcessingParameterField(
self.SORTING_FIELD,
self.tr("Sorting Field"),
parentLayerParameterName=self.LAYER,
type=QgsProcessingParameterField.Any,
optional=False
)
)
self.addParameter(
QgsProcessingParameterString(
self.FIELD_NAME,
self.tr("Field Name"),
defaultValue="DISTANCE",
optional=False
)
)
def processAlgorithm(self, parameters, context, feedback):
calculate_distance(
self.parameterAsVectorLayer(parameters, self.LAYER, context),
self.parameterAsString(parameters, self.SORTING_FIELD, context),
self.parameterAsString(parameters, self.FIELD_NAME, context)
)
return {}
Resultado
¿Cómo añadir el script a la caja de herramientas de procesamiento?
- Abrir QGIS
- En su caja de herramientas de procesamiento, haga clic en el icono de Python
- Entonces
Create New Script...
- Escriba su script, o copie/pegue el ejemplo anterior y guárdelo
- Por último, encontrará el script en su caja de herramientas de Processing en
Scripts
:
Ejemplo de script con PyQGIS
Aquí el mismo script de ejemplo pero independiente y no como herramienta de procesamiento:
from qgis.core import QgsField, QgsProject, QgsFeatureRequest
from PyQt5.QtCore import QVariant
layer_name = "RR_POINT_10K"
sorting_field = "OBJECTID"
field_name = "DISTANCE"
def calculate_distance(layer, sorting_field, field_name="DISTANCE"):
""" Calculates distance between points along a path """
layer.startEditing()
try:
layer_provider = layer.dataProvider()
if field_name not in layer.fields().names():
layer_provider.addAttributes(
[QgsField(field_name, QVariant.Double)]
)
layer.updateFields()
fields = layer.fields().names()
field_index = fields.index(field_name)
sort_request = QgsFeatureRequest().addOrderBy(
sorting_field,
True, # sorted by asc
False, # None value at the end
)
feature_iterator = layer.getFeatures(sort_request)
changes = {}
last = None
for current in feature_iterator:
distance = 0
if last:
distance = last.geometry().distance(current.geometry())
changes[current.id()] = {
field_index: distance
}
last = current
layer_provider.changeAttributeValues(changes)
layer.commitChanges()
except Exception:
layer.rollBack()
raise Exception("Script failed")
if __name__ == "__main__":
layers = QgsProject.instance().mapLayersByName(layer_name)
if not layers:
raise Exception(f"Layer {layer_name} does not exist")
calculate_distance(layers[0], sorting_field, field_name)