Skip to content
Permalink
Browse files

Merge pull request #3371 from nyalldawson/processing

[processing] New algs + a fix
  • Loading branch information
nyalldawson committed Aug 10, 2016
2 parents 0a2dd93 + 142de7c commit d5516fa7e325dcf9904a056a30c5e98b4cece6ae
Showing with 1,512 additions and 2 deletions.
  1. +10 −0 python/plugins/processing/algs/help/qgis.yaml
  2. +97 −0 python/plugins/processing/algs/qgis/Boundary.py
  3. +86 −0 python/plugins/processing/algs/qgis/BoundingBox.py
  4. +83 −0 python/plugins/processing/algs/qgis/PointOnSurface.py
  5. +5 −1 python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
  6. +48 −0 python/plugins/processing/tests/testdata/expected/lines_boundary.gml
  7. +23 −0 python/plugins/processing/tests/testdata/expected/lines_boundary.xsd
  8. +48 −0 python/plugins/processing/tests/testdata/expected/lines_bounds.gml
  9. +23 −0 python/plugins/processing/tests/testdata/expected/lines_bounds.xsd
  10. +33 −0 python/plugins/processing/tests/testdata/expected/multiline_boundary.gml
  11. +23 −0 python/plugins/processing/tests/testdata/expected/multiline_boundary.xsd
  12. +33 −0 python/plugins/processing/tests/testdata/expected/multiline_bounds.gml
  13. +23 −0 python/plugins/processing/tests/testdata/expected/multiline_bounds.xsd
  14. +43 −0 python/plugins/processing/tests/testdata/expected/multipoint_bounds.gml
  15. +30 −0 python/plugins/processing/tests/testdata/expected/multipoint_bounds.xsd
  16. +42 −0 python/plugins/processing/tests/testdata/expected/multipoly_boundary.gml
  17. +43 −0 python/plugins/processing/tests/testdata/expected/multipoly_boundary.xsd
  18. +42 −0 python/plugins/processing/tests/testdata/expected/multipoly_bounds.gml
  19. +43 −0 python/plugins/processing/tests/testdata/expected/multipoly_bounds.xsd
  20. +59 −0 python/plugins/processing/tests/testdata/expected/point_bounds.gml
  21. +23 −0 python/plugins/processing/tests/testdata/expected/point_bounds.xsd
  22. +48 −0 python/plugins/processing/tests/testdata/expected/point_on_line.gml
  23. +23 −0 python/plugins/processing/tests/testdata/expected/point_on_line.xsd
  24. +43 −0 python/plugins/processing/tests/testdata/expected/point_on_multipoint.gml
  25. +30 −0 python/plugins/processing/tests/testdata/expected/point_on_multipoint.xsd
  26. +58 −0 python/plugins/processing/tests/testdata/expected/point_on_poly.gml
  27. +43 −0 python/plugins/processing/tests/testdata/expected/point_on_poly.xsd
  28. +58 −0 python/plugins/processing/tests/testdata/expected/poly_boundary.gml
  29. +43 −0 python/plugins/processing/tests/testdata/expected/poly_boundary.xsd
  30. +58 −0 python/plugins/processing/tests/testdata/expected/poly_bounds.gml
  31. +43 −0 python/plugins/processing/tests/testdata/expected/poly_bounds.xsd
  32. +19 −0 python/plugins/processing/tests/testdata/multipoints.gfs
  33. +43 −0 python/plugins/processing/tests/testdata/multipoints.gml
  34. +142 −0 python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
  35. +1 −1 python/plugins/processing/tools/vector.py
@@ -33,6 +33,12 @@ qgis:basicstatisticsfortextfields: >

Statistics are generated as an HTML file.

qgis:boundary: >
Returns the closure of the combinatorial boundary of the input geometries (ie the topological boundary of the geometry). For instance, a polygon geometry will have a boundary consisting of the linestrings for each ring in the polygon. Only valid for polygon or line layers.

qgis:boundingboxes: >
This algorithm calculates the bounding box (envelope) of each feature in an input layer.

qgis:buildvirtualvector: >
This algorithm creates a virtual layer that contains a set of vector layer.

@@ -259,6 +265,10 @@ qgis:orientedminimumboundingbox: >
qgis:pointsdisplacement:


qgis:pointonsurface: >
Returns a point guaranteed to lie on the surface of a geometry.


qgis:pointslayerfromtable: >
This algorithm generates a points layer based on the values from an input table.

@@ -0,0 +1,97 @@
# -*- coding: utf-8 -*-

