33
33
QgsFeature ,
34
34
QgsWkbTypes ,
35
35
QgsFeatureRequest ,
36
- QgsApplication ,
37
- QgsProcessingUtils )
36
+ QgsProcessing ,
37
+ QgsProcessingParameterFeatureSource ,
38
+ QgsProcessingParameterBoolean ,
39
+ QgsProcessingParameterFeatureSink ,
40
+ QgsProcessingException )
38
41
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
44
42
45
43
46
44
class OrientedMinimumBoundingBox (QgisAlgorithm ):
47
45
48
- INPUT_LAYER = 'INPUT_LAYER '
46
+ INPUT = 'INPUT '
49
47
BY_FEATURE = 'BY_FEATURE'
50
48
51
49
OUTPUT = 'OUTPUT'
@@ -57,12 +55,12 @@ def __init__(self):
57
55
super ().__init__ ()
58
56
59
57
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 ))
64
62
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 ))
66
64
67
65
def name (self ):
68
66
return 'orientedminimumboundingbox'
@@ -71,14 +69,14 @@ def displayName(self):
71
69
return self .tr ('Oriented minimum bounding box' )
72
70
73
71
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 )
76
74
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" ))
79
77
80
- if byFeature :
81
- fields = layer .fields ()
78
+ if by_feature :
79
+ fields = source .fields ()
82
80
else :
83
81
fields = QgsFields ()
84
82
fields .append (QgsField ('area' , QVariant .Double ))
@@ -87,29 +85,32 @@ def processAlgorithm(self, parameters, context, feedback):
87
85
fields .append (QgsField ('width' , QVariant .Double ))
88
86
fields .append (QgsField ('height' , QVariant .Double ))
89
87
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 ())
91
90
92
- if byFeature :
93
- self .featureOmbb (layer , context , writer , feedback )
91
+ if by_feature :
92
+ self .featureOmbb (source , context , sink , feedback )
94
93
else :
95
- self .layerOmmb (layer , context , writer , feedback )
94
+ self .layerOmmb (source , context , sink , feedback )
96
95
97
- del writer
96
+ return { self . OUTPUT : dest_id }
98
97
99
- def layerOmmb (self , layer , context , writer , feedback ):
98
+ def layerOmmb (self , source , context , sink , feedback ):
100
99
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
103
102
newgeometry = QgsGeometry ()
104
103
first = True
104
+ geometries = []
105
105
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 ())
111
111
feedback .setProgress (int (current * total ))
112
112
113
+ newgeometry = QgsGeometry .unaryUnion (geometries )
113
114
geometry , area , angle , width , height = newgeometry .orientedMinimumBoundingBox ()
114
115
115
116
if geometry :
@@ -121,13 +122,16 @@ def layerOmmb(self, layer, context, writer, feedback):
121
122
angle ,
122
123
width ,
123
124
height ])
124
- writer .addFeature (outFeat , QgsFeatureSink .FastInsert )
125
+ sink .addFeature (outFeat , QgsFeatureSink .FastInsert )
125
126
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
129
130
outFeat = QgsFeature ()
130
131
for current , inFeat in enumerate (features ):
132
+ if feedback .isCanceled ():
133
+ break
134
+
131
135
geometry , area , angle , width , height = inFeat .geometry ().orientedMinimumBoundingBox ()
132
136
if geometry :
133
137
outFeat .setGeometry (geometry )
@@ -138,7 +142,7 @@ def featureOmbb(self, layer, context, writer, feedback):
138
142
width ,
139
143
height ])
140
144
outFeat .setAttributes (attrs )
141
- writer .addFeature (outFeat , QgsFeatureSink .FastInsert )
145
+ sink .addFeature (outFeat , QgsFeatureSink .FastInsert )
142
146
else :
143
147
feedback .pushInfo (self .tr ("Can't calculate an OMBB for feature {0}." ).format (inFeat .id ()))
144
148
feedback .setProgress (int (current * total ))
0 commit comments