Loading MapStore Annotations in QGIS
MapStore is an Open Source highly modular web gis framework developed by GeoSolutions to create, manage and share securely in a simple and intuitive way maps created by mixing geospatial contents served from servers like Google Maps, OpenStreetMap, Bing or from server adhering to OGC standards like WFS, CSW, WMS and WMTS.
Although it is possible to make layers editable within MapStore, the annotation functionality is a much more accessible functionality to sketch on a map and save the results of these sketches. The annotations provide a simple, yet powerful tool that can be very useful e.g.. in data reviewing or stakeholder engagement sessions.
However, if one wants to use the annotations in another context (spatial analysis in a desktop GIS, show in other web maps, etc.), things become more difficult. The annotations can be downloaded as a .json file, however this is a custom json format which can only be imported in MapStore itself.
A while ago I had already created some functionality to load these annotations into QGIS and when a posts was made onto the MapStore developers mailinglist, I decided to share this efforts1.
The complete workflow should be as simple as:
- Download MapStore annotation file
- Copy-paste the Python code below into a text editor
- Change the input file path in the Python code
- Open QGIS and open the Python console (Plugins Python Console )
- Copy-paste the modified Python code into the QGIS Python console
- Notice the annotations showing up as a group layer.
Python code:
# !/usr/bin/env python
# -*- coding: utf-8 -*-
import json
from PyQt5.QtGui import QColor, QFont
from qgis.core import QgsPalLayerSettings, QgsTextFormat
from qgis.core import QgsTextBufferSettings, QgsVectorLayerSimpleLabeling
# Replace with the path to the downloaded .json file with annotations
input_file_path = unicode(r"C:\Users\NL01031\Downloads\Sample Map.json")
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
layer_settings.placement = 4
layer_settings.enabled = True
layer_settings = QgsVectorLayerSimpleLabeling(layer_settings)
layer.setLabelsEnabled(True)
layer.setLabeling(layer_settings)
layer.triggerRepaint()
groupName ="Annotations"
project = QgsProject.instance()
root = project.layerTreeRoot()
group = root.addGroup(groupName)
lineLayer = QgsVectorLayer("linestring?crs=epsg:4326&field=id:string(36)&field=title:string&field=description:string&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&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&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 = []
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"')