Skip to content

Commit

Permalink
Flip some more algorithms to feature based algorithms
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jul 20, 2017
1 parent 6e49403 commit d4af761
Show file tree
Hide file tree
Showing 15 changed files with 278 additions and 565 deletions.
58 changes: 18 additions & 40 deletions python/plugins/processing/algs/qgis/Boundary.py
Expand Up @@ -28,31 +28,20 @@
import os import os


from qgis.core import (QgsGeometry, from qgis.core import (QgsGeometry,
QgsWkbTypes, QgsWkbTypes)
QgsFeatureSink,
QgsProcessing,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterFeatureSink)


from qgis.PyQt.QtGui import QIcon from qgis.PyQt.QtGui import QIcon


from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm


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]




class Boundary(QgisAlgorithm): class Boundary(QgisFeatureBasedAlgorithm):

INPUT_LAYER = 'INPUT_LAYER'
OUTPUT_LAYER = 'OUTPUT_LAYER'


def __init__(self): def __init__(self):
super().__init__() super().__init__()


def initAlgorithm(self, config=None):
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT_LAYER, self.tr('Input layer'), [QgsProcessing.TypeVectorLine, QgsProcessing.TypeVectorPolygon]))
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT_LAYER, self.tr('Boundary')))

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 @@ -65,10 +54,10 @@ def name(self):
def displayName(self): def displayName(self):
return self.tr('Boundary') return self.tr('Boundary')


def processAlgorithm(self, parameters, context, feedback): def outputName(self):
source = self.parameterAsSource(parameters, self.INPUT_LAYER, context) return self.tr('Boundary')


input_wkb = source.wkbType() def outputWkbType(self, input_wkb):
if QgsWkbTypes.geometryType(input_wkb) == QgsWkbTypes.LineGeometry: if QgsWkbTypes.geometryType(input_wkb) == QgsWkbTypes.LineGeometry:
output_wkb = QgsWkbTypes.MultiPoint output_wkb = QgsWkbTypes.MultiPoint
elif QgsWkbTypes.geometryType(input_wkb) == QgsWkbTypes.PolygonGeometry: elif QgsWkbTypes.geometryType(input_wkb) == QgsWkbTypes.PolygonGeometry:
Expand All @@ -78,26 +67,15 @@ def processAlgorithm(self, parameters, context, feedback):
if QgsWkbTypes.hasM(input_wkb): if QgsWkbTypes.hasM(input_wkb):
output_wkb = QgsWkbTypes.addM(output_wkb) output_wkb = QgsWkbTypes.addM(output_wkb)


(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LAYER, context, return output_wkb
source.fields(), output_wkb, source.sourceCrs())

def processFeature(self, feature, feedback):
features = source.getFeatures() input_geometry = feature.geometry()
total = 100.0 / source.featureCount() if source.featureCount() else 0 if input_geometry:

output_geometry = QgsGeometry(input_geometry.geometry().boundary())
for current, input_feature in enumerate(features): if not output_geometry:
if feedback.isCanceled(): feedback.reportError(self.tr('No boundary for feature {} (possibly a closed linestring?)').format(feature.id()))
break feature.clearGeometry()
output_feature = input_feature else:
input_geometry = input_feature.geometry() feature.setGeometry(output_geometry)
if input_geometry: return feature
output_geometry = QgsGeometry(input_geometry.geometry().boundary())
if not output_geometry:
feedback.reportError(self.tr('No boundary for feature {} (possibly a closed linestring?)').format(input_feature.id()))
output_feature.clearGeometry()
else:
output_feature.setGeometry(output_geometry)

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

return {self.OUTPUT_LAYER: dest_id}
72 changes: 28 additions & 44 deletions python/plugins/processing/algs/qgis/DeleteColumn.py
Expand Up @@ -25,18 +25,13 @@


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


from qgis.core import (QgsFeatureSink, from qgis.core import (QgsProcessingParameterField)
QgsProcessingParameterFeatureSource, from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
QgsProcessingParameterFeatureSink,
QgsProcessingParameterField)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm




class DeleteColumn(QgisAlgorithm): class DeleteColumn(QgisFeatureBasedAlgorithm):


INPUT = 'INPUT'
COLUMNS = 'COLUMN' COLUMNS = 'COLUMN'
OUTPUT = 'OUTPUT'


