Skip to content

Instantly share code, notes, and snippets.

@ewsterrenburg
Last active June 28, 2023 17:18
Show Gist options
  • Save ewsterrenburg/b579e1f6c053050112a2e89f9811408d to your computer and use it in GitHub Desktop.
Save ewsterrenburg/b579e1f6c053050112a2e89f9811408d to your computer and use it in GitHub Desktop.
Load Mapstore annotations into QGIS
# -*- 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
Copy link

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!

@ewsterrenburg
Copy link
Author

ewsterrenburg commented Jun 28, 2023

@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

@roelsantiago
Copy link

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