Skip to content

Commit

Permalink
[FEATURE][processing] New algorithm to extend lines
Browse files Browse the repository at this point in the history
Allows extending linestrings by a set distance at the start
and end of the line
  • Loading branch information
nyalldawson committed Oct 30, 2016
1 parent 2b54582 commit 8dab2cd
Show file tree
Hide file tree
Showing 8 changed files with 229 additions and 1 deletion.
3 changes: 3 additions & 0 deletions python/plugins/processing/algs/help/qgis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ qgis:exportaddgeometrycolumns: >

Depending on the geometry type of the vector layer, the attributes added to the table will be different.

qgis:extendlines: >
This algorithms extends line geometries by a specified amount at the start and end of the line. Lines are extended using the bearing of the first and last segment in the line.

qgis:extractbyattribute: >
This algorithms creates a new vector layer that only contains matching features from an input layer. The criteria for adding features to the resulting layer is defined based on the values of an attribute from the input layer.

Expand Down
86 changes: 86 additions & 0 deletions python/plugins/processing/algs/qgis/ExtendLines.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-

"""
***************************************************************************
ExtendLines.py
--------------------
Date : October 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__ = 'October 2016'
__copyright__ = '(C) 2016, Nyall Dawson'

# This will get replaced with a git SHA1 when you do a git archive323

__revision__ = '$Format:%H$'


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


class ExtendLines(GeoAlgorithm):

INPUT_LAYER = 'INPUT_LAYER'
OUTPUT_LAYER = 'OUTPUT_LAYER'
START_DISTANCE = 'START_DISTANCE'
END_DISTANCE = 'END_DISTANCE'

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

self.addParameter(ParameterVector(self.INPUT_LAYER,
self.tr('Input layer'), [dataobjects.TYPE_VECTOR_LINE]))
self.addParameter(ParameterNumber(self.START_DISTANCE,
self.tr('Start distance'), default=0.0))
self.addParameter(ParameterNumber(self.END_DISTANCE,
self.tr('End distance'), default=0.0))

self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Extended lines')))

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

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

start_distance = self.getParameterValue(self.START_DISTANCE)
end_distance = self.getParameterValue(self.END_DISTANCE)

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.extendLine(start_distance, end_distance)
if not output_geometry:
raise GeoAlgorithmExecutionException(
self.tr('Error calculating extended line'))

output_feature.setGeometry(output_geometry)

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

del writer
3 changes: 2 additions & 1 deletion python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@
from .TinInterpolationAttribute import TinInterpolationAttribute
from .ZonalStatisticsQgis import ZonalStatisticsQgis
from .RemoveNullGeometry import RemoveNullGeometry
from .ExtendLines import ExtendLines

pluginPath = os.path.normpath(os.path.join(
os.path.split(os.path.dirname(__file__))[0], os.pardir))
Expand Down Expand Up @@ -232,7 +233,7 @@ def __init__(self):
ReliefAuto(), ZonalStatisticsQgis(),
IdwInterpolationZValue(), IdwInterpolationAttribute(),
TinInterpolationZValue(), TinInterpolationAttribute(),
RemoveNullGeometry(), ExtractByExpression()
RemoveNullGeometry(), ExtractByExpression(), ExtendLines()
]

if hasMatplotlib:
Expand Down
15 changes: 15 additions & 0 deletions python/plugins/processing/tests/testdata/expected/extend_lines.gfs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>extend_lines</Name>
<ElementPath>extend_lines</ElementPath>
<GeometryType>2</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>7</FeatureCount>
<ExtentXMin>-1.10000</ExtentXMin>
<ExtentXMax>11.14142</ExtentXMax>
<ExtentYMin>-3.07071</ExtentYMin>
<ExtentYMax>5.14142</ExtentYMax>
</DatasetSpecificInfo>
</GMLFeatureClass>
</GMLFeatureClassList>
48 changes: 48 additions & 0 deletions python/plugins/processing/tests/testdata/expected/extend_lines.gml
Original file line number Diff line number Diff line change
@@ -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>-1.1</gml:X><gml:Y>-3.070710678118655</gml:Y></gml:coord>
<gml:coord><gml:X>11.14142135623731</gml:X><gml:Y>5.141421356237309</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:extend_lines fid="lines.0">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5.9,2.0 9,2 9,3 11.141421356237309,5.141421356237309</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:extend_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extend_lines fid="lines.1">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-1.1,-1.0 1.2,-1.0</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:extend_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extend_lines fid="lines.2">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2.0,-0.1 2,2 3,2 3.0,3.2</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:extend_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extend_lines fid="lines.3">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2.9,1.0 5.2,1.0</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:extend_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extend_lines fid="lines.4">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6.9,-3.0 10.2,-3.0</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:extend_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extend_lines fid="lines.5">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5.929289321881345,-3.070710678118655 10.141421356237309,1.141421356237309</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:extend_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extend_lines fid="lines.6">
</ogr:extend_lines>
</gml:featureMember>
</ogr:FeatureCollection>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>extend_multilines</Name>
<ElementPath>extend_multilines</ElementPath>
<GeometryType>5</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>4</FeatureCount>
<ExtentXMin>-1.20000</ExtentXMin>
<ExtentXMax>5.98034</ExtentXMax>
<ExtentYMin>-1.00000</ExtentYMin>
<ExtentYMax>4.13130</ExtentYMax>
</DatasetSpecificInfo>
</GMLFeatureClass>
</GMLFeatureClassList>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?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>-1.2</gml:X><gml:Y>-1</gml:Y></gml:coord>
<gml:coord><gml:X>5.980337387043503</gml:X><gml:Y>4.131303337656388</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:extend_multilines fid="lines.1">
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>-1.2,-1.0 1.4,-1.0</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:extend_multilines>
</gml:featureMember>
<gml:featureMember>
<ogr:extend_multilines fid="lines.2">
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>2.8,1.0 5.4,1.0</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>5.027602565068266,2.614750056493599 4.993163391936403,0.600058428279599</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:extend_multilines>
</gml:featureMember>
<gml:featureMember>
<ogr:extend_multilines fid="lines.3">
</ogr:extend_multilines>
</gml:featureMember>
<gml:featureMember>
<ogr:extend_multilines fid="lines.4">
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>2.0,-0.2 2,2 3,2 3.0,3.4</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>2.744420970065991,4.041450058619024 5.859334643361299,4.131303337656388</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>2.800042438915868,3.004119922970864 5.980337387043503,2.938593167493973</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:extend_multilines>
</gml:featureMember>
</ogr:FeatureCollection>
27 changes: 27 additions & 0 deletions python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1225,3 +1225,30 @@ tests:
OUTPUT:
name: expected/extract_expression.gml
type: vector

- algorithm: qgis:extendlines
name: Extend lines
params:
END_DISTANCE: 0.2
INPUT_LAYER:
name: lines.gml
type: vector
START_DISTANCE: 0.1
results:
OUTPUT_LAYER:
name: expected/extend_lines.gml
type: vector


- algorithm: qgis:extendlines
name: Extend multilines
params:
END_DISTANCE: 0.4
INPUT_LAYER:
name: multilines.gml
type: vector
START_DISTANCE: 0.2
results:
OUTPUT_LAYER:
name: expected/extend_multilines.gml
type: vector

0 comments on commit 8dab2cd

Please sign in to comment.