Skip to content
Permalink
Browse files

[FEATURE][processing] Extract nodes algorithm now saves node

index, distance along line and angle at node

Also correctly handles null geometries
  • Loading branch information
nyalldawson committed Aug 29, 2016
1 parent 986b531 commit 9fa4e776dbf2ba5004583be1bcb0e8eb8c343301
@@ -166,6 +166,8 @@ qgis:extractbylocation: >
qgis:extractnodes: >
This algorithm takes a line or polygon layer and generates a point layer with points representing the nodes in the input lines or polygons. The attributes associated to each point are the same ones associated to the line or polygon that the point belongs to.

Additional fields are added to the nodes indicating the node index (beginning at 0), distance along original geometry and bisector angle of node for original geometry.

qgis:fieldcalculator: >
This algorithm computes a new vector layer with the same features of the input layer, but with an additional attribute. The values of this new attribute are computed from each feature using a mathematical formula, based on te properties and attributes of the feature.

@@ -26,10 +26,12 @@
__revision__ = '$Format:%H$'

import os
import math

from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtCore import QVariant

from qgis.core import Qgis, QgsFeature, QgsGeometry, QgsWkbTypes
from qgis.core import QgsFeature, QgsGeometry, QgsWkbTypes, QgsField

from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.parameters import ParameterVector
@@ -61,25 +63,34 @@ def processAlgorithm(self, progress):
layer = dataobjects.getObjectFromUri(
self.getParameterValue(self.INPUT))

writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
layer.fields().toList(), QgsWkbTypes.Point, layer.crs())
fields = layer.fields()
fields.append(QgsField('node_index', QVariant.Int))
fields.append(QgsField('distance', QVariant.Double))
fields.append(QgsField('angle', QVariant.Double))

outFeat = QgsFeature()
inGeom = QgsGeometry()
outGeom = QgsGeometry()
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
fields, QgsWkbTypes.Point, layer.crs())

features = vector.features(layer)
total = 100.0 / len(features)
for current, f in enumerate(features):
inGeom = f.geometry()
attrs = f.attributes()

points = vector.extractPoints(inGeom)
outFeat.setAttributes(attrs)

for i in points:
outFeat.setGeometry(outGeom.fromPoint(i))
writer.addFeature(outFeat)
input_geometry = f.geometry()
if not input_geometry:
writer.addFeature(f)
else:
points = vector.extractPoints(input_geometry)

for i, point in enumerate(points):
distance = input_geometry.distanceToVertex(i)
angle = math.degrees(input_geometry.angleAtVertex(i))
attrs = f.attributes()
attrs.append(i)
attrs.append(distance)
attrs.append(angle)
output_feature = QgsFeature()
output_feature.setAttributes(attrs)
output_feature.setGeometry(QgsGeometry.fromPoint(point))
writer.addFeature(output_feature)

progress.setPercentage(int(current * total))

