Сделать поле таблицы атрибутов QGIS автоматическим?

9

Я работаю над тем, чтобы делать гидрологические проекты, используя QGIS и рабочий лист Excel, который у меня есть. Для этого я хочу извлечь некоторую информацию о линиях, включенных в векторный слой, который представляет сечение трубы.

Информация, которую мне нужно извлечь:

  • Идентификационный номер
  • длина
  • X, Y начальная и конечная координаты

Я нашел способ захватить это поле, используя $ length и другой алгоритм для координат X и Y, но для этого мне нужно открыть таблицу атрибутов, поместить выражения в каждый столбец атрибута и щелкнуть, чтобы обновить поля.

Есть ли способ, когда я рисую линию, эти поля заполняются автоматически? То есть я рисую / редактирую линию (начало редактирования или конечный узел), и когда я открываю таблицу атрибутов, поля длины и координаты X, Y заполняются и обновляются.

LeoNazareth
источник
1
Не уверен, что это возможно в режиме редактирования, как во временной таблице. Но вы могли бы взглянуть на действия. Вы можете использовать их, например, для запуска кода Python для заполнения ваших расчетов. Ну, вы должны нажать дополнительную кнопку, чтобы запустить его из таблицы атрибутов. Вы можете взглянуть на имеющиеся возможности и посмотреть, соответствует ли это вашей идее.
Матт

Ответы:

7

Если вам нужны только эти поля внутри QGIS , вы можете использовать виртуальные поля. Это позволяет использовать выражение (например $length), которое зависит от других значений или геометрии.

Откройте калькулятор полей, добавьте новое поле с длиной имени, установите флажок «Виртуальное поле» и введите в $lengthкачестве выражения (или что-то еще для других полей).

Однако они не будут сохранены в файл Excel.

Если вы хотите синхронизировать файл Excel с файлом shp для геометрии и включить производные поля в файл Excel, существует плагин ShpSync, который знает об этой концепции и автоматически обновляет поля при изменении, добавлении или удалении объектов.

Матиас Кун
источник
На самом деле, ответ ниже работает именно так, как я хочу, но этот плагин, который вы сказали, будет работать для следующего шага моего проекта. Спасибо за вашу помощь
LeoNazareth
15

Интересный вопрос! Я не знаю ни одного другого способа достижения того, чего вы хотите, кроме использования PyQGIS.

Прочитайте код ниже. Он имеет некоторые тексты в нем: 'lines', 'length', 'startX', 'startY', 'endX', 'endY'. Вы можете настроить эти имена в скрипте, чтобы он работал с вашими данными. Первый - это имя слоя, а остальные соответствуют именам полей. Я предполагаю, что ваш линейный слой имеет эти поля (в конце концов, вы хотите, чтобы значения были записаны там).

После того, как вы настроили имя слоя и имена полей, которые вы хотите автоматически обновлять, скопируйте и вставьте скрипт в консоль QGIS Python.

Если все идет хорошо, вы должны увидеть, что значения полей автоматически обновляются в двух сценариях: 1) при добавлении новых объектов и 2) при изменении геометрии.

# 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 )

Вот как это работает:

Автоматическое обновление полей в QGIS

Если у вас возникли проблемы во время работы скрипта, добавьте комментарий под этим ответом.

Возможно, вам будет удобно иметь эту функцию уже при открытии проекта QGIS. Если это так, скажите мне, я мог бы опубликовать инструкции, чтобы сделать это.


РЕДАКТИРОВАТЬ:

Чтобы эта функция была доступна каждый раз, когда вы открываете свой проект QGIS (т. Е. .qgsФайл, содержащий, среди прочего, ваш линейный слой), вам необходимо выполнить следующие шаги:

  1. Перейдите QGIS->Project->Project Properties->Macros, отметьте Python macrosопцию и замените весь код на этот (отрегулируйте значения, обозначающие ваш слой и имена полей):

    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
    
  2. Убедитесь , что вы включить макросы на ваш проект, таким образом: Settings->Options->General->Enable macros: Always.

  3. Сохраните свой проект QGIS.

Теперь, каждый раз, когда вы открываете .qgsфайл, который вы только что сохранили, атрибуты вашего линейного слоя будут автоматически обновляться при добавлении новой функции или изменении геометрии (т. Е. Больше не нужно ничего копировать в консоль QGIS Python).


2-е РЕДАКТИРОВАНИЕ:

Я только что опубликовал плагин под названием AutoFields, чтобы помочь людям решать подобные проблемы. Я даже сделал видео, показывающее, как решить вашу проблему, вы можете посмотреть его по адресу:

https://vimeo.com/germap/autofields-geometric-properties

Документация AutoFields: http://geotux.tuxfamily.org/index.php/en/geo-blogs/item/333-autofields-plugin-for-qgis

Герман Каррильо
источник
2
Это именно то, что я искал. На самом деле я использовал твой код, чтобы поймать координаты X, Y, которые я нашел в твоем старом ответе в этой ссылке , той же самой, которую ты публикуешь сейчас. Я уже проверил автоматизацию, и она работает отлично. Я сохранил код Python в виде файла .pycl. Если вы можете объяснить мне, как это может быть доступно, когда я открою мой проект QGIS, это будет здорово. Спасибо за помощь.
LeoNazareth
1
Немец, это был потрясающий ответ! Спасибо! Я многому научился у вас с тем, что вы отправили!
jbgramm
1
Я на самом деле работаю над плагином, который позволит вам сделать именно это. Поскольку я могу посвятить его разработке только свое свободное время, я не могу сообщить вам ожидаемую дату выпуска. Тем временем, вы можете запустить мой первый фрагмент кода после добавления Tramo.shp, настроив: myLayer = QgsMapLayerRegistry.instance().mapLayersByName( 'Tramo' )[0]Если вам действительно интересен мой будущий плагин, присылайте мне любые ваши предложения, я был бы признателен. Вы можете связаться со мной в GeoTux .
Герман Каррильо
1
Это будет здорово для меня (и для многих людей, конечно), я уже использую код с этой настройкой, которую вы предложили. Я с нетерпением буду ждать вашего нового плагина, и если я подумаю над чем-нибудь полезным, я свяжусь с вами. Спасибо тебе за все.
LeoNazareth
1
@LeoNazareth, вы хотели бы проверить плагин? Он готовится, но я хотел бы выполнить некоторые тесты, прежде чем выпустить его. Если вы хотите проверить это, пожалуйста, пришлите мне по электронной почте .
Герман Каррильо
2

Для QGIS 3 перейдите в Layers Properties=> Attributes Form=> выберите ваше поле со значениями геометрии (например, area) => введите $areaв Defaults valueполе и отметьте Apply default value on update. Это также может быть полезным: $perimeter, $y, $x,$id

Товарищ че
источник
1

Я помещал данные в базу данных (PostGIS) и извлекал данные в QGIS с (вероятно, материализованным) представлением.

nielsgerrits
источник