Skip to content

Commit

Permalink
Port oriented minimum bounds to new API
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Aug 18, 2017
1 parent 86949cb commit c4011ad
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 54 deletions.
78 changes: 41 additions & 37 deletions python/plugins/processing/algs/qgis/OrientedMinimumBoundingBox.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,17 @@
QgsFeature,
QgsWkbTypes,
QgsFeatureRequest,
QgsApplication,
QgsProcessingUtils)
QgsProcessing,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterBoolean,
QgsProcessingParameterFeatureSink,
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 ParameterBoolean
from processing.core.outputs import OutputVector
from processing.tools import dataobjects


class OrientedMinimumBoundingBox(QgisAlgorithm):

INPUT_LAYER = 'INPUT_LAYER'
INPUT = 'INPUT'
BY_FEATURE = 'BY_FEATURE'

OUTPUT = 'OUTPUT'
Expand All @@ -57,12 +55,12 @@ def __init__(self):
super().__init__()

def initAlgorithm(self, config=None):
self.addParameter(ParameterVector(self.INPUT_LAYER,
self.tr('Input layer')))
self.addParameter(ParameterBoolean(self.BY_FEATURE,
self.tr('Calculate OMBB for each feature separately'), True))
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
self.tr('Input layer'), [QgsProcessing.TypeVectorAny]))
self.addParameter(QgsProcessingParameterBoolean(self.BY_FEATURE,
self.tr('Calculate bounds for each feature separately'), defaultValue=True))

self.addOutput(OutputVector(self.OUTPUT, self.tr('Oriented_MBBox'), datatype=[dataobjects.TYPE_VECTOR_POLYGON]))
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Bounding boxes'), QgsProcessing.TypeVectorPolygon))

def name(self):
return 'orientedminimumboundingbox'
Expand All @@ -71,14 +69,14 @@ def displayName(self):
return self.tr('Oriented minimum bounding box')

def processAlgorithm(self, parameters, context, feedback):
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)
byFeature = self.getParameterValue(self.BY_FEATURE)
source = self.parameterAsSource(parameters, self.INPUT, context)
by_feature = self.parameterAsBool(parameters, self.BY_FEATURE, context)

if byFeature and layer.geometryType() == QgsWkbTypes.PointGeometry and layer.featureCount() <= 2:
raise GeoAlgorithmExecutionException(self.tr("Can't calculate an OMBB for each point, it's a point. The number of points must be greater than 2"))
if not by_feature and QgsWkbTypes.geometryType(source.wkbType()) == QgsWkbTypes.PointGeometry and source.featureCount() <= 2:
raise QgsProcessingException(self.tr("Can't calculate an OMBB for each point, it's a point. The number of points must be greater than 2"))

if byFeature:
fields = layer.fields()
if by_feature:
fields = source.fields()
else:
fields = QgsFields()
fields.append(QgsField('area', QVariant.Double))
Expand All @@ -87,29 +85,32 @@ def processAlgorithm(self, parameters, context, feedback):
fields.append(QgsField('width', QVariant.Double))
fields.append(QgsField('height', QVariant.Double))

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

if byFeature:
self.featureOmbb(layer, context, writer, feedback)
if by_feature:
self.featureOmbb(source, context, sink, feedback)
else:
self.layerOmmb(layer, context, writer, feedback)
self.layerOmmb(source, context, sink, feedback)

del writer
return {self.OUTPUT: dest_id}

def layerOmmb(self, layer, context, writer, feedback):
def layerOmmb(self, source, context, sink, feedback):
req = QgsFeatureRequest().setSubsetOfAttributes([])
features = QgsProcessingUtils.getFeatures(layer, context, req)
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
features = source.getFeatures(req)
total = 100.0 / source.featureCount() if source.featureCount() else 0
newgeometry = QgsGeometry()
first = True
geometries = []
for current, inFeat in enumerate(features):
if first:
newgeometry = inFeat.geometry()
first = False
else:
newgeometry = newgeometry.combine(inFeat.geometry())
if feedback.isCanceled():
break

if inFeat.hasGeometry():
geometries.append(inFeat.geometry())
feedback.setProgress(int(current * total))

newgeometry = QgsGeometry.unaryUnion(geometries)
geometry, area, angle, width, height = newgeometry.orientedMinimumBoundingBox()

if geometry:
Expand All @@ -121,13 +122,16 @@ def layerOmmb(self, layer, context, writer, feedback):
angle,
width,
height])
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)

def featureOmbb(self, layer, context, writer, feedback):
features = QgsProcessingUtils.getFeatures(layer, context)
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
def featureOmbb(self, source, context, sink, feedback):
features = source.getFeatures()
total = 100.0 / source.featureCount() if source.featureCount() else 0
outFeat = QgsFeature()
for current, inFeat in enumerate(features):
if feedback.isCanceled():
break

geometry, area, angle, width, height = inFeat.geometry().orientedMinimumBoundingBox()
if geometry:
outFeat.setGeometry(geometry)
Expand All @@ -138,7 +142,7 @@ def featureOmbb(self, layer, context, writer, feedback):
width,
height])
outFeat.setAttributes(attrs)
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
else:
feedback.pushInfo(self.tr("Can't calculate an OMBB for feature {0}.").format(inFeat.id()))
feedback.setProgress(int(current * total))
5 changes: 3 additions & 2 deletions python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
from .MergeLines import MergeLines
from .NearestNeighbourAnalysis import NearestNeighbourAnalysis
from .OffsetLine import OffsetLine
from .OrientedMinimumBoundingBox import OrientedMinimumBoundingBox
from .Orthogonalize import Orthogonalize
from .PointDistance import PointDistance
from .PointOnSurface import PointOnSurface
Expand Down Expand Up @@ -163,7 +164,6 @@
# from .SelectByAttributeSum import SelectByAttributeSum
# from .HypsometricCurves import HypsometricCurves
# from .Datasources2Vrt import Datasources2Vrt
# from .OrientedMinimumBoundingBox import OrientedMinimumBoundingBox
# from .DefineProjection import DefineProjection
# from .RectanglesOvalsDiamondsVariable import RectanglesOvalsDiamondsVariable
# from .RectanglesOvalsDiamondsFixed import RectanglesOvalsDiamondsFixed
Expand Down Expand Up @@ -195,7 +195,7 @@ def getAlgs(self):
# SetVectorStyle(), SetRasterStyle(),
# HypsometricCurves(),
# FieldsMapper(), SelectByAttributeSum(), Datasources2Vrt(),
# OrientedMinimumBoundingBox(),
#
# DefineProjection(),
# RectanglesOvalsDiamondsVariable(),
# RectanglesOvalsDiamondsFixed(),
Expand Down Expand Up @@ -256,6 +256,7 @@ def getAlgs(self):
MergeLines(),
NearestNeighbourAnalysis(),
OffsetLine(),
OrientedMinimumBoundingBox(),
Orthogonalize(),
PointDistance(),
PointOnSurface(),
Expand Down
30 changes: 15 additions & 15 deletions python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2235,21 +2235,21 @@ tests:
# OUTPUT:
# hash: fe6e018be13c5a3c17f3f4d0f0dc7686c628cb440b74c4642aa0c939
# type: rasterhash
#
# - algorithm: qgis:orientedminimumboundingbox
# name: Oriented minimum bounding box polys
# params:
# BY_FEATURE: true
# INPUT_LAYER:
# name: custom/oriented_bbox.gml
# type: vector
# results:
# OUTPUT:
# name: expected/oriented_bounds.gml
# type: vector
# compare:
# geometry:
# precision: 7

- algorithm: qgis:orientedminimumboundingbox
name: Oriented minimum bounding box polys
params:
BY_FEATURE: true
INPUT:
name: custom/oriented_bbox.gml
type: vector
results:
OUTPUT:
name: expected/oriented_bounds.gml
type: vector
compare:
geometry:
precision: 7

- algorithm: qgis:orthogonalize
name: Orthogonalize polys
Expand Down

0 comments on commit c4011ad

Please sign in to comment.