Làm trường bảng thuộc tính QGIS tự động?


9

Tôi đang làm việc theo cách để thực hiện các dự án thủy văn bằng cách sử dụng QGIS và bảng tính Excel mà tôi có. Để làm điều này, tôi muốn trích xuất một số thông tin của các dòng, được bao gồm trong một lớp vectơ, đại diện cho một phần ống.

Thông tin mà tôi cần trích xuất là:

  • Số ID
  • Chiều dài
  • Tọa độ bắt đầu và kết thúc X, Y

Tôi đã tìm thấy một cách để nắm bắt trường này bằng cách sử dụng "$ length" và một thuật toán khác cho tọa độ X và Y, nhưng tôi cần mở bảng Thuộc tính, đặt các biểu thức trong mỗi cột thuộc tính và nhấp để cập nhật các trường.

Có cách nào để tôi vẽ một dòng các trường này được điền tự động không? Nghĩa là, tôi vẽ / chỉnh sửa một dòng (bắt đầu chỉnh sửa hoặc nút kết thúc) và khi tôi mở bảng thuộc tính, các trường độ dài và tọa độ X, Y được điền và cập nhật.


1
Không chắc chắn nếu có thể trong khi ở chế độ chỉnh sửa vì nó được thực hiện trong một bảng tạm thời. Nhưng bạn có thể có một cái nhìn vào hành động. Bạn có thể sử dụng chúng chẳng hạn để chạy mã python để điền vào các tính toán của bạn. Vâng, bạn phải nhấn một nút thêm để chạy nó từ bảng thuộc tính. Bạn có thể xem xét các khả năng có và xem nó có phù hợp với ý tưởng của bạn không.
Mờ

Câu trả lời:


7

Nếu bạn chỉ cần các trường này trong QGIS , bạn có thể sử dụng các trường ảo. Chúng cho phép sử dụng một biểu thức (như $length) phụ thuộc vào các giá trị khác hoặc hình học.

Mở máy tính trường, thêm một trường mới với độ dài tên, đánh dấu vào hộp kiểm "Trường ảo" và nhập $lengthdưới dạng biểu thức (hoặc một cái gì đó khác cho các trường khác).

Tuy nhiên, những thứ này sẽ không được lưu vào tệp excel.

Nếu bạn muốn giữ tệp excel đồng bộ hóa với tệp shp cho hình học và bao gồm các trường dẫn xuất trong tệp excel, có một plugin có tên ShpSync nhận biết khái niệm này và tự động cập nhật các trường khi các tính năng được thay đổi, thêm hoặc xóa.


Trong thực tế, câu trả lời dưới đây hoạt động chính xác cách tôi muốn làm, nhưng plugin này mà bạn nói sẽ hoạt động cho bước tiếp theo của dự án của tôi. Cảm ơn sự giúp đỡ của bạn
LeoNazareth

15

Câu hỏi thú vị! Tôi không biết về bất kỳ cách nào khác để đạt được những gì bạn muốn, nhưng sử dụng PyQGIS.

Đọc mã dưới đây. Nó có một số văn bản trong đó: 'lines', 'length', 'startX', 'startY', 'endX', 'endY'. Bạn có thể điều chỉnh các tên đó trong tập lệnh để nó hoạt động trên dữ liệu của bạn. Cái đầu tiên là tên lớp của bạn, trong khi phần còn lại tương ứng với tên trường. Tôi giả sử lớp dòng của bạn có các trường đó (sau tất cả, bạn muốn các giá trị được viết ở đó).

Khi bạn đã điều chỉnh tên lớp của mình và tên của các trường bạn muốn được cập nhật tự động, hãy sao chép và dán tập lệnh vào bảng điều khiển QGIS Python.

Nếu mọi thứ đều ổn, bạn sẽ có thể thấy các giá trị trường được tự động cập nhật theo hai kịch bản: 1) Khi các tính năng mới được thêm vào và 2) Khi hình học được sửa đổi.

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

Đây là cách nó hoạt động:

Cập nhật tự động các trường trong QGIS

Nếu bạn có bất kỳ vấn đề nào trong khi chạy tập lệnh, hãy thêm một bình luận bên dưới câu trả lời này.

Bạn có thể có sẵn chức năng này khi bạn mở dự án QGIS. Nếu đó là trường hợp, cho tôi biết, tôi có thể gửi hướng dẫn để làm điều đó.


BIÊN TẬP:

