我为QGIS 3.x编写了一个处理脚本,它本身在for循环中调用本机处理函数(qgis:shortestpathpointtolayer)。
from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (QgsProcessing,
QgsFeatureRequest,
QgsExpression,
QgsProcessingContext,
QgsProcessingException,
QgsProcessingAlgorithm,
QgsProcessingParameterVectorLayer,
QgsProcessingFeatureSourceDefinition)
from qgis import processing
class findDownstreamPathAlgorithm(QgsProcessingAlgorithm):
"""
This is an algorithm that calculates downstream paths on
a simplified network.
"""
INPUT_NETWORK = 'INPUT_NETWORK'
INPUT_VALVES = 'INPUT_VALVES'
def tr(self, string):
return QCoreApplication.translate('Processing', string)
def createInstance(self):
return findDownstreamPathAlgorithm()
def name(self):
return 'iterateclusters'
def displayName(self):
return self.tr('Iterate clusters')
def group(self):
return self.tr('Thvilum')
def groupId(self):
return 'lukkelister'
def shortHelpString(self):
return self.tr("Iterate clusters in a simplified network")
def initAlgorithm(self, config=None):
self.addParameter(
QgsProcessingParameterVectorLayer(
self.INPUT_NETWORK,
self.tr('Netværkslag'),
[QgsProcessing.SourceType.TypeVectorLine]
)
)
self.addParameter(
QgsProcessingParameterVectorLayer(
self.INPUT_VALVES,
self.tr('Ventillag'),
[QgsProcessing.SourceType.TypeVectorPoint]
)
)
def processAlgorithm(self, parameters, context, feedback):
# Retrieve the feature sources
network = self.parameterAsVectorLayer(
parameters,
self.INPUT_NETWORK,
context
)
valves = self.parameterAsVectorLayer(
parameters,
self.INPUT_VALVES,
context
)
if network is None:
raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT_NETWORK))
if valves is None:
raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT_VALVES))
# Store inlets from valves layer in separate scractch layer
inlets = valves.materialize(QgsFeatureRequest(QgsExpression("situation = 'IsInlet'")))
# Collect clusters to evaluate
clusterList = []
for feat in network.getFeatures():
clusterList.append(feat["cluster"])
# Remove duplicates and sort list
clusterList = sorted(set(clusterList))
if len(clusterList) > 0:
total = 100.0 / len(clusterList)
else:
total = 0
isCanceled = False
for current, cluster in enumerate(clusterList):
# Update the progress bar
feedback.setProgress(int(current * total))
valves.selectByExpression("cluster = {} and situation = 'Flow'".format(cluster))
for feat in valves.selectedFeatures():
# Stop the algorithm if cancel button has been clicked
if feedback.isCanceled():
isCanceled = True
break
vertex_id = feat["vertexId"]
valve_geom = feat.geometry()
network.selectByExpression("cluster != {}".format(cluster))
parameters = {
'DEFAULT_DIRECTION' : 2,
'DEFAULT_SPEED' : 50,
'DIRECTION_FIELD' : '',
'END_POINTS' : inlets,
'INPUT' : QgsProcessingFeatureSourceDefinition( network.id(), selectedFeaturesOnly=True),
'OUTPUT' : 'TEMPORARY_OUTPUT',
#'OUTPUT_NON_ROUTABLE' : 'TEMPORARY_OUTPUT',
'SPEED_FIELD' : '',
'START_POINT' : valve_geom,
'STRATEGY' : 0,
'TOLERANCE' : 0,
'VALUE_BACKWARD' : '',
'VALUE_BOTH' : '',
'VALUE_FORWARD' : ''
}
result = processing.run("qgis:shortestpathpointtolayer", parameters, context=context, feedback=feedback, is_child_algorithm=True)
shortest_path = QgsProcessingContext.takeResultLayer(context, result['OUTPUT'])
# Do something with the path
del shortest_path
if isCanceled:
break
return {self.INPUT_NETWORK: network}
在 QGIS 3.28.4 上运行此脚本时,它会运行几次迭代,然后引发异常(访问冲突),并具有以下描述:
Python 堆栈跟踪 Windows 致命异常:访问冲突
线程 0x00005d8c(最近调用优先): 文件“C:\PROGRA~1/QGIS32~2.4/apps/qgis-ltr/./python/plugins\processing\gui\AlgorithmExecutor.py”,第 72 行执行 结果,ok = alg.run(参数,上下文,反馈,{},False) 文件“C:\PROGRA~1/QGIS32~2.4/apps/qgis-ltr/./python/plugins\processin