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
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)
- 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)
- vertexAt() now returns a QgsPoint (previously QgsPointV2) instead of a QgsPointXY (previously QgsPoint)


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

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

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

__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):

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

outFeat = QgsFeature()

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

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

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

attrs = inFeat.attributes()
if useField:
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)
outFeat.setGeometry(final_geometry)
outFeat.setAttributes(attrs)
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
else:

features = source.getFeatures()

# Without dissolve
for inFeat in features:
if feedback.isCanceled():
break
attrs = inFeat.attributes()
if useField:
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)
outFeat.setGeometry(outGeom)
outFeat.setAttributes(attrs)
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
current += 1
feedback.setProgress(int(current * total))

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

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

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

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

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

self.addParameter(ParameterVector(self.INPUT,
self.tr('Input layer')))
self.addParameter(ParameterTableField(self.FIELD,
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]))
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
self.tr('Input layer')))
self.addParameter(QgsProcessingParameterField(self.FIELD,
self.tr('Field (optional, set if creating convex hulls by classes)'),
parentLayerParameterName=self.INPUT, optional=True))
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Convex hull'), QgsProcessing.TypeVectorPolygon))

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

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

field_index = None
f = QgsField('value', QVariant.String, '', 255)
if useField:
index = layer.fields().lookupField(fieldName)
fType = layer.fields()[index].type()
field_index = source.fields().lookupField(fieldName)
fType = source.fields()[field_index].type()
if fType in [QVariant.Int, QVariant.UInt, QVariant.LongLong, QVariant.ULongLong]:
f.setType(fType)
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('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()
inGeom = QgsGeometry()
outGeom = QgsGeometry()

fid = 0
val = None
features = QgsProcessingUtils.getFeatures(layer, context)
if useField:
unique = layer.uniqueValues(index)
unique = source.uniqueValues(field_index)
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:
if feedback.isCanceled():
break

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

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

inGeom = f.geometry()
points = vector.extractPoints(inGeom)
hull.extend(points)
Expand All @@ -180,9 +183,9 @@ def processAlgorithm(self, parameters, context, feedback):
perim = NULL
outFeat.setGeometry(outGeom)
outFeat.setAttributes([0, 'all', area, perim])
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
except:
raise GeoAlgorithmExecutionException(
raise QgsProcessingException(
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
Expand Up @@ -26,12 +26,10 @@
__revision__ = '$Format:%H$'

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


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

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

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

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()

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
features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]))
total = 100.0 / source.featureCount() if source.featureCount() else 0
geoms = dict()
for current, f in enumerate(features):
if feedback.isCanceled():
break

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

cleaned = dict(geoms)

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

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

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

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

del writer
return {self.OUTPUT: dest_id}

0 comments on commit 9763b60

Please sign in to comment.