def tags(self): def tags(self):
return self.tr('drop,delete,remove,fields,columns,attributes').split(',') return self.tr('drop,delete,remove,fields,columns,attributes').split(',')
Expand All @@ -46,55 +41,44 @@ def group(self):


def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.fields_to_delete = []
self.field_indices = []


def initAlgorithm(self, config=None): def initParameters(self, config=None):
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, self.tr('Input layer')))
self.addParameter(QgsProcessingParameterField(self.COLUMNS, self.addParameter(QgsProcessingParameterField(self.COLUMNS,
self.tr('Fields to drop'), self.tr('Fields to drop'),
None, self.INPUT, QgsProcessingParameterField.Any, True)) None, 'INPUT', QgsProcessingParameterField.Any, True))

self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Output layer')))


def name(self): def name(self):
return 'deletecolumn' return 'deletecolumn'


def displayName(self): def displayName(self):
return self.tr('Drop field(s)') return self.tr('Drop field(s)')


def processAlgorithm(self, parameters, context, feedback): def outputName(self):
source = self.parameterAsSource(parameters, self.INPUT, context) return self.tr('Fields dropped')
fields_to_delete = self.parameterAsFields(parameters, self.COLUMNS, context)
def prepareAlgorithm(self, parameters, context, feedback):
self.fields_to_delete = self.parameterAsFields(parameters, self.COLUMNS, context)
return True


fields = source.fields() def outputFields(self, input_fields):
field_indices = []
# loop through twice - first we need to build up a list of original attribute indices # loop through twice - first we need to build up a list of original attribute indices
for f in fields_to_delete: for f in self.fields_to_delete:
index = fields.lookupField(f) index = input_fields.lookupField(f)
field_indices.append(index) self.field_indices.append(index)


# important - make sure we remove from the end so we aren't changing used indices as we go # important - make sure we remove from the end so we aren't changing used indices as we go
field_indices.sort(reverse=True) self.field_indices.sort(reverse=True)


# this second time we make a cleaned version of the fields # this second time we make a cleaned version of the fields
for index in field_indices: for index in self.field_indices:
fields.remove(index) input_fields.remove(index)

return input_fields
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
fields, source.wkbType(), source.sourceCrs()) def processFeature(self, feature, feedback):

attributes = feature.attributes()
features = source.getFeatures() for index in self.field_indices:
total = 100.0 / source.featureCount() if source.featureCount() else 0 del attributes[index]

feature.setAttributes(attributes)
for current, f in enumerate(features): return feature
if feedback.isCanceled():
break

attributes = f.attributes()
for index in field_indices:
del attributes[index]
f.setAttributes(attributes)
sink.addFeature(f, QgsFeatureSink.FastInsert)

feedback.setProgress(int(current * total))

return {self.OUTPUT: dest_id}
50 changes: 16 additions & 34 deletions python/plugins/processing/algs/qgis/DeleteHoles.py
Expand Up @@ -24,32 +24,23 @@


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


from qgis.core import (QgsFeatureSink, from qgis.core import (QgsProcessingParameterNumber)
QgsProcessing, from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
QgsProcessingParameterFeatureSource,
QgsProcessingParameterNumber,
QgsProcessingParameterFeatureSink)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm




class DeleteHoles(QgisAlgorithm): class DeleteHoles(QgisFeatureBasedAlgorithm):


INPUT = 'INPUT'
MIN_AREA = 'MIN_AREA' MIN_AREA = 'MIN_AREA'
OUTPUT = 'OUTPUT'


def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.min_area = None


def initAlgorithm(self, config=None): def initParameters(self, config=None):
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
self.tr('Input layer'), [QgsProcessing.TypeVectorPolygon]))
self.addParameter(QgsProcessingParameterNumber(self.MIN_AREA, self.addParameter(QgsProcessingParameterNumber(self.MIN_AREA,
self.tr('Remove holes with area less than'), QgsProcessingParameterNumber.Double, self.tr('Remove holes with area less than'), QgsProcessingParameterNumber.Double,
0, True, 0.0, 10000000.0)) 0, True, 0.0, 10000000.0))


self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Cleaned'), QgsProcessing.TypeVectorPolygon))

