9

Summarizing my problem, I'm a beginner and I'm developing a plugin that will be able to do several spatial joins. For this, it will have to separate the spatial from the non-spatial layers and do the spatial join between them. I've a list of layer names from this code:

layerList = QgsProject.instance().layerTreeRoot().findLayers()
nlist = []
for layer in layerList:
    nlist.append(layer.name())

hence I do the geometry test:

layer = iface.activeLayer()
features = layer.getFeatures()

for feature in features:
    # the geometry type can be of single or multi type
    geom = feature.geometry()

    if geom.type() == QgsWkbTypes.PointGeometry:
        print("point")
    elif geom.type() == QgsWkbTypes.LineGeometry:
        print("line")
    elif geom.type() == QgsWkbTypes.PolygonGeometry:
        print("area")
    elif geom.type() == QgsWkbTypes.UnknownGeometry:
        print("table")

and finally I do the spatial join:

root = QgsProject.instance().layerTreeRoot()
ids = root.findLayerIds()
target = QgsProject.instance().mapLayer(ids[1])
print('target: ', target.id())
layerToJoin = QgsProject.instance().mapLayer(ids[0])
print('layerToJoin: ', layerToJoin.id())
fieldToJoin = QgsProject.instance()
symb = QgsVectorLayerJoinInfo()
symb.setJoinFieldName('id_feature')
symb.setTargetFieldName('id')
symb.setJoinLayerId(layerToJoin.id())
symb.setUsingMemoryCache(True)
symb.setEditable(True)
symb.setDynamicFormEnabled(True)
symb.setUpsertOnEdit(True)
symb.setPrefix('')
symb.setJoinFieldNamesSubset('')
symb.setJoinLayer(layerToJoin)
target.addJoin(symb)

Separately, each code block works fine, but I need to put all together and I doesn't figure how. First issue the QgsProject doesn't have a geometry method, so I can't iterate in the layer list and test the geometry, that way I can't direct a vector layer and postgresql table to do the spatial join. If anyone has an idea or a better way to do this please help!!!

2
  • What happens when you test the geometry? Does the code continue regardless or does it stop after a certain geometry is detected? Or do you want to only join layers which have the same geometry?
    – Joseph
    Commented Feb 14, 2019 at 11:32
  • @Joseph I want to join Layers which have different geometry but the same name. I think isn't cristal clear in my post, guess I've to edit it. Therefore, I thought in this workflow: get a list of layer names - from this list test for layers which have same name and different geometry - and then do the spatial join(point layer with a PostgreSQL table for e.g.). If you figure out another way I'll be glad to listen about. Thanks. Commented Feb 14, 2019 at 12:09

1 Answer 1

7

After some tries I can handle using functions and working better in the loops.

def lyrdict(self):
    g_dict = {}
    t_dict = {}
    i = 0
    for layer_tree in self.layers_tree:
        layer = layer_tree.layer()

        if layer.type() == 0:
            layer_type = layer.geometryType()
            layer_name = layer.name()
            ids = self.root.findLayerIds()

            if layer_type == QgsWkbTypes.PointGeometry or layer_type == QgsWkbTypes.LineGeometry:
                g = layer_name
                gids = ids[i]
                g_dict[gids] = g_dict.setdefault(gids, g)
            elif layer_type == 4:
                t = layer_name
                tids = ids[i]
                t_dict[tids] = t_dict.setdefault(tids, t)
            i += 1
    return g_dict, t_dict

def lyrpair(self):
    g_dict, t_dict = self.lyrdict()
    d = {}
    for k, v in g_dict.items():
        for c, e in t_dict.items():
            if g_dict[k] == t_dict[c]:
                d[k] = d.setdefault(k, c)
    return d

def jointables(self):
    d = self.lyrpair()
    for k, v in d.items():
        target = QgsProject.instance().mapLayer(k)
        layerToJoin = QgsProject.instance().mapLayer(v)
        fieldToJoin = QgsProject.instance()
        symb = QgsVectorLayerJoinInfo()
        symb.setJoinFieldName('id_feature')
        symb.setTargetFieldName('id')
        symb.setJoinLayerId(layerToJoin.id())
        symb.setUsingMemoryCache(True)
        symb.setEditable(True)
        symb.setDynamicFormEnabled(True)
        symb.setUpsertOnEdit(True)
        symb.setPrefix('')
        symb.setJoinLayer(layerToJoin)
        target.addJoin(symb)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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