"""
***************************************************************************
Boundary.py
--------------
Date : July 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__ = 'July 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
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 Boundary(GeoAlgorithm):

INPUT_LAYER = 'INPUT_LAYER'
OUTPUT_LAYER = 'OUTPUT_LAYER'

def getIcon(self):
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'convex_hull.png'))

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

self.addParameter(ParameterVector(self.INPUT_LAYER,
self.tr('Input layer'), [ParameterVector.VECTOR_TYPE_LINE,
ParameterVector.VECTOR_TYPE_POLYGON]))
self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Boundary')))

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

input_wkb = layer.wkbType()
if QgsWkbTypes.geometryType(input_wkb) == QgsWkbTypes.LineGeometry:
output_wkb = QgsWkbTypes.MultiPoint
elif QgsWkbTypes.geometryType(input_wkb) == QgsWkbTypes.PolygonGeometry:
output_wkb = QgsWkbTypes.MultiLineString
if QgsWkbTypes.hasZ(input_wkb):
output_wkb = QgsWkbTypes.addZ(output_wkb)
if QgsWkbTypes.hasM(input_wkb):
output_wkb = QgsWkbTypes.addM(output_wkb)

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

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 = QgsGeometry(input_geometry.geometry().boundary())
if not output_geometry:
raise GeoAlgorithmExecutionException(
self.tr('Error calculating boundary'))

output_feature.setGeometry(output_geometry)

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

del writer
@@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-

"""
***************************************************************************
BoundingBox.py
--------------
Date : July 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__ = 'July 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
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 BoundingBox(GeoAlgorithm):

INPUT_LAYER = 'INPUT_LAYER'
OUTPUT_LAYER = 'OUTPUT_LAYER'

def getIcon(self):
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'matrix.png'))

def defineCharacteristics(self):
self.name, self.i18n_name = self.trAlgorithm('Bounding boxes')
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.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Bounds')))

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

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

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 = QgsGeometry.fromRect(input_geometry.boundingBox())
if not output_geometry:
raise GeoAlgorithmExecutionException(
self.tr('Error calculating bounding box'))

output_feature.setGeometry(output_geometry)

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

del writer
@@ -0,0 +1,83 @@
# -*- coding: utf-8 -*-

"""
***************************************************************************
PointOnSurface.py
--------------
Date : July 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__ = 'July 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
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 PointOnSurface(GeoAlgorithm):

INPUT_LAYER = 'INPUT_LAYER'
OUTPUT_LAYER = 'OUTPUT_LAYER'

def defineCharacteristics(self):
self.name, self.i18n_name = self.trAlgorithm('Point on surface')
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.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Point')))

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

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

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.pointOnSurface()
if not output_geometry:
raise GeoAlgorithmExecutionException(
self.tr('Error calculating point on surface'))

output_feature.setGeometry(output_geometry)

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

del writer
@@ -147,6 +147,9 @@
from .RectanglesOvalsDiamondsVariable import RectanglesOvalsDiamondsVariable
from .RectanglesOvalsDiamondsFixed import RectanglesOvalsDiamondsFixed
from .MergeLines import MergeLines
from .BoundingBox import BoundingBox
from .Boundary import Boundary
from .PointOnSurface import PointOnSurface

pluginPath = os.path.normpath(os.path.join(
os.path.split(os.path.dirname(__file__))[0], os.pardir))
@@ -198,7 +201,8 @@ def __init__(self):
CheckValidity(), OrientedMinimumBoundingBox(), Smooth(),
ReverseLineDirection(), SpatialIndex(), DefineProjection(),
RectanglesOvalsDiamondsVariable(),
RectanglesOvalsDiamondsFixed(), MergeLines()
RectanglesOvalsDiamondsFixed(), MergeLines(),
BoundingBox(), Boundary(), PointOnSurface()
]

if hasMatplotlib:
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ogr.maptools.org/ lines_boundary.xsd"
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:lines_boundary fid="lines.0">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>6,2</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>11,5</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
</ogr:lines_boundary>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_boundary fid="lines.1">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>-1,-1</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>1,-1</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
</ogr:lines_boundary>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_boundary fid="lines.2">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>2,0</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>3,3</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
</ogr:lines_boundary>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_boundary fid="lines.3">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>3,1</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>5,1</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
</ogr:lines_boundary>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_boundary fid="lines.4">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>7,-3</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>10,-3</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
</ogr:lines_boundary>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_boundary fid="lines.5">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>6,-3</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>10,1</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
</ogr:lines_boundary>
</gml:featureMember>
<gml:featureMember>
<ogr:lines_boundary fid="lines.6">
</ogr:lines_boundary>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
<xs:complexType name="FeatureCollectionType">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureCollectionType">
<xs:attribute name="lockId" type="xs:string" use="optional"/>
<xs:attribute name="scope" type="xs:string" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="lines_boundary" type="ogr:lines_boundary_Type" substitutionGroup="gml:_Feature"/>
<xs:complexType name="lines_boundary_Type">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="geometryProperty" type="gml:MultiPointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>

0 comments on commit d5516fa

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