Skip to content

Commit

Permalink
[FEATURE][processing] New algorithm for translating (moving) points
Browse files Browse the repository at this point in the history
Allows geometries to be shifted by a x/y displacement
  • Loading branch information
nyalldawson committed Aug 14, 2016
1 parent a064c0a commit 0f268bf
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 1 deletion.
3 changes: 3 additions & 0 deletions python/plugins/processing/algs/help/qgis.yaml
Expand Up @@ -452,6 +452,9 @@ qgis:symmetricaldifference: >
qgis:texttofloat: >
This algorithm modifies the type of a given attribute in a vector layer, converting a text attribute containing numeric strings into a numeric attribute.

qgis:translate: >
This algorithm moves the geometries within a layer, by offsetting them with a specified x and y displacement.

qgis:union: >
This algorithm creates a layer containing all the features from both input layers. In the case of polygon layers, separate features are created for overlapping and non-overlapping features. The attribute table of the union layer contains attribute values from the respective input layer for non-overlapping features, and attribute values from both input layers for overlapping features.

Expand Down
4 changes: 3 additions & 1 deletion python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
Expand Up @@ -152,6 +152,7 @@
from .PointOnSurface import PointOnSurface
from .OffsetLine import OffsetLine
from .PolygonCentroids import PolygonCentroids
from .Translate import Translate

pluginPath = os.path.normpath(os.path.join(
os.path.split(os.path.dirname(__file__))[0], os.pardir))
Expand Down Expand Up @@ -205,7 +206,8 @@ def __init__(self):
RectanglesOvalsDiamondsVariable(),
RectanglesOvalsDiamondsFixed(), MergeLines(),
BoundingBox(), Boundary(), PointOnSurface(),
OffsetLine(), PolygonCentroids()
OffsetLine(), PolygonCentroids(),
Translate()
]

if hasMatplotlib:
Expand Down
94 changes: 94 additions & 0 deletions python/plugins/processing/algs/qgis/Translate.py
@@ -0,0 +1,94 @@
# -*- coding: utf-8 -*-

"""
***************************************************************************
Translate.py
--------------
Date : August 2016
Copyright : (C) 2016 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__ = 'August 2016'
__copyright__ = '(C) 2016, 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

from qgis.PyQt.QtGui import QIcon

from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector, ParameterSelection, ParameterNumber
from processing.core.outputs import OutputVector
from processing.tools import dataobjects, vector

pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]


class Translate(GeoAlgorithm):

INPUT_LAYER = 'INPUT_LAYER'
OUTPUT_LAYER = 'OUTPUT_LAYER'
DELTA_X = 'DELTA_X'
DELTA_Y = 'DELTA_Y'

def defineCharacteristics(self):
self.name, self.i18n_name = self.trAlgorithm('Translate geometry')
self.group, self.i18n_group = self.trAlgorithm('Vector geometry tools')

self.addParameter(ParameterVector(self.INPUT_LAYER,
self.tr('Input layer'), [ParameterVector.VECTOR_TYPE_ANY]))
self.addParameter(ParameterNumber(self.DELTA_X,
self.tr('Offset distance (x-axis)'), default=1.0))
self.addParameter(ParameterNumber(self.DELTA_Y,
self.tr('Offset distance (y-axis)'), default=0.0))

self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Translated')))

def processAlgorithm(self, progress):
layer = dataobjects.getObjectFromUri(
self.getParameterValue(self.INPUT_LAYER))

writer = self.getOutputFromName(
self.OUTPUT_LAYER).getVectorWriter(
layer.fields().toList(),
layer.wkbType(),
layer.crs())

delta_x = self.getParameterValue(self.DELTA_X)
delta_y = self.getParameterValue(self.DELTA_Y)

features = vector.features(layer)
total = 100.0 / len(features)

for current, input_feature in enumerate(features):
output_feature = input_feature
input_geometry = input_feature.geometry()
if input_geometry:
output_geometry = input_geometry
output_geometry.translate(delta_x, delta_y)
if not output_geometry:
raise GeoAlgorithmExecutionException(
self.tr('Error translating geometry'))

output_feature.setGeometry(output_geometry)

writer.addFeature(output_feature)
progress.setPercentage(int(current * total))

del writer
@@ -0,0 +1,15 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>lines_translated</Name>
<ElementPath>lines_translated</ElementPath>
<GeometryType>2</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>7</FeatureCount>
<ExtentXMin>-0.90000</ExtentXMin>
<ExtentXMax>11.10000</ExtentXMax>
<ExtentYMin>-3.20000</ExtentYMin>
<ExtentYMax>4.80000</ExtentYMax>
</DatasetSpecificInfo>
</GMLFeatureClass>
</GMLFeatureClassList>
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=""
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>-0.9</gml:X><gml:Y>-3.2</gml:Y></gml:coord>
<gml:coord><gml:X>11.1</gml:X><gml:Y>4.8</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:lines_translated fid="lines.0">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6.1,1.8 9.1,1.8 9.1,2.8 11.1,4.8</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:lines_translated>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_translated fid="lines.1">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-0.9,-1.2 1.1,-1.2</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:lines_translated>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_translated fid="lines.2">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2.1,-0.2 2.1,1.8 3.1,1.8 3.1,2.8</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:lines_translated>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_translated fid="lines.3">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3.1,0.8 5.1,0.8</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:lines_translated>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_translated fid="lines.4">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7.1,-3.2 10.1,-3.2</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:lines_translated>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_translated fid="lines.5">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6.1,-3.2 10.1,0.8</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:lines_translated>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_translated fid="lines.6">
</ogr:lines_translated>
</gml:featureMember>
</ogr:FeatureCollection>
12 changes: 12 additions & 0 deletions python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
Expand Up @@ -809,3 +809,15 @@ tests:
name: expected/centroid_polys.gml
type: vector

- algorithm: qgis:translategeometry
name: Lines translated
params:
DELTA_X: 0.1
DELTA_Y: -0.2
INPUT_LAYER:
name: lines.gml
type: vector
results:
OUTPUT_LAYER:
name: expected/lines_translated.gml
type: vector

0 comments on commit 0f268bf

Please sign in to comment.