Solución:
¡Interesante pregunta! No conozco ninguna otra forma de lograr lo que desea, pero usando PyQGIS.
Lea el código a continuación. Tiene algunos textos en él: 'lines'
, 'length'
, 'startX'
, 'startY'
, 'endX'
, 'endY'
. Puede ajustar esos nombres en el script para que funcione con sus datos. El primero es el nombre de la capa, mientras que el resto corresponde a los nombres de los campos. Supongo que su capa de línea tiene esos campos (después de todo, desea que los valores se escriban allí).
Una vez que haya ajustado el nombre de su capa y los nombres de los campos que desea que se actualicen automáticamente, copie y pegue el script en la consola QGIS Python.
Si todo va bien, debería poder ver que los valores de campo se actualizan automáticamente en dos escenarios: 1) Cuando se agregan nuevas características y 2) Cuando se modifican las geometrías.
# Initialize required variables
myLayer = QgsMapLayerRegistry.instance().mapLayersByName( 'lines' )[0]
lengthField = myLayer.fieldNameIndex( 'length' )
startXField = myLayer.fieldNameIndex( 'startX' )
startYField = myLayer.fieldNameIndex( 'startY' )
endXField = myLayer.fieldNameIndex( 'endX' )
endYField = myLayer.fieldNameIndex( 'endY' )
# Slot, updates field values
def updateFeatureAttrs( fId, geom=None ):
f = myLayer.getFeatures( QgsFeatureRequest( fId ) ).next()
if not geom:
geom = f.geometry()
myLayer.changeAttributeValue( fId, lengthField, geom.length() )
myLayer.changeAttributeValue( fId, startXField, geom.vertexAt( 0 )[0] )
myLayer.changeAttributeValue( fId, startYField, geom.vertexAt( 0 )[1] )
myLayer.changeAttributeValue( fId, endXField, geom.asPolyline()[-1][0] )
myLayer.changeAttributeValue( fId, endYField, geom.asPolyline()[-1][1] )
# Update feature attributes when new features are added or geometry changes
myLayer.featureAdded.connect( updateFeatureAttrs )
myLayer.geometryChanged.connect( updateFeatureAttrs )
Así es como funciona:
Si tiene algún problema mientras ejecuta el script, agregue un comentario debajo de esta respuesta.
Puede resultarle útil tener esta funcionalidad ya disponible cuando abra su proyecto QGIS. Si ese es el caso, dígame, podría publicar instrucciones para hacerlo.
EDITAR:
Para que esta funcionalidad esté disponible cada vez que abra su proyecto QGIS (es decir, un .qgs
archivo que contiene, entre otros, su capa de línea) debe seguir estos pasos:
-
Ir a
QGIS->Project->Project Properties->Macros
, comprobar elPython macros
opción, y reemplace todo el código con este (ajuste los valores que indican los nombres de su capa y campo):from qgis.core import QgsMapLayerRegistry, QgsFeatureRequest def openProject(): # Initialize required variables myLayer = QgsMapLayerRegistry.instance().mapLayersByName( 'lines' )[0] # Update feature attributes when new features are added or geometry changes myLayer.featureAdded.connect( updateFeatureAttrs ) myLayer.geometryChanged.connect( updateFeatureAttrs ) # Slot, updates field values def updateFeatureAttrs( fId, geom=None ): myLayer = QgsMapLayerRegistry.instance().mapLayersByName( 'lines' )[0] lengthField = myLayer.fieldNameIndex( 'length' ) startXField = myLayer.fieldNameIndex( 'startX' ) startYField = myLayer.fieldNameIndex( 'startY' ) endXField = myLayer.fieldNameIndex( 'endX' ) endYField = myLayer.fieldNameIndex( 'endY' ) f = myLayer.getFeatures( QgsFeatureRequest( fId ) ).next() if not geom: geom = f.geometry() myLayer.changeAttributeValue( fId, lengthField, geom.length() ) myLayer.changeAttributeValue( fId, startXField, geom.vertexAt( 0 )[0] ) myLayer.changeAttributeValue( fId, startYField, geom.vertexAt( 0 )[1] ) myLayer.changeAttributeValue( fId, endXField, geom.asPolyline()[-1][0] ) myLayer.changeAttributeValue( fId, endYField, geom.asPolyline()[-1][1] ) def saveProject(): pass def closeProject(): pass
-
Asegúrese de habilitar macros en su proyecto, de esta manera:
Settings->Options->General->Enable macros: Always
. -
Guarde su proyecto QGIS.
Ahora, cada vez que abres el .qgs
archivo que acaba de guardar, los atributos de su capa de línea se actualizarán automáticamente cuando agregue una nueva característica o modifique una geometría (es decir, ya no es necesario copiar nada en la consola QGIS Python).
2da EDICIÓN:
Acabo de publicar un complemento llamado AutoFields para ayudar a las personas a resolver este tipo de problemas. Incluso hice un video que muestra cómo resolver su problema, puede verlo en:
Documentación de AutoFields: http://geotux.tuxfamily.org/index.php/en/geo-blogs/item/333-autofields-plugin-for-qgis
Si solo necesita estos campos dentro de QGIS, puede utilizar campos virtuales. Estos permiten usar una expresión (como $length
) que depende de otros valores o de la geometría.
Abra la calculadora de campo, agregue un nuevo campo con la longitud del nombre, marque la casilla de verificación “Campo virtual” e ingrese $length
como expresión (o algo más para los otros campos).
Sin embargo, estos no se guardarán en el archivo de Excel.
Si desea mantener un archivo de Excel sincronizado con un archivo shp para geometría e incluir campos derivados en el archivo de Excel, existe un complemento llamado ShpSync que conoce este concepto y actualiza los campos automáticamente cuando se cambian, agregan o eliminan características.
Para QGIS 3 Ve a la Layers Properties
=> Attributes Form
=> elija su campo con valores de geometría (en ejemplo, area
) => tipo $area
en el Defaults value
caja y marca Apply default value on update
. Esto también podría ser útil: $perimeter
, $y
, $x
, $id