Skip to content

Commit c4011ad

Browse files
committed
Port oriented minimum bounds to new API
1 parent 86949cb commit c4011ad

File tree

3 files changed

+59
-54
lines changed

3 files changed

+59
-54
lines changed

python/plugins/processing/algs/qgis/OrientedMinimumBoundingBox.py

+41-37
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,17 @@
3333
QgsFeature,
3434
QgsWkbTypes,
3535
QgsFeatureRequest,
36-
QgsApplication,
37-
QgsProcessingUtils)
36+
QgsProcessing,
37+
QgsProcessingParameterFeatureSource,
38+
QgsProcessingParameterBoolean,
39+
QgsProcessingParameterFeatureSink,
40+
QgsProcessingException)
3841
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
39-
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
40-
from processing.core.parameters import ParameterVector
41-
from processing.core.parameters import ParameterBoolean
42-
from processing.core.outputs import OutputVector
43-
from processing.tools import dataobjects
4442

4543

4644
class OrientedMinimumBoundingBox(QgisAlgorithm):
4745

48-
INPUT_LAYER = 'INPUT_LAYER'
46+
INPUT = 'INPUT'
4947
BY_FEATURE = 'BY_FEATURE'
5048

5149
OUTPUT = 'OUTPUT'
@@ -57,12 +55,12 @@ def __init__(self):
5755
super().__init__()
5856

5957
def initAlgorithm(self, config=None):
60-
self.addParameter(ParameterVector(self.INPUT_LAYER,
61-
self.tr('Input layer')))
62-
self.addParameter(ParameterBoolean(self.BY_FEATURE,
63-
self.tr('Calculate OMBB for each feature separately'), True))
58+
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
59+
self.tr('Input layer'), [QgsProcessing.TypeVectorAny]))
60+
self.addParameter(QgsProcessingParameterBoolean(self.BY_FEATURE,
61+
self.tr('Calculate bounds for each feature separately'), defaultValue=True))
6462

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

6765
def name(self):
6866
return 'orientedminimumboundingbox'
@@ -71,14 +69,14 @@ def displayName(self):
7169
return self.tr('Oriented minimum bounding box')
7270

7371
def processAlgorithm(self, parameters, context, feedback):
74-
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)
75-
byFeature = self.getParameterValue(self.BY_FEATURE)
72+
source = self.parameterAsSource(parameters, self.INPUT, context)
73+
by_feature = self.parameterAsBool(parameters, self.BY_FEATURE, context)
7674

77-
if byFeature and layer.geometryType() == QgsWkbTypes.PointGeometry and layer.featureCount() <= 2:
78-
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"))
75+
if not by_feature and QgsWkbTypes.geometryType(source.wkbType()) == QgsWkbTypes.PointGeometry and source.featureCount() <= 2:
76+
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"))
7977

80-
if byFeature:
81-
fields = layer.fields()
78+
if by_feature:
79+
fields = source.fields()
8280
else:
8381
fields = QgsFields()
8482
fields.append(QgsField('area', QVariant.Double))
@@ -87,29 +85,32 @@ def processAlgorithm(self, parameters, context, feedback):
8785
fields.append(QgsField('width', QVariant.Double))
8886
fields.append(QgsField('height', QVariant.Double))
8987

90-
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.Polygon, layer.crs(), context)
88+
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
89+
fields, QgsWkbTypes.Polygon, source.sourceCrs())
9190

92-
if byFeature:
93-
self.featureOmbb(layer, context, writer, feedback)
91+
if by_feature:
92+
self.featureOmbb(source, context, sink, feedback)
9493
else:
95-
self.layerOmmb(layer, context, writer, feedback)
94+
self.layerOmmb(source, context, sink, feedback)
9695

97-
del writer
96+
return {self.OUTPUT: dest_id}
9897

99-
def layerOmmb(self, layer, context, writer, feedback):
98+
def layerOmmb(self, source, context, sink, feedback):
10099
req = QgsFeatureRequest().setSubsetOfAttributes([])
101-
features = QgsProcessingUtils.getFeatures(layer, context, req)
102-
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
100+
features = source.getFeatures(req)
101+
total = 100.0 / source.featureCount() if source.featureCount() else 0
103102
newgeometry = QgsGeometry()
104103
first = True
104+
geometries = []
105105
for current, inFeat in enumerate(features):
106-
if first:
107-
newgeometry = inFeat.geometry()
108-
first = False
109-
else:
110-
newgeometry = newgeometry.combine(inFeat.geometry())
106+
if feedback.isCanceled():
107+
break
108+
109+
if inFeat.hasGeometry():
110+
geometries.append(inFeat.geometry())
111111
feedback.setProgress(int(current * total))
112112

