Navigation Menu

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

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

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]


class Boundary(QgisAlgorithm):

INPUT_LAYER = 'INPUT_LAYER'
OUTPUT_LAYER = 'OUTPUT_LAYER'
class Boundary(QgisFeatureBasedAlgorithm):

def __init__(self):
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):
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'convex_hull.png'))

Expand All @@ -65,10 +54,10 @@ def name(self):
def displayName(self):
return self.tr('Boundary')

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

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

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

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

for current, input_feature in enumerate(features):
if feedback.isCanceled():
break
output_feature = input_feature
input_geometry = input_feature.geometry()
if input_geometry:
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}
return output_wkb

def processFeature(self, feature, feedback):
input_geometry = feature.geometry()
if input_geometry:
output_geometry = QgsGeometry(input_geometry.geometry().boundary())
if not output_geometry:
feedback.reportError(self.tr('No boundary for feature {} (possibly a closed linestring?)').format(feature.id()))
feature.clearGeometry()
else:
feature.setGeometry(output_geometry)
return feature
72 changes: 28 additions & 44 deletions python/plugins/processing/algs/qgis/DeleteColumn.py
Expand Up @@ -25,18 +25,13 @@

__revision__ = '$Format:%H$'

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


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

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

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

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

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

self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Output layer')))
None, 'INPUT', QgsProcessingParameterField.Any, True))

def name(self):
return 'deletecolumn'

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

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

def prepareAlgorithm(self, parameters, context, feedback):
self.fields_to_delete = self.parameterAsFields(parameters, self.COLUMNS, context)
return True

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

# 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
for index in field_indices:
fields.remove(index)

(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
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

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}
for index in self.field_indices:
input_fields.remove(index)
return input_fields

def processFeature(self, feature, feedback):
attributes = feature.attributes()
for index in self.field_indices:
del attributes[index]
feature.setAttributes(attributes)
return feature
50 changes: 16 additions & 34 deletions python/plugins/processing/algs/qgis/DeleteHoles.py
Expand Up @@ -24,32 +24,23 @@

__revision__ = '$Format:%H$'

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


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

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

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

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

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

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

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

def processAlgorithm(self, parameters, context, feedback):
source = self.parameterAsSource(parameters, self.INPUT, context)
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
def outputName(self):
return self.tr('Cleaned')

if f.hasGeometry():
f.setGeometry(f.geometry().removeInteriorRings(min_area))
sink.addFeature(f, QgsFeatureSink.FastInsert)
feedback.setProgress(int(current * total))
def prepareAlgorithm(self, parameters, context, feedback):
self.min_area = self.parameterAsDouble(parameters, self.MIN_AREA, context)
if self.min_area == 0.0:
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

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

from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm

class DensifyGeometries(QgisAlgorithm):

INPUT = 'INPUT'
class DensifyGeometries(QgisFeatureBasedAlgorithm):

VERTICES = 'VERTICES'
OUTPUT = 'OUTPUT'

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

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

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

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

def name(self):
return 'densifygeometries'

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

def processAlgorithm(self, parameters, context, feedback):
source = self.parameterAsSource(parameters, self.INPUT, context)
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
def outputName(self):
return self.tr('Densified')

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

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.