From 340cf93f93fb28e1aa9e23b2d80a7c38e6a89d6c Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Mon, 17 Jul 2017 11:31:34 +1000 Subject: [PATCH] [FEATURE] New algorithms to add Z/M values to existing geometries Allows upgrading geometries to include these dimensions, or overwriting any existing Z/M values with a new value. Intended mostly as a test run for QgsProcessingFeatureBasedAlgorithm --- python/plugins/processing/algs/help/qgis.yaml | 9 ++ .../algs/qgis/QGISAlgorithmProvider.py | 4 + .../plugins/processing/algs/qgis/SetMValue.py | 86 ++++++++++++++++++ .../plugins/processing/algs/qgis/SetZValue.py | 86 ++++++++++++++++++ .../tests/testdata/expected/set_m_value.dbf | Bin 0 -> 2604 bytes .../tests/testdata/expected/set_m_value.prj | 1 + .../tests/testdata/expected/set_m_value.qpj | 1 + .../tests/testdata/expected/set_m_value.shp | Bin 0 -> 424 bytes .../tests/testdata/expected/set_m_value.shx | Bin 0 -> 172 bytes .../tests/testdata/expected/set_z_value.dbf | Bin 0 -> 2604 bytes .../tests/testdata/expected/set_z_value.prj | 1 + .../tests/testdata/expected/set_z_value.qpj | 1 + .../tests/testdata/expected/set_z_value.shp | Bin 0 -> 424 bytes .../tests/testdata/expected/set_z_value.shx | Bin 0 -> 172 bytes .../tests/testdata/qgis_algorithm_tests.yaml | 24 +++++ 15 files changed, 213 insertions(+) create mode 100644 python/plugins/processing/algs/qgis/SetMValue.py create mode 100644 python/plugins/processing/algs/qgis/SetZValue.py create mode 100644 python/plugins/processing/tests/testdata/expected/set_m_value.dbf create mode 100644 python/plugins/processing/tests/testdata/expected/set_m_value.prj create mode 100644 python/plugins/processing/tests/testdata/expected/set_m_value.qpj create mode 100644 python/plugins/processing/tests/testdata/expected/set_m_value.shp create mode 100644 python/plugins/processing/tests/testdata/expected/set_m_value.shx create mode 100644 python/plugins/processing/tests/testdata/expected/set_z_value.dbf create mode 100644 python/plugins/processing/tests/testdata/expected/set_z_value.prj create mode 100644 python/plugins/processing/tests/testdata/expected/set_z_value.qpj create mode 100644 python/plugins/processing/tests/testdata/expected/set_z_value.shp create mode 100644 python/plugins/processing/tests/testdata/expected/set_z_value.shx diff --git a/python/plugins/processing/algs/help/qgis.yaml b/python/plugins/processing/algs/help/qgis.yaml index 6bf5b08eab1..e04c83843e5 100755 --- a/python/plugins/processing/algs/help/qgis.yaml +++ b/python/plugins/processing/algs/help/qgis.yaml @@ -503,6 +503,10 @@ qgis:selectbyexpression: > qgis:selectbylocation: > This algorithm creates a selection in a vector layer. The criteria for selecting features is based on the spatial relationship between each feature and the features in an additional layer. +qgis:setmvalue: > + This algorithm sets the M value for geometries in a layer. + + If M values already exist in the layer, they will be overwritten with the new value. If no M values exist, the geometry will be upgraded to include M values and the specified value used as the initial M value for all geometries. qgis:setstyleforrasterlayer: > This algorithm sets the style of a raster layer. The style must be defined in a QML file. @@ -510,6 +514,11 @@ qgis:setstyleforrasterlayer: > qgis:setstyleforvectorlayer: > This algorithm sets the style of a vector layer. The style must be defined in a QML file. +qgis:setzvalue: > + This algorithm sets the Z value for geometries in a layer. + + If Z values already exist in the layer, they will be overwritten with the new value. If no Z values exist, the geometry will be upgraded to include Z values and the specified value used as the initial Z value for all geometries. + qgis:simplifygeometries: > This algorithm simplifies the geometries in a line or polygon layer. It creates a new layer with the same features as the ones in the input layer, but with geometries containing a lower number of vertices. diff --git a/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py b/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py index fde3c1757c7..200c322e046 100644 --- a/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py +++ b/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py @@ -89,6 +89,8 @@ from .SelectByAttribute import SelectByAttribute from .SelectByExpression import SelectByExpression from .ServiceAreaFromLayer import ServiceAreaFromLayer from .ServiceAreaFromPoint import ServiceAreaFromPoint +from .SetMValue import SetMValue +from .SetZValue import SetZValue from .ShortestPathLayerToPoint import ShortestPathLayerToPoint from .ShortestPathPointToLayer import ShortestPathPointToLayer from .ShortestPathPointToPoint import ShortestPathPointToPoint @@ -276,6 +278,8 @@ class QGISAlgorithmProvider(QgsProcessingProvider): SelectByExpression(), ServiceAreaFromLayer(), ServiceAreaFromPoint(), + SetMValue(), + SetZValue(), ShortestPathLayerToPoint(), ShortestPathPointToLayer(), ShortestPathPointToPoint(), diff --git a/python/plugins/processing/algs/qgis/SetMValue.py b/python/plugins/processing/algs/qgis/SetMValue.py new file mode 100644 index 00000000000..f22c02f14b8 --- /dev/null +++ b/python/plugins/processing/algs/qgis/SetMValue.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + SetMValue.py + -------------- + Date : July 2017 + Copyright : (C) 2017 by Nyall Dawson + Email : nyall dot dawson at gmail dot com +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +__author__ = 'Nyall Dawson' +__date__ = 'July 2017' +__copyright__ = '(C) 2017, Nyall Dawson' + +# This will get replaced with a git SHA1 when you do a git archive323 + +__revision__ = '$Format:%H$' + +import os + +from qgis.core import (QgsGeometry, + QgsWkbTypes, + QgsProcessingParameterNumber) + + +from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm + +pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0] + + +class SetMValue(QgisFeatureBasedAlgorithm): + + M_VALUE = 'M_VALUE' + + def group(self): + return self.tr('Vector geometry tools') + + def __init__(self): + super().__init__() + self.m_value = 0 + + def name(self): + return 'setmvalue' + + def displayName(self): + return self.tr('Set M Value') + + def outputName(self): + return self.tr('M Added') + + def tags(self): + return self.tr('set,add,m,measure,values').split(',') + + def initParameters(self, config=None): + self.addParameter(QgsProcessingParameterNumber(self.M_VALUE, + self.tr('M Value'), QgsProcessingParameterNumber.Double, defaultValue=0.0)) + + def outputWkbType(self, inputWkb): + return QgsWkbTypes.addM(inputWkb) + + def prepareAlgorithm(self, parameters, context, feedback): + self.m_value = self.parameterAsDouble(parameters, self.M_VALUE, context) + return True + + def processFeature(self, feature, feedback): + input_geometry = feature.geometry() + if input_geometry: + new_geom = input_geometry.geometry().clone() + if QgsWkbTypes.hasM(new_geom.wkbType()): + # addMValue won't alter existing M values, so drop them first + new_geom.dropMValue() + + new_geom.addMValue(self.m_value) + + feature.setGeometry(QgsGeometry(new_geom)) + + return True diff --git a/python/plugins/processing/algs/qgis/SetZValue.py b/python/plugins/processing/algs/qgis/SetZValue.py new file mode 100644 index 00000000000..1611be177c3 --- /dev/null +++ b/python/plugins/processing/algs/qgis/SetZValue.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + SetZValue.py + -------------- + Date : July 2017 + Copyright : (C) 2017 by Nyall Dawson + Email : nyall dot dawson at gmail dot com +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +__author__ = 'Nyall Dawson' +__date__ = 'July 2017' +__copyright__ = '(C) 2017, Nyall Dawson' + +# This will get replaced with a git SHA1 when you do a git archive323 + +__revision__ = '$Format:%H$' + +import os + +from qgis.core import (QgsGeometry, + QgsWkbTypes, + QgsProcessingParameterNumber) + + +from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm + +pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0] + + +class SetZValue(QgisFeatureBasedAlgorithm): + + Z_VALUE = 'Z_VALUE' + + def group(self): + return self.tr('Vector geometry tools') + + def __init__(self): + super().__init__() + self.z_value = 0 + + def name(self): + return 'setzvalue' + + def displayName(self): + return self.tr('Set Z Value') + + def outputName(self): + return self.tr('Z Added') + + def tags(self): + return self.tr('set,add,z,25d,3d,values').split(',') + + def initParameters(self, config=None): + self.addParameter(QgsProcessingParameterNumber(self.Z_VALUE, + self.tr('Z Value'), QgsProcessingParameterNumber.Double, defaultValue=0.0)) + + def outputWkbType(self, inputWkb): + return QgsWkbTypes.addZ(inputWkb) + + def prepareAlgorithm(self, parameters, context, feedback): + self.z_value = self.parameterAsDouble(parameters, self.Z_VALUE, context) + return True + + def processFeature(self, feature, feedback): + input_geometry = feature.geometry() + if input_geometry: + new_geom = input_geometry.geometry().clone() + if QgsWkbTypes.hasZ(new_geom.wkbType()): + # addZValue won't alter existing Z values, so drop them first + new_geom.dropZValue() + + new_geom.addZValue(self.z_value) + + feature.setGeometry(QgsGeometry(new_geom)) + + return True diff --git a/python/plugins/processing/tests/testdata/expected/set_m_value.dbf b/python/plugins/processing/tests/testdata/expected/set_m_value.dbf new file mode 100644 index 0000000000000000000000000000000000000000..cd3f0bb7691cb9cb8a8daaa04d276ca495dce4c6 GIT binary patch literal 2604 zcmd^;F$%&!5Jg8Uf`UcJ1#$w}teR+T?>p~8-~9F7n!RA_0-;RxYEg^sqYL}ktNgm9t4fwt)b Dg&0od literal 0 HcmV?d00001 diff --git a/python/plugins/processing/tests/testdata/expected/set_m_value.prj b/python/plugins/processing/tests/testdata/expected/set_m_value.prj new file mode 100644 index 00000000000..a30c00a55de --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/set_m_value.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] \ No newline at end of file diff --git a/python/plugins/processing/tests/testdata/expected/set_m_value.qpj b/python/plugins/processing/tests/testdata/expected/set_m_value.qpj new file mode 100644 index 00000000000..5fbc831e743 --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/set_m_value.qpj @@ -0,0 +1 @@ +GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]] diff --git a/python/plugins/processing/tests/testdata/expected/set_m_value.shp b/python/plugins/processing/tests/testdata/expected/set_m_value.shp new file mode 100644 index 0000000000000000000000000000000000000000..b3540dfa002aa6fb2438c6d59a5d5ab8147dbf31 GIT binary patch literal 424 zcmZvYI}(5(3`FDqQ#cmbS=f0Dy}2I3Ls)VIGaE9H5ejy)JeCBaeWd()-im1Xow-}A z?G){UN)`7t_|Ss=DQ5XYI8`vEWi(e640n{~&?z~pU~0>_9Mf244vguiwG3BSIzQg( Y*h=QoKk=8aV0z2IW6LmuW#o3se4Vcp`~Uy| literal 0 HcmV?d00001 diff --git a/python/plugins/processing/tests/testdata/expected/set_m_value.shx b/python/plugins/processing/tests/testdata/expected/set_m_value.shx new file mode 100644 index 0000000000000000000000000000000000000000..6a28b1d3ddd447b2e8137eccad9e42bb2482ca40 GIT binary patch literal 172 zcmZQzQ0HR64#HkAGcbr^$cY?)2q`!~Xbvb1;UP#Fs5qE50*dniu?v(AgVGsLx(Z77 OK>p~8-~9F7n!RA_0-;RxYEg^sqYL}ktNgm9t4fwt)b Dg&0od literal 0 HcmV?d00001 diff --git a/python/plugins/processing/tests/testdata/expected/set_z_value.prj b/python/plugins/processing/tests/testdata/expected/set_z_value.prj new file mode 100644 index 00000000000..a30c00a55de --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/set_z_value.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] \ No newline at end of file diff --git a/python/plugins/processing/tests/testdata/expected/set_z_value.qpj b/python/plugins/processing/tests/testdata/expected/set_z_value.qpj new file mode 100644 index 00000000000..5fbc831e743 --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/set_z_value.qpj @@ -0,0 +1 @@ +GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]] diff --git a/python/plugins/processing/tests/testdata/expected/set_z_value.shp b/python/plugins/processing/tests/testdata/expected/set_z_value.shp new file mode 100644 index 0000000000000000000000000000000000000000..e0f2a15aa22dbd03a9fbfa53986432019712d995 GIT binary patch literal 424 zcmZQzQ0HR64z9dlW?T=&0*!{qLP;i+GoW-8l