113+
newgeometry = QgsGeometry.unaryUnion(geometries)
113114
geometry, area, angle, width, height = newgeometry.orientedMinimumBoundingBox()
114115

115116
if geometry:
@@ -121,13 +122,16 @@ def layerOmmb(self, layer, context, writer, feedback):
121122
angle,
122123
width,
123124
height])
124-
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
125+
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
125126

126-
def featureOmbb(self, layer, context, writer, feedback):
127-
features = QgsProcessingUtils.getFeatures(layer, context)
128-
total = 100.0 / layer.featureCount() if layer.featureCount() else 0
127+
def featureOmbb(self, source, context, sink, feedback):
128+
features = source.getFeatures()
129+
total = 100.0 / source.featureCount() if source.featureCount() else 0
129130
outFeat = QgsFeature()
130131
for current, inFeat in enumerate(features):
132+
if feedback.isCanceled():
133+
break
134+
131135
geometry, area, angle, width, height = inFeat.geometry().orientedMinimumBoundingBox()
132136
if geometry:
133137
outFeat.setGeometry(geometry)
@@ -138,7 +142,7 @@ def featureOmbb(self, layer, context, writer, feedback):
138142
width,
139143
height])
140144
outFeat.setAttributes(attrs)
141-
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
145+
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
142146
else:
143147
feedback.pushInfo(self.tr("Can't calculate an OMBB for feature {0}.").format(inFeat.id()))
144148
feedback.setProgress(int(current * total))

python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
from .MergeLines import MergeLines
9393
from .NearestNeighbourAnalysis import NearestNeighbourAnalysis
9494
from .OffsetLine import OffsetLine
95+
from .OrientedMinimumBoundingBox import OrientedMinimumBoundingBox
9596
from .Orthogonalize import Orthogonalize
9697
from .PointDistance import PointDistance
9798
from .PointOnSurface import PointOnSurface
@@ -163,7 +164,6 @@
163164
# from .SelectByAttributeSum import SelectByAttributeSum
164165
# from .HypsometricCurves import HypsometricCurves
165166
# from .Datasources2Vrt import Datasources2Vrt
166-
# from .OrientedMinimumBoundingBox import OrientedMinimumBoundingBox
167167
# from .DefineProjection import DefineProjection
168168
# from .RectanglesOvalsDiamondsVariable import RectanglesOvalsDiamondsVariable
169169
# from .RectanglesOvalsDiamondsFixed import RectanglesOvalsDiamondsFixed
@@ -195,7 +195,7 @@ def getAlgs(self):
195195
# SetVectorStyle(), SetRasterStyle(),
196196
# HypsometricCurves(),
197197
# FieldsMapper(), SelectByAttributeSum(), Datasources2Vrt(),
198-
# OrientedMinimumBoundingBox(),
198+
#
199199
# DefineProjection(),
200200
# RectanglesOvalsDiamondsVariable(),
201201
# RectanglesOvalsDiamondsFixed(),
@@ -256,6 +256,7 @@ def getAlgs(self):
256256
MergeLines(),
257257
NearestNeighbourAnalysis(),
258258
OffsetLine(),
259+
OrientedMinimumBoundingBox(),
259260
Orthogonalize(),
260261
PointDistance(),
261262
PointOnSurface(),

python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml

+15-15
Original file line numberDiff line numberDiff line change
@@ -2235,21 +2235,21 @@ tests:
22352235
# OUTPUT:
22362236
# hash: fe6e018be13c5a3c17f3f4d0f0dc7686c628cb440b74c4642aa0c939
22372237
# type: rasterhash
2238-
#
2239-
# - algorithm: qgis:orientedminimumboundingbox
2240-
# name: Oriented minimum bounding box polys
2241-
# params:
2242-
# BY_FEATURE: true
2243-
# INPUT_LAYER:
2244-
# name: custom/oriented_bbox.gml
2245-
# type: vector
2246-
# results:
2247-
# OUTPUT:
2248-
# name: expected/oriented_bounds.gml
2249-
# type: vector
2250-
# compare:
2251-
# geometry:
2252-
# precision: 7
2238+
2239+
- algorithm: qgis:orientedminimumboundingbox
2240+
name: Oriented minimum bounding box polys
2241+
params:
2242+
BY_FEATURE: true
2243+
INPUT:
2244+
name: custom/oriented_bbox.gml
2245+
type: vector
2246+
results:
2247+
OUTPUT:
2248+
name: expected/oriented_bounds.gml
2249+
type: vector
2250+
compare:
2251+
geometry:
2252+
precision: 7
22532253

22542254
- algorithm: qgis:orthogonalize
22552255
name: Orthogonalize polys

0 commit comments

Comments
 (0)