Sto cercando di modificare il valore di un attributo per ogni funzione in un livello usando un plug-in QGIS Python. Ho scoperto che farlo al di fuori della modalità di modifica è molto più lento rispetto alla modifica (anche includendo le modifiche). Vedi il codice sotto (linee intercambiabili nello stesso punto in un ciclo). La differenza di velocità per il mio set di dati di esempio è di 2 secondi (modalità di modifica) contro 72 secondi (non modalità di modifica).
Modifica di un attributo in modalità modifica:
layer.changeAttributeValue(feature.id(), 17, QtCore.QVariant(value))
Modifica di un attributo al di fuori della modalità di modifica:
layer.dataProvider().changeAttributeValues({ feature.id() : { 17 : QtCore.QVariant(value) } })
È un comportamento previsto? Non ho bisogno che l'utente sia in grado di annullare le modifiche, quindi non credo di dover utilizzare la modalità di modifica.
Modifica 1: vedi sotto il codice completo con entrambe le versioni incluse (ma commentate):
def run(self):
try:
# create spatial index of buffered layer
index = QgsSpatialIndex()
self.layer_buffered.select()
for feature in self.layer_buffered:
index.insertFeature(feature)
# enable editing
#was_editing = self.layer_target.isEditable()
#if was_editing is False:
# self.layer_target.startEditing()
# check intersections
self.layer_target.select()
self.feature_count = self.layer_target.featureCount()
for feature in self.layer_target:
distance_min = None
fids = index.intersects(feature.geometry().boundingBox())
for fid in fids:
# feature's bounding box and buffer bounding box intersect
feature_buffered = QgsFeature()
self.layer_buffered.featureAtId(fid, feature_buffered)
if feature.geometry().intersects(feature_buffered.geometry()):
# feature intersects buffer
attrs = feature_buffered.attributeMap()
distance = attrs[0].toPyObject()
if distance_min is None or distance < distance_min:
distance_min = distance
if self.abort is True: break
if self.abort is True: break
# update feature's distance attribute
self.layer_target.dataProvider().changeAttributeValues({feature.id(): {self.field_index: QtCore.QVariant(distance_min)}})
#self.layer_target.changeAttributeValue(feature.id(), self.field_index, QtCore.QVariant(distance_min))
self.calculate_progress()
# disable editing
#if was_editing is False:
# self.layer_target.commitChanges()
except:
import traceback
self.error.emit(traceback.format_exc())
self.progress.emit(100)
self.finished.emit(self.abort)
Entrambi i metodi producono lo stesso risultato, ma la scrittura tramite il fornitore di dati richiede molto più tempo. La funzione classifica la vicinanza delle caratteristiche dell'edificio ai campi vicini (viola) utilizzando buffer pre-creati (brown-ish).