@@ -0,0 +1,25 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>extract_nodes_lines</Name>
<ElementPath>extract_nodes_lines</ElementPath>
<GeometryType>1</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>17</FeatureCount>
<ExtentXMin>-1.00000</ExtentXMin>
<ExtentXMax>11.00000</ExtentXMax>
<ExtentYMin>-3.00000</ExtentYMin>
<ExtentYMax>5.00000</ExtentYMax>
</DatasetSpecificInfo>
<PropertyDefn>
<Name>distance</Name>
<ElementPath>distance</ElementPath>
<Type>Real</Type>
</PropertyDefn>
<PropertyDefn>
<Name>angle</Name>
<ElementPath>angle</ElementPath>
<Type>Real</Type>
</PropertyDefn>
</GMLFeatureClass>
</GMLFeatureClassList>
@@ -0,0 +1,146 @@
<?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</gml:X><gml:Y>-3</gml:Y></gml:coord>
<gml:coord><gml:X>11</gml:X><gml:Y>5</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.0">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>6,2</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:node_index>0</ogr:node_index>
<ogr:distance>0</ogr:distance>
<ogr:angle>90</ogr:angle>
</ogr:extract_nodes_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.0">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>9,2</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:node_index>1</ogr:node_index>
<ogr:distance>3</ogr:distance>
<ogr:angle>45</ogr:angle>
</ogr:extract_nodes_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.0">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>9,3</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:node_index>2</ogr:node_index>
<ogr:distance>4</ogr:distance>
<ogr:angle>22.5</ogr:angle>
</ogr:extract_nodes_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.0">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>11,5</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:node_index>3</ogr:node_index>
<ogr:distance>6.82842712474619</ogr:distance>
<ogr:angle>45</ogr:angle>
</ogr:extract_nodes_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.1">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>-1,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:node_index>0</ogr:node_index>
<ogr:distance>0</ogr:distance>
<ogr:angle>90</ogr:angle>
</ogr:extract_nodes_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.1">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,-1</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:node_index>1</ogr:node_index>
<ogr:distance>2</ogr:distance>
<ogr:angle>90</ogr:angle>
</ogr:extract_nodes_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.2">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,0</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:node_index>0</ogr:node_index>
<ogr:distance>0</ogr:distance>
<ogr:angle>0</ogr:angle>
</ogr:extract_nodes_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.2">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,2</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:node_index>1</ogr:node_index>
<ogr:distance>2</ogr:distance>
<ogr:angle>45</ogr:angle>
</ogr:extract_nodes_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.2">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,2</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:node_index>2</ogr:node_index>
<ogr:distance>3</ogr:distance>
<ogr:angle>45</ogr:angle>
</ogr:extract_nodes_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.2">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,3</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:node_index>3</ogr:node_index>
<ogr:distance>4</ogr:distance>
<ogr:angle>0</ogr:angle>
</ogr:extract_nodes_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.3">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,1</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:node_index>0</ogr:node_index>
<ogr:distance>0</ogr:distance>
<ogr:angle>90</ogr:angle>
</ogr:extract_nodes_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.3">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>5,1</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:node_index>1</ogr:node_index>
<ogr:distance>2</ogr:distance>
<ogr:angle>90</ogr:angle>
</ogr:extract_nodes_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.4">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7,-3</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:node_index>0</ogr:node_index>
<ogr:distance>0</ogr:distance>
<ogr:angle>90</ogr:angle>
</ogr:extract_nodes_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.4">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>10,-3</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:node_index>1</ogr:node_index>
<ogr:distance>3</ogr:distance>
<ogr:angle>90</ogr:angle>
</ogr:extract_nodes_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.5">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>6,-3</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:node_index>0</ogr:node_index>
<ogr:distance>0</ogr:distance>
<ogr:angle>45</ogr:angle>
</ogr:extract_nodes_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.5">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>10,1</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:node_index>1</ogr:node_index>
<ogr:distance>5.65685424949238</ogr:distance>
<ogr:angle>45</ogr:angle>
</ogr:extract_nodes_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:extract_nodes_lines fid="lines.6">
</ogr:extract_nodes_lines>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,25 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>extract_nodes_multilines</Name>
<ElementPath>extract_nodes_multilines</ElementPath>
<GeometryType>1</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>15</FeatureCount>
<ExtentXMin>-1.00000</ExtentXMin>
<ExtentXMax>5.58042</ExtentXMax>
<ExtentYMin>-1.00000</ExtentYMin>
<ExtentYMax>4.11977</ExtentYMax>
</DatasetSpecificInfo>
<PropertyDefn>
<Name>distance</Name>
<ElementPath>distance</ElementPath>
<Type>Real</Type>
</PropertyDefn>
<PropertyDefn>
<Name>angle</Name>
<ElementPath>angle</ElementPath>
<Type>Real</Type>
</PropertyDefn>
</GMLFeatureClass>
</GMLFeatureClassList>

0 comments on commit 9fa4e77

Please sign in to comment.
You can’t perform that action at this time.