def tags(self): def tags(self):
return self.tr('remove,delete,drop,holes,rings,fill').split(',') return self.tr('remove,delete,drop,holes,rings,fill').split(',')


Expand All @@ -62,25 +53,16 @@ def name(self):
def displayName(self): def displayName(self):
return self.tr('Delete holes') return self.tr('Delete holes')


def processAlgorithm(self, parameters, context, feedback): def outputName(self):
source = self.parameterAsSource(parameters, self.INPUT, context) return self.tr('Cleaned')
min_area = self.parameterAsDouble(parameters, self.MIN_AREA, context)
if min_area == 0.0:
min_area = -1.0

(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
source.fields(), source.wkbType(), source.sourceCrs())

features = source.getFeatures()
total = 100.0 / source.featureCount() if source.featureCount() else 0

for current, f in enumerate(features):
if feedback.isCanceled():
break


if f.hasGeometry(): def prepareAlgorithm(self, parameters, context, feedback):
f.setGeometry(f.geometry().removeInteriorRings(min_area)) self.min_area = self.parameterAsDouble(parameters, self.MIN_AREA, context)
sink.addFeature(f, QgsFeatureSink.FastInsert) if self.min_area == 0.0:
feedback.setProgress(int(current * total)) self.min_area = -1.0
return True


return {self.OUTPUT: dest_id} def processFeature(self, feature, feedback):
if feature.hasGeometry():
feature.setGeometry(feature.geometry().removeInteriorRings(self.min_area))
return feature
50 changes: 16 additions & 34 deletions python/plugins/processing/algs/qgis/DensifyGeometries.py
Expand Up @@ -28,19 +28,14 @@


import os import os


from qgis.core import (QgsFeatureSink, from qgis.core import (QgsProcessingParameterNumber)
QgsProcessing,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterNumber,
QgsProcessingParameterFeatureSink)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm


from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm


class DensifyGeometries(QgisAlgorithm):


INPUT = 'INPUT' class DensifyGeometries(QgisFeatureBasedAlgorithm):

VERTICES = 'VERTICES' VERTICES = 'VERTICES'
OUTPUT = 'OUTPUT'


def tags(self): def tags(self):
return self.tr('add,vertices,points').split(',') return self.tr('add,vertices,points').split(',')
Expand All @@ -50,41 +45,28 @@ def group(self):


def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.vertices = None


def initAlgorithm(self, config=None): def initParameters(self, config=None):
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
self.tr('Input layer'), [QgsProcessing.TypeVectorPolygon, QgsProcessing.TypeVectorLine]))
self.addParameter(QgsProcessingParameterNumber(self.VERTICES, self.addParameter(QgsProcessingParameterNumber(self.VERTICES,
self.tr('Vertices to add'), QgsProcessingParameterNumber.Integer, self.tr('Vertices to add'), QgsProcessingParameterNumber.Integer,
1, False, 1, 10000000)) 1, False, 1, 10000000))


self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Densified')))

def name(self): def name(self):
return 'densifygeometries' return 'densifygeometries'


def displayName(self): def displayName(self):
return self.tr('Densify geometries') return self.tr('Densify geometries')


def processAlgorithm(self, parameters, context, feedback): def outputName(self):
source = self.parameterAsSource(parameters, self.INPUT, context) return self.tr('Densified')
vertices = self.parameterAsInt(parameters, self.VERTICES, context)

(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
source.fields(), source.wkbType(), source.sourceCrs())

features = source.getFeatures()
total = 100.0 / source.featureCount() if source.featureCount() else 0

for current, f in enumerate(features):
if feedback.isCanceled():
break


feature = f def prepareAlgorithm(self, parameters, context, feedback):
if feature.hasGeometry(): self.vertices = self.parameterAsInt(parameters, self.VERTICES, context)
new_geometry = feature.geometry().densifyByCount(vertices) return True
feature.setGeometry(new_geometry)
sink.addFeature(feature, QgsFeatureSink.FastInsert)
feedback.setProgress(int(current * total))


return {self.OUTPUT: dest_id} def processFeature(self, feature, feedback):
if feature.hasGeometry():
new_geometry = feature.geometry().densifyByCount(self.vertices)
feature.setGeometry(new_geometry)
return feature

0 comments on commit d4af761

Please sign in to comment.