Last active
June 28, 2023 17:18
-
-
Save ewsterrenburg/b579e1f6c053050112a2e89f9811408d to your computer and use it in GitHub Desktop.
Load Mapstore annotations into QGIS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
import json | |
from PyQt5.QtGui import QColor, QFont | |
from qgis.core import QgsPalLayerSettings, QgsTextFormat | |
from qgis.core import QgsTextBufferSettings, QgsVectorLayerSimpleLabeling | |
def turnOnLabels(layer, expression): | |
layer_settings = QgsPalLayerSettings() | |
text_format = QgsTextFormat() | |
text_format.setFont(QFont("Arial", 10)) | |
text_format.setSize(10) | |
buffer_settings = QgsTextBufferSettings() | |
buffer_settings.setEnabled(True) | |
buffer_settings.setSize(0.10) | |
buffer_settings.setColor(QColor("black")) | |
text_format.setBuffer(buffer_settings) | |
layer_settings.setFormat(text_format) | |
layer_settings.fieldName = expression | |
layer_settings.isExpression = True | |
# Line below is the original version | |
# Can't figure out anymore what the exact meaning of the magic 4 is... | |
# Could be replaced with a proper placement if required | |
# layer_settings.placement = 4 | |
layer_settings.enabled = True | |
layer_settings = QgsVectorLayerSimpleLabeling(layer_settings) | |
layer.setLabelsEnabled(True) | |
layer.setLabeling(layer_settings) | |
layer.triggerRepaint() | |
input_file_path = unicode(r"C:\Users\NL01031\Downloads\Annotations.json") | |
groupName ="Annotations" | |
project = QgsProject.instance() | |
root = project.layerTreeRoot() | |
group = root.addGroup(groupName) | |
# not the most elegant way to allow for longer descriptions, yet | |
# good enough for now. | |
# (for adding the fields in a more elegant way: https://anitagraser.com/pyqgis-101-introduction-to-qgis-python-programming-for-non-programmers/pyqgis101-creating-editing-a-new-vector-layer/ ) | |
lineLayer = QgsVectorLayer("linestring?crs=epsg:4326&field=id:string(36)&field=title:string&field=description:string(10000)&index=yes", "PolyLines", "memory") | |
project.addMapLayer(lineLayer, False) | |
group.addLayer(lineLayer) | |
pointLayer = QgsVectorLayer("point?crs=epsg:4326&field=id:string(36)&field=title:string&field=description:string(10000)&field=textvalue:string&&index=yes", "Points", "memory") | |
project.addMapLayer(pointLayer, False) | |
group.addLayer(pointLayer) | |
polygonLayer = QgsVectorLayer("polygon?crs=epsg:4326&field=id:string(36)&field=title:string&field=description:string(10000)&index=yes", "Polygons", "memory") | |
project.addMapLayer(polygonLayer, False) | |
group.addLayer(polygonLayer) | |
annotationFile = open(input_file_path) | |
annotations = json.loads(annotationFile.read()) | |
features = annotations['features'] | |
for feature in features: | |
attributeId = feature['properties']['id'] | |
attributeTitle = feature['properties']['title'] | |
try: | |
attributeDescription = feature['properties']['description'] | |
except KeyError: | |
attributeDescription = None | |
subParts = feature['features'] | |
for subPart in subParts: | |
featureType = subPart['geometry']['type'] | |
if featureType == 'LineString': | |
vertices = [] | |
for coord in subPart['geometry']['coordinates']: | |
vertex = QgsPoint(coord[0], coord[1]) | |
vertices.append(vertex) | |
geom = QgsGeometry.fromPolyline(vertices) | |
feat = QgsFeature(lineLayer.fields()) | |
elif featureType == 'Point': | |
coord = subPart['geometry']['coordinates'] | |
pointXY = QgsPointXY(coord[0], coord[1]) | |
geom = QgsGeometry.fromPointXY(pointXY) | |
feat = QgsFeature(pointLayer.fields()) | |
try: | |
attributeTextValue = subPart['properties']['valueText'] | |
except KeyError: | |
attributeTextValue = '' | |
feat.setAttribute('textvalue', attributeTextValue) | |
elif featureType == 'Polygon': | |
vertices = [] | |
if len(subPart['geometry']['coordinates']) == 0: | |
iface.messageBar().pushMessage("Warning", f"Polygon without vertices encountered for feature with id {attributeId}.", level=Qgis.Warning) | |
continue | |
for coord in subPart['geometry']['coordinates'][0]: | |
vertex = QgsPointXY(coord[0], coord[1]) | |
vertices.append(vertex) | |
geom = QgsGeometry.fromPolygonXY([vertices]) | |
geom.addRing(vertices) | |
feat = QgsFeature(polygonLayer.fields()) | |
feat.setGeometry(geom) | |
feat.setAttribute('id', attributeId) | |
feat.setAttribute('title', attributeTitle) | |
feat.setAttribute('description', attributeDescription) | |
if featureType == 'LineString': | |
(res, outFeats) = lineLayer.dataProvider().addFeatures([feat]) | |
elif featureType == 'Point': | |
(res, outFeats) = pointLayer.dataProvider().addFeatures([feat]) | |
elif featureType == 'Polygon': | |
(res, outFeats) = polygonLayer.dataProvider().addFeatures([feat]) | |
turnOnLabels(pointLayer, '"title" || \' - \' || "textvalue"') | |
turnOnLabels(lineLayer, '"title"') | |
turnOnLabels(polygonLayer, '"title"') |
@roelsantiago There's a few minor differences, yet indeed it can be implemented (in fact, this gist originally started as a plugin)
I included the improvements the current version and made it available here
https://drive.google.com/file/d/1vpJbGGb9Dq3U00u5rJ1bN5YGrcmg6BF3/view?usp=sharing
Thanks for the update! Tested the plugin in QGIS 3.32 and works perfectly fine.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Success. great guide! Just a follow up, I notice in the python console, there's an option to "Add script Toolbox" Can this be implemented? then simply run the tools in the same manner like running a buffer? Big thanks!