Skip to content

Commit

Permalink
Merge pull request #4936 from nyalldawson/algs
Browse files Browse the repository at this point in the history
Restore more processing algs
  • Loading branch information
nyalldawson committed Jul 28, 2017
2 parents fbff452 + e829092 commit 9763b60
Show file tree
Hide file tree
Showing 19 changed files with 621 additions and 536 deletions.
1 change: 1 addition & 0 deletions doc/api_break.dox
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -1242,6 +1242,7 @@ empty geometry collection)
- avoidIntersections() got an extra argument: list of layers to include in the operation (previously read from active QgsProject) - avoidIntersections() got an extra argument: list of layers to include in the operation (previously read from active QgsProject)
- isGeosEmpty() was removed. Use isEmpty() instead. - isGeosEmpty() was removed. Use isEmpty() instead.
- reshapeGeometry() expects QgsLineString as a parameter instead of a list of 2D points (so that it can support 3D geometries) - reshapeGeometry() expects QgsLineString as a parameter instead of a list of 2D points (so that it can support 3D geometries)
- vertexAt() now returns a QgsPoint (previously QgsPointV2) instead of a QgsPointXY (previously QgsPoint)




QgsGeometryAnalyzer {#qgis_api_break_3_0_QgsGeometryAnalyzer} QgsGeometryAnalyzer {#qgis_api_break_3_0_QgsGeometryAnalyzer}
Expand Down
6 changes: 3 additions & 3 deletions python/core/geometry/qgsgeometry.sip
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -326,12 +326,12 @@ Returns true if WKB of the geometry is of WKBMulti* type
:rtype: bool :rtype: bool
%End %End


QgsPointXY vertexAt( int atVertex ) const; QgsPoint vertexAt( int atVertex ) const;
%Docstring %Docstring
Returns coordinates of a vertex. Returns coordinates of a vertex.
\param atVertex index of the vertex \param atVertex index of the vertex
:return: Coordinates of the vertex or QgsPointXY(0,0) on error :return: Coordinates of the vertex or QgsPoint(0,0) on error
:rtype: QgsPointXY :rtype: QgsPoint
%End %End


double sqrDistToVertexAt( QgsPointXY &point /In/, int atVertex ) const; double sqrDistToVertexAt( QgsPointXY &point /In/, int atVertex ) const;
Expand Down
31 changes: 22 additions & 9 deletions python/plugins/processing/algs/qgis/Buffer.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -25,25 +25,35 @@


__revision__ = '$Format:%H$' __revision__ = '$Format:%H$'


from qgis.core import QgsFeature, QgsGeometry, QgsProcessingUtils from qgis.core import (QgsFeature,
QgsGeometry,
QgsFeatureRequest,
QgsFeatureSink)




def buffering(feedback, context, writer, distance, field, useField, layer, dissolve, segments, endCapStyle=1, def buffering(feedback, context, sink, distance, field, useField, source, dissolve, segments, endCapStyle=1,
joinStyle=1, mitreLimit=2): joinStyle=1, mitreLimit=2):


if useField: if useField:
field = layer.fields().lookupField(field) field = source.fields().lookupField(field)


outFeat = QgsFeature() outFeat = QgsFeature()


current = 0 current = 0
features = QgsProcessingUtils.getFeatures(layer, context) total = 100.0 / source.featureCount() if source.featureCount() else 0
total = 100.0 / layer.featureCount() if layer.featureCount() else 0


# With dissolve # With dissolve
if dissolve: if dissolve:
attributes_to_fetch = []
if useField:
attributes_to_fetch.append(field)

features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(attributes_to_fetch))
buffered_geometries = [] buffered_geometries = []
for inFeat in features: for inFeat in features:
if feedback.isCanceled():
break

