Skip to content

Instantly share code, notes, and snippets.

@arbakker
Last active August 17, 2022 15:35
Show Gist options
  • Save arbakker/71cd5e8ff25be56e113f3c0296b94937 to your computer and use it in GitHub Desktop.
Save arbakker/71cd5e8ff25be56e113f3c0296b94937 to your computer and use it in GitHub Desktop.
QGIS processing algorithm that forces counter-clockwise orientation of polygon geometries in Geopackage file #qgis #processing #gpkg #pdok

PDOK Geometry Orientation Fixer QGIS Processing Tool

QGIS processing tools for joining PDOK AHN3 WCS (elevation) data with point data.

Tested with QGIS version 3.18, will most likely work with all QGIS version 3.X.

Installation

  1. Download pdok_geom_orientation_fixer.py
  2. Open the QGIS Processing Toolbox and click Add Script to Toolbox... and browse to the downloaded pdok_geom_orientation_fixer.py file:

  1. Now the PDOK Geometry Orientation Fixer tool should be available in your toolbox:

image

  1. Start using the PDOK Geometry Orientation Fixer:

image

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
""""""
# MIT License
# Copyright (c) 2022 Anton Bakker
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
__author__ = "Anton Bakker"
__copyright__ = "Copyright 2022, Anton Bakker"
__license__ = "MIT"
__version__ = "0.0.0"
__maintainer__ = "Anton Bakker"
__email__ = "[email protected]"
__date__ = "2022-08-09"
from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (
QgsProcessingAlgorithm,
QgsProcessingException,
QgsProcessingParameterFile,
QgsProcessingParameterFileDestination,
)
from qgis import processing
from osgeo import ogr, gdal
class PDOKGeomFixer(QgsProcessingAlgorithm):
"""QGIS processing algorithm that forces counter-clockwise orientation of polygon geometries in Geopackage file"""
def tr(self, string):
"""
Returns a translatable string with the self.tr() function.
"""
return QCoreApplication.translate("Processing", string)
def createInstance(self):
# Must return a new copy of your algorithm.
return PDOKGeomFixer()
def name(self):
"""
Returns the unique algorithm name.
"""
return "pdok-geom-orientation-fixer"
def displayName(self):
"""
Returns the translated algorithm name.
"""
return self.tr("PDOK Geometry Orientation Fixer")
def group(self):
"""
Returns the name of the group this algorithm belongs to.
"""
return self.tr("PDOK Tools")
def groupId(self):
"""
Returns the unique ID of the group this algorithm belongs
to.
"""
return "pdok-tools"
def shortHelpString(self):
"""
Returns a localised short help string for the algorithm.
"""
return self.tr(
"This processing tool forces the orientation of polygon geometries to counter-clockwise (CCW) in the ouput GeoPackage file. Non-polygon layers are copied over to the output GeoPackage file.\n\
Parameters:\n\n\
- Input GeoPackage file\n\
- Output GeoPackage file\
"
)
def initAlgorithm(self, config=None):
"""
Here we define the inputs and outputs of the algorithm.
"""
self.INPUT = "INPUT" # recommended name for the main input parameter
self.OUTPUT = "OUTPUT" # recommended name for the main input parameter
self.addParameter(
QgsProcessingParameterFile(
self.INPUT, self.tr("Input GeoPackage file"), fileFilter="gpkg(*.gpkg)"
)
)
self.addParameter(
QgsProcessingParameterFileDestination(
self.OUTPUT,
self.tr("Output GeoPackage file"),
fileFilter="gpkg(*.gpkg)",
)
)
def processAlgorithm(self, parameters, context, feedback):
try:
# read out parameters
source_gpkg_path = self.parameterAsFile(parameters, self.INPUT, context)
target_gpkg_path = self.parameterAsFile(parameters, self.OUTPUT, context)
feedback.pushInfo(f"INFO: {source_gpkg_path}")
# read out
layer_list = []
source = ogr.Open(source_gpkg_path)
for i in source:
layer_list_item = {}
layer_name = i.GetName()
layer_list_item["name"] = layer_name
layer = source.GetLayer(layer_name)
# attributes = []
# ldefn = layer.GetLayerDefn()
# for n in range(ldefn.GetFieldCount()):
# fdefn = ldefn.GetFieldDefn(n)
# attributes.append(fdefn.name)
# gdef = ldefn.GetGeomFieldDefn(0)
# geom_name = gdef.name
# layer_list_item["attributes"] = attributes
# layer_list_item["geom_name"] = geom_name
feature = layer.GetNextFeature()
geometry = feature.GetGeometryRef()
geom_type = geometry.GetGeometryName()
layer_list_item["geom_type"] = geom_type
layer_list.append(layer_list_item)
gdal.UseExceptions()
gdal.SetConfigOption("CPL_DEBUG", "ON")
first = True
for layer in layer_list:
options = ["-lco", "GEOMETRY_NAME=geom"]
if not first:
options.extend(["-update", "-append"])
layer_name = layer["name"]
options.extend([layer_name])
gdoptions = gdal.VectorTranslateOptions(
format="GPKG",
options=options,
)
ds = gdal.VectorTranslate(
destNameOrDestDS=target_gpkg_path,
srcDS=source_gpkg_path,
options=gdoptions,
)
del ds
first = False
ogr.UseExceptions()
for layer in layer_list:
if not "POLYGON" in layer["geom_type"]:
next
layer_name = layer["name"]
driver = ogr.GetDriverByName("GPKG")
ogr_ds = driver.Open(target_gpkg_path, 1)
geom_name = "geom"
sql = f"UPDATE {layer_name} SET {geom_name} = ST_ForcePolygonCCW({geom_name})"
layer = ogr_ds.ExecuteSQL(sql)
del layer
return {
"Input folder path": source_gpkg_path,
"output_file": target_gpkg_path,
"layer_list": layer_list,
} # all processing algs must
except Exception as e:
raise QgsProcessingException(
f"Unexpected error occured while running PDOKGeomFixer: {str(e)}"
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment