Sunday 24 March 2019

QGIS Plugin to extract nodes from polygon (and not only...)

This plugins allows you to easily get following result for selected polygon:



convert coordinates of nodes (vertices) of featutre into human friendly DMS format.
The first (upper) string is latitude, the second (lower) is longitude.

NOTE: Almost every spatial task can be solved at least in a few ways: we can do it manually by clicking, we can automate task by combining geoprocessing tools and create model, we can write script or create plugin.


First, we need to check if user selected only one feature from layer that is polygon type. If not, give appropriate messages, else create point layer called 'NODE' . This layer is temporary, memory layer to keep extracted nodes from selected feature:


canvas = self.iface.mapCanvas()
clayer = canvas.currentLayer()
if clayer.geometryType() is None:
    QMessageBox.critical(w, "Message", "No active layer")

elif clayer.geometryType() == QgsWkbTypes.PolygonGeometry:
    selected_count = clayer.selectedFeatureCount()
    if selected_count == 0:
        QMessageBox.critical(w, "Message", "Select 1 polygon")
    elif selected_count > 1:
        QMessageBox.critical(w, "Message", "Select only 1 polygon. Selected polygons: {}".format(selected_count))
    else:
        if self.node_lyr_name == '':
            self.node_lyr_name = 'NODES'

        layers = QgsProject.instance().layerTreeRoot().children()
        layers_list = []  # List of layers in current (opened) QGIS project
        for layer in layers:
            layers_list.append(layer.name())

        if self.node_lyr_name not in layers_list:
            self.create_nodes_mlyr(self.node_lyr_name)

If 'NODE' layer already exists - truncate 'layer' to ensure that only extracted nodes for current selection will be in the layer, and get selected feature.


out_lyr = QgsProject.instance().mapLayersByName(self.node_lyr_name)[0]
self.iface.setActiveLayer(out_lyr)

# if number of nodes is > 0 -> remove them
out_lyr.startEditing()
out_lyr.dataProvider().truncate()
out_lyr.commitChanges()

selected_feat = clayer.selectedFeatures()[0]

If current layer (from which is selected polygon) has type MultiPolygon we have to get nodes in following loops, because multipolygon conatins other 'polygons':


elif clayer.wkbType() == QgsWkbTypes.MultiPolygon:
multi_polygon = selected_feat.geometry().asMultiPolygon()
for i in range(len(multi_polygon)):
    for j in range(len(multi_polygon[i])):
        for k in range(len(multi_polygon[i][j])):
            lon_dms = dd2dms(multi_polygon[i][j][k][0])
            lat_dms = dd2dms(multi_polygon[i][j][k][1])

            attr = ["",
                    "",
                    "",
                    "",
                    str(lat_dms),
                    str(lon_dms)]
            self.add_node(multi_polygon[i][j][k], attr)

No comments:

Post a Comment