Зробити поле таблиці атрибутів QGIS автоматичним?


9

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

Інформацію, яку мені потрібно витягти, є:

  • Номер документа
  • Довжина
  • X, Y координати початку та кінця

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

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


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, ви хочете протестувати плагін? Він готується, але я хотів би виконати кілька тестів, перш ніж випустити його. Якщо ви готові перевірити це, надішліть мені електронний лист .
Germán Carrillo

2

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


1

Я б помістив ці дані в базу даних (PostGIS) і витяг їх у QGIS з (можливо, матеріалізованим) поданням.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.