Tuesday 21 May 2019

QGIS Plugin: csv2polygon

Another plugin that takes data stored in CSV file. This time you can create polygon.  It is especially useful, when you have tabular data that describes polygon (e. g. airspace) as pair of latitude an longitude values. The biggest advantage is that you can create many polygons in one run of a plugin.

This plugin is designed to deal with data in following format:
polygon_name1;lat1,lon1
polygon_name1;lat2,lon2
polygon_name1;lat3,lon3
polygon_name1;lat4,lon4
...
...
polygon_name_n;lat_m,lon_m
polygon_name_n;lat_m+1,lon_m+1
....

In other words:
Each polygon is described by lines, and each line contains: polygon name, latitude and longitude of vertex.

So far, in all tools that creates any 'spatial layer' I always use WGS 84 coordinate system. Source data are not always in WGS 84 so it is a goog idea to add possibility to choose coordinate system. This is very use when we used  QgsProjectionSelectionWidget. Method crs() returns the selected coordinate system, and this result will be used while creating output 'spatial' file:

selected_crs = self.dlg.mQgsProjectionSelectionWidget.crs()
out_fields = QgsFields()
out_fields.append(QgsField("POLYGON_ID", QVariant.String))

writer = QgsVectorFileWriter(self.shp_file, "CP1250", out_fields, QgsWkbTypes.Polygon, selected_crs,
                             "ESRI Shapefile")

The idea behind creating polygons is described in detail below. But first I want to initialize some variables that will keep
qgs_vertices - list of QgsPoints, that later will be passed to QgsGeometry.fromPolygonXY method
qgs_vertices_count - number of QgsPints in the qgs_vertices. I want to check if there more the 3 points in the list - then I am able to create polygon.
Note 1: I do not have to use additional variables. I can check number of pionts in following way:
len(qgs_vertices)
Note 2: Some function for cerating polygons require that first and last veretx are the same vertices. At this version I do not this check, and eventually append to the qgs_vertices list additional vertex - the first vertex.
current_poly_id - to track and detect change in polygon name.
So, let's initialize variables now:

qgs_vertices = []
qgs_vertices_count = 0
current_poly_id = ''


with open(self.csv_file, 'r') as csv_data:
    reader = csv.DictReader(csv_data, delimiter=';')
    while True:
        try:
            row = next(reader)
            current_poly_id = row[self.dlg.comboBoxPolyIdField.currentText()]
            exit
        except StopIteration:
            break

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
feat = QgsFeature()

with open(self.csv_file, 'r') as csv_data:
    reader = csv.DictReader(csv_data, delimiter=';')
    while True:
        try:
            row = next(reader)
            poly_id = row[self.dlg.comboBoxPolyIdField.currentText()]

            # Create vertex from data in line
            vertex = agc.CoordinatesPair(row[self.dlg.comboBoxVertexLatField.currentText()],
                                         row[self.dlg.comboBoxVertexLonField.currentText()])

            qgs_vertex = QgsPointXY(vertex.lon_dd, vertex.lat_dd)

            if poly_id == current_poly_id:
                qgs_vertices_count += 1
                qgs_vertices.append(qgs_vertex)
            elif poly_id != current_poly_id:
                if qgs_vertices_count < 3:
                    pass  # TO DO: log error message
                else:
                    try:  # Try to create polygon
                        feat.setGeometry(QgsGeometry.fromPolygonXY([qgs_vertices]))
                        feat.setAttributes([current_poly_id])
                        writer.addFeature(feat)
                    except:
                        pass  # TO DO: log error message
                # Reset variables
                qgs_vertices_count = 0
                current_poly_id = poly_id
                qgs_vertices.clear()
                qgs_vertices.append(qgs_vertex)
        except StopIteration:  # End of file - try to create polygon from data
            if qgs_vertices_count < 3:  # We need at least 3 vertices to create polygon
                pass  # TO DO: error message
            else:
                try:
                    feat.setGeometry(QgsGeometry.fromPolygonXY([qgs_vertices]))
                    feat.setAttributes([current_poly_id])
                    writer.addFeature(feat)
                except:
                    pass  # TO DO: error message
            break  # Stop iteration

del writer


if self.dlg.checkBoxAddToMap.isChecked():
    self.iface.addVectorLayer(self.shp_file, '', "ogr")


No comments:

Post a Comment