Để chức năng này có sẵn mỗi khi bạn mở dự án QGIS (nghĩa là một .qgstệp chứa, trong số các tệp khác, lớp dòng của bạn), bạn cần phải làm theo các bước sau:

  1. Đi đến QGIS->Project->Project Properties->Macros, kiểm tra Python macrostùy chọn và thay thế toàn bộ mã bằng mã này (điều chỉnh các giá trị cho biết tên lớp và trường của bạn):

    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. Hãy chắc chắn rằng bạn bật macro trên dự án của bạn, theo cách này : Settings->Options->General->Enable macros: Always.

  3. Lưu dự án QGIS của bạn.

Bây giờ, mỗi khi bạn mở .qgstệp bạn vừa lưu, các thuộc tính của lớp dòng của bạn sẽ được cập nhật tự động khi bạn thêm một tính năng mới hoặc sửa đổi hình học (nghĩa là không cần phải sao chép bất cứ điều gì vào Bảng điều khiển Python của QGIS nữa).


EDIT thứ 2:

Tôi vừa xuất bản một plugin có tên AutoFields để giúp mọi người giải quyết loại vấn đề này. Tôi thậm chí đã làm một video cho thấy làm thế nào để giải quyết vấn đề của bạn, bạn có thể xem nó tại:

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

Tài liệu về AutoFields: http : //geotux.tuxf Family.org/index.php/en/geo-bloss/item/333-autofields-plugin-for-qgis


2
Điều này thật đúng với gì mà tôi đã tìm kiếm. Thật ra tôi đang sử dụng mã của bạn để bắt tọa độ X, Y, mà tôi đã tìm thấy trong câu trả lời cũ của bạn trong liên kết bài đăng này , giống như bạn đăng bây giờ. Tôi đã thử nghiệm tự động hóa và nó hoạt động hoàn hảo. Tôi đã lưu mã Python dưới dạng tệp ".pycl". Nếu bạn có thể giải thích cho tôi làm thế nào nó có thể có sẵn khi tôi mở dự án QGIS của tôi sẽ rất tuyệt. Cảm ơn bạn đã giúp đỡ.
LeoNazareth

1
Tiếng Đức, đó là một câu trả lời tuyệt vời! Cảm ơn! Tôi đã học được rất nhiều từ bạn với những gì bạn đăng!
jbgramm

1
Tôi thực sự đang làm việc trên một plugin sẽ cho phép bạn làm chính xác điều đó. Vì tôi chỉ có thể dành cho sự phát triển của nó khi rảnh rỗi, tôi không thể nói cho bạn biết ngày phát hành dự kiến. Trong thời gian chờ đợi, bạn có thể chạy đoạn mã đầu tiên của tôi sau khi bạn thêm Tramo.shp, điều chỉnh: myLayer = QgsMapLayerRegistry.instance().mapLayersByName( 'Tramo' )[0]Nếu bạn thực sự quan tâm đến plugin tương lai của tôi, vui lòng gửi cho tôi bất kỳ đề xuất nào bạn có, tôi đánh giá cao điều đó. Bạn có thể liên hệ với tôi tại GeoTux .
Germán Carrillo

1
Điều đó sẽ rất tuyệt với tôi (và đối với nhiều người, tất nhiên), tôi đã sử dụng mã với sự bất công này mà bạn đề xuất. Tôi lo lắng chờ đợi plugin mới của bạn và nếu tôi nghĩ rằng trong một cái gì đó hữu ích, tôi liên hệ với bạn. Cảm ơn bạn cho tất cả mọi thứ.
LeoNazareth

1
@LeoNazareth, bạn có muốn thử plugin không? Nó đã sẵn sàng, nhưng tôi muốn thực hiện một số thử nghiệm trước khi phát hành nó. Nếu bạn sẵn sàng thử nó, xin vui lòng gửi cho tôi một e-mail .
Germán Carrillo

2

Đối với QGIS 3, hãy truy cập Layers Properties=> Attributes Form=> chọn trường của bạn với các giá trị hình học (ví dụ area:) => nhập $areavào Defaults valuehộp và kiểm tra Apply default value on update. Điều này cũng có thể hữu ích: $perimeter, $y, $x,$id


1

Tôi sẽ đặt dữ liệu vào cơ sở dữ liệu (PostGIS) và trích xuất dữ liệu sang QGIS với chế độ xem (có thể được cụ thể hóa).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.