attrs = inFeat.attributes() attrs = inFeat.attributes()
if useField: if useField:
value = attrs[field] value = attrs[field]
Expand All @@ -60,10 +70,15 @@ def buffering(feedback, context, writer, distance, field, useField, layer, disso
final_geometry = QgsGeometry.unaryUnion(buffered_geometries) final_geometry = QgsGeometry.unaryUnion(buffered_geometries)
outFeat.setGeometry(final_geometry) outFeat.setGeometry(final_geometry)
outFeat.setAttributes(attrs) outFeat.setAttributes(attrs)
writer.addFeature(outFeat, QgsFeatureSink.FastInsert) sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
else: else:

features = source.getFeatures()

# Without dissolve # Without dissolve
for inFeat in features: for inFeat in features:
if feedback.isCanceled():
break
attrs = inFeat.attributes() attrs = inFeat.attributes()
if useField: if useField:
value = attrs[field] value = attrs[field]
Expand All @@ -74,8 +89,6 @@ def buffering(feedback, context, writer, distance, field, useField, layer, disso
outGeom = inGeom.buffer(float(value), segments, endCapStyle, joinStyle, mitreLimit) outGeom = inGeom.buffer(float(value), segments, endCapStyle, joinStyle, mitreLimit)
outFeat.setGeometry(outGeom) outFeat.setGeometry(outGeom)
outFeat.setAttributes(attrs) outFeat.setAttributes(attrs)
writer.addFeature(outFeat, QgsFeatureSink.FastInsert) sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
current += 1 current += 1
feedback.setProgress(int(current * total)) feedback.setProgress(int(current * total))

del writer
79 changes: 41 additions & 38 deletions python/plugins/processing/algs/qgis/ConvexHull.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@
QgsFeatureSink, QgsFeatureSink,
QgsGeometry, QgsGeometry,
QgsWkbTypes, QgsWkbTypes,
QgsProcessingUtils, QgsFeatureRequest,
QgsFields, QgsFields,
NULL) NULL,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterField,
QgsProcessingParameterFeatureSink,
QgsProcessing,
QgsProcessingException)


from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterTableField
from processing.core.parameters import ParameterSelection
from processing.core.outputs import OutputVector
from processing.tools import dataobjects, vector from processing.tools import dataobjects, vector


pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0] pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
Expand All @@ -56,7 +56,6 @@ class ConvexHull(QgisAlgorithm):
INPUT = 'INPUT' INPUT = 'INPUT'
OUTPUT = 'OUTPUT' OUTPUT = 'OUTPUT'
FIELD = 'FIELD' FIELD = 'FIELD'
METHOD = 'METHOD'


def icon(self): def icon(self):
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'convex_hull.png')) return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'convex_hull.png'))
Expand All @@ -68,17 +67,12 @@ def __init__(self):
super().__init__() super().__init__()


def initAlgorithm(self, config=None): def initAlgorithm(self, config=None):
self.methods = [self.tr('Create single minimum convex hull'), self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
self.tr('Create convex hulls based on field')] self.tr('Input layer')))

self.addParameter(QgsProcessingParameterField(self.FIELD,
self.addParameter(ParameterVector(self.INPUT, self.tr('Field (optional, set if creating convex hulls by classes)'),
self.tr('Input layer'))) parentLayerParameterName=self.INPUT, optional=True))
self.addParameter(ParameterTableField(self.FIELD, self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Convex hull'), QgsProcessing.TypeVectorPolygon))
self.tr('Field (optional, only used if creating convex hulls by classes)'),
self.INPUT, optional=True))
self.addParameter(ParameterSelection(self.METHOD,
self.tr('Method'), self.methods))
self.addOutput(OutputVector(self.OUTPUT, self.tr('Convex hull'), datatype=[dataobjects.TYPE_VECTOR_POLYGON]))


def name(self): def name(self):
return 'convexhull' return 'convexhull'
Expand All @@ -87,14 +81,15 @@ def displayName(self):
return self.tr('Convex hull') return self.tr('Convex hull')


def processAlgorithm(self, parameters, context, feedback): def processAlgorithm(self, parameters, context, feedback):
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context) source = self.parameterAsSource(parameters, self.INPUT, context)
useField = self.getParameterValue(self.METHOD) == 1 fieldName = self.parameterAsString(parameters, self.FIELD, context)
fieldName = self.getParameterValue(self.FIELD) useField = bool(fieldName)


field_index = None
f = QgsField('value', QVariant.String, '', 255) f = QgsField('value', QVariant.String, '', 255)
if useField: if useField:
index = layer.fields().lookupField(fieldName) field_index = source.fields().lookupField(fieldName)
fType = layer.fields()[index].type() fType = source.fields()[field_index].type()
if fType in [QVariant.Int, QVariant.UInt, QVariant.LongLong, QVariant.ULongLong]: if fType in [QVariant.Int, QVariant.UInt, QVariant.LongLong, QVariant.ULongLong]:
f.setType(fType) f.setType(fType)
f.setLength(20) f.setLength(20)
Expand All @@ -112,25 +107,30 @@ def processAlgorithm(self, parameters, context, feedback):
fields.append(QgsField('area', QVariant.Double, '', 20, 6)) fields.append(QgsField('area', QVariant.Double, '', 20, 6))
fields.append(QgsField('perim', QVariant.Double, '', 20, 6)) fields.append(QgsField('perim', QVariant.Double, '', 20, 6))


writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.Polygon, layer.crs(), context) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
fields, QgsWkbTypes.Polygon, source.sourceCrs())


outFeat = QgsFeature() outFeat = QgsFeature()
inGeom = QgsGeometry()
outGeom = QgsGeometry() outGeom = QgsGeometry()


fid = 0 fid = 0
val = None val = None
features = QgsProcessingUtils.getFeatures(layer, context)
if useField: if useField:
unique = layer.uniqueValues(index) unique = source.uniqueValues(field_index)
current = 0 current = 0
total = 100.0 / (layer.featureCount() * len(unique)) if layer.featureCount() else 1 total = 100.0 / (source.featureCount() * len(unique)) if source.featureCount() else 1
for i in unique: for i in unique:
if feedback.isCanceled():
break

first = True first = True
hull = [] hull = []
features = QgsProcessingUtils.getFeatures(layer, context) features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([field_index]))
for f in features: for f in features:
idVar = f[fieldName] if feedback.isCanceled():
break

idVar = f.attributes()[field_index]
if str(idVar).strip() == str(i).strip(): if str(idVar).strip() == str(i).strip():
if first: if first:
val = idVar val = idVar
Expand All @@ -154,16 +154,19 @@ def processAlgorithm(self, parameters, context, feedback):
perim = NULL perim = NULL
outFeat.setGeometry(outGeom) outFeat.setGeometry(outGeom)
outFeat.setAttributes([fid, val, area, perim]) outFeat.setAttributes([fid, val, area, perim])
writer.addFeature(outFeat, QgsFeatureSink.FastInsert) sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
except: except:
raise GeoAlgorithmExecutionException( raise QgsProcessingException(
self.tr('Exception while computing convex hull')) self.tr('Exception while computing convex hull'))
fid += 1 fid += 1
else: else:
hull = [] hull = []
total = 100.0 / layer.featureCount() if layer.featureCount() else 1 total = 100.0 / source.featureCount() if source.featureCount() else 1
features = QgsProcessingUtils.getFeatures(layer, context) features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]))
for current, f in enumerate(features): for current, f in enumerate(features):
if feedback.isCanceled():
break

inGeom = f.geometry() inGeom = f.geometry()
points = vector.extractPoints(inGeom) points = vector.extractPoints(inGeom)
hull.extend(points) hull.extend(points)
Expand All @@ -180,9 +183,9 @@ def processAlgorithm(self, parameters, context, feedback):
perim = NULL perim = NULL
outFeat.setGeometry(outGeom) outFeat.setGeometry(outGeom)
outFeat.setAttributes([0, 'all', area, perim]) outFeat.setAttributes([0, 'all', area, perim])
writer.addFeature(outFeat, QgsFeatureSink.FastInsert) sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
except: except:
raise GeoAlgorithmExecutionException( raise QgsProcessingException(
self.tr('Exception while computing convex hull')) self.tr('Exception while computing convex hull'))


del writer return {self.OUTPUT: dest_id}
40 changes: 22 additions & 18 deletions python/plugins/processing/algs/qgis/DeleteDuplicateGeometries.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@
__revision__ = '$Format:%H$' __revision__ = '$Format:%H$'


from qgis.core import (QgsFeatureRequest, from qgis.core import (QgsFeatureRequest,
QgsApplication,
QgsFeatureSink, QgsFeatureSink,
QgsProcessingUtils) QgsProcessingParameterFeatureSource,
QgsProcessingParameterFeatureSink)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.core.parameters import ParameterVector
from processing.core.outputs import OutputVector




class DeleteDuplicateGeometries(QgisAlgorithm): class DeleteDuplicateGeometries(QgisAlgorithm):
Expand All @@ -46,9 +44,9 @@ def __init__(self):
super().__init__() super().__init__()


def initAlgorithm(self, config=None): def initAlgorithm(self, config=None):
self.addParameter(ParameterVector(self.INPUT, self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
self.tr('Input layer'))) self.tr('Input layer')))
self.addOutput(OutputVector(self.OUTPUT, self.tr('Cleaned'))) self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Cleaned')))


def name(self): def name(self):
return 'deleteduplicategeometries' return 'deleteduplicategeometries'
Expand All @@ -57,23 +55,26 @@ def displayName(self):
return self.tr('Delete duplicate geometries') return self.tr('Delete duplicate geometries')


def processAlgorithm(self, parameters, context, feedback): def processAlgorithm(self, parameters, context, feedback):
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context) source = self.parameterAsSource(parameters, self.INPUT, context)
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
source.fields(), source.wkbType(), source.sourceCrs())


fields = layer.fields() features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]))

total = 100.0 / source.featureCount() if source.featureCount() else 0
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, layer.wkbType(), layer.crs(), context)

features = QgsProcessingUtils.getFeatures(layer, context)

total = 100.0 / layer.featureCount() if layer.featureCount() else 0
geoms = dict() geoms = dict()
for current, f in enumerate(features): for current, f in enumerate(features):
if feedback.isCanceled():
break

geoms[f.id()] = f.geometry() geoms[f.id()] = f.geometry()
feedback.setProgress(int(current * total)) feedback.setProgress(int(current * total))


cleaned = dict(geoms) cleaned = dict(geoms)


for i, g in list(geoms.items()): for i, g in list(geoms.items()):
if feedback.isCanceled():
break

for j in list(cleaned.keys()): for j in list(cleaned.keys()):
if i == j or i not in cleaned: if i == j or i not in cleaned:
continue continue
Expand All @@ -82,8 +83,11 @@ def processAlgorithm(self, parameters, context, feedback):


total = 100.0 / len(cleaned) if cleaned else 1 total = 100.0 / len(cleaned) if cleaned else 1
request = QgsFeatureRequest().setFilterFids(list(cleaned.keys())) request = QgsFeatureRequest().setFilterFids(list(cleaned.keys()))
for current, f in enumerate(layer.getFeatures(request)): for current, f in enumerate(source.getFeatures(request)):
writer.addFeature(f, QgsFeatureSink.FastInsert) if feedback.isCanceled():
break

sink.addFeature(f, QgsFeatureSink.FastInsert)
feedback.setProgress(int(current * total)) feedback.setProgress(int(current * total))


del writer return {self.OUTPUT: dest_id}
Loading

0 comments on commit 9763b60

Please sign in to comment.