2

Is it possible to automatically set attribute values for a layer based on proximity relationships to another layer in QGIS?

This is a more generic question with a variety of applications, so here is a concrete example: I have a road network (linestrings) with attributes (among others) road_name and road_sgmnt_id and a point layer with building sites also with attributes road_name and road_sgmnt_id (also among others). What I would like to do during digitizing a building site is to find the closest (proximity relationship) road segment, retrieve certain attribute values and insert them into the building site form as shown in the screenshot:

enter image description here

I must confess I am not quite experienced with user defined forms in QGIS (ui-files) but I think such form with some python logic defined behind it could do the trick.

Hint: Since the datasource is not necessarily a database, and if, the form could not be auto-filled this way during digitizing, a trigger function would only be a second option (if any).

3

I found a solution that works fine for me using a Python Init function for an autogenerated form, setup in Layer Properties|Fields like this:

enter image description here

The python init code provided in the dialog that finds the nearest road segments and autofills the appropriate fields in the form is the following:

# -*- coding: utf-8 -*-

from qgis.PyQt.QtWidgets import QWidget, QLineEdit
from qgis.core import *
from qgis.utils import *
from qgis.gui import *

def my_form_open(dialog, layer, feature):
    #access road network layer
    road_lyr = QgsMapLayerRegistry.instance().mapLayersByName(u'road_network')[0]

    #create index and insert features
    road_lyr_index = QgsSpatialIndex()
    for f in road_lyr.getFeatures():
        road_lyr_index.insertFeature(f)

    #nearest neighbor expects QgsPoint as parameter
    geom = feature.geometry().asPoint()

    #find nearest road line segments
    fids = road_lyr_index.nearestNeighbor(geom, 1)
    req = QgsFeatureRequest().setFilterFids(fids)
    res = [(f['osm_id'], f['osm_name']) for f in road_lyr.getFeatures(req)]

    #autofill form depending on result
    if len(res) == 1:
        str_id, str_name = res[0]

        le_osm_id = dialog.findChild(QLineEdit, "str_osm_id")
        le_str = dialog.findChild(QLineEdit, "str")

        le_osm_id.setText(str(str_id))
        le_str.setText(str_name)
    else:
        le_osm_id.setText('0')
        le_str.setText('undef\'d, enter manually') 

Note that the index creation takes some time for large network datasets, my dataset is ~18k features, index creation slightly above 1 sec.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.