33
33
from processing .core .outputs import OutputVector
34
34
from processing .tools import dataobjects , vector
35
35
36
+ wkbTypeGroups = {
37
+ 'Point' : (QGis .WKBPoint , QGis .WKBMultiPoint , QGis .WKBPoint25D , QGis .WKBMultiPoint25D ,),
38
+ 'LineString' : (QGis .WKBLineString , QGis .WKBMultiLineString , QGis .WKBLineString25D , QGis .WKBMultiLineString25D ,),
39
+ 'Polygon' : (QGis .WKBPolygon , QGis .WKBMultiPolygon , QGis .WKBPolygon25D , QGis .WKBMultiPolygon25D ,),
40
+ }
41
+ for key , value in wkbTypeGroups .items ():
42
+ for const in value :
43
+ wkbTypeGroups [const ] = key
44
+
45
+ GEOM_25D = [QGis .WKBPoint25D , QGis .WKBLineString25D , QGis .WKBPolygon25D ,
46
+ QGis .WKBMultiPoint25D , QGis .WKBMultiLineString25D ,
47
+ QGis .WKBMultiPolygon25D ]
48
+
36
49
37
50
class Union (GeoAlgorithm ):
38
51
39
52
INPUT = 'INPUT'
40
53
INPUT2 = 'INPUT2'
41
54
OUTPUT = 'OUTPUT'
42
55
56
+ def defineCharacteristics (self ):
57
+ self .name , self .i18n_name = self .trAlgorithm ('Union' )
58
+ self .group , self .i18n_group = self .trAlgorithm ('Vector overlay tools' )
59
+ self .addParameter (ParameterVector (Union .INPUT ,
60
+ self .tr ('Input layer' ), [ParameterVector .VECTOR_TYPE_ANY ]))
61
+ self .addParameter (ParameterVector (Union .INPUT2 ,
62
+ self .tr ('Input layer 2' ), [ParameterVector .VECTOR_TYPE_ANY ]))
63
+ self .addOutput (OutputVector (Union .OUTPUT , self .tr ('Union' )))
64
+
43
65
def processAlgorithm (self , progress ):
44
66
vlayerA = dataobjects .getObjectFromUri (self .getParameterValue (Union .INPUT ))
45
67
vlayerB = dataobjects .getObjectFromUri (self .getParameterValue (Union .INPUT2 ))
46
- GEOS_EXCEPT = True
47
- FEATURE_EXCEPT = True
68
+
48
69
vproviderA = vlayerA .dataProvider ()
49
70
71
+ geomType = vproviderA .geometryType ()
72
+ if geomType in GEOM_25D :
73
+ raise GeoAlgorithmExecutionException (
74
+ self .tr ('Input layer has unsupported geometry type {}' ).format (geomType ))
75
+
50
76
fields = vector .combineVectorFields (vlayerA , vlayerB )
51
- names = [field .name () for field in fields ]
52
- ProcessingLog .addToLog (ProcessingLog .LOG_INFO , unicode (names ))
53
77
writer = self .getOutputFromName (Union .OUTPUT ).getVectorWriter (fields ,
54
- vproviderA . geometryType () , vproviderA .crs ())
78
+ geomType , vproviderA .crs ())
55
79
inFeatA = QgsFeature ()
56
80
inFeatB = QgsFeature ()
57
81
outFeat = QgsFeature ()
@@ -77,8 +101,8 @@ def processAlgorithm(self, progress):
77
101
except :
78
102
# This really shouldn't happen, as we haven't
79
103
# edited the input geom at all
80
- raise GeoAlgorithmExecutionException (
81
- self .tr ('Feature exception while computing union ' ))
104
+ ProcessingLog . addToLog ( ProcessingLog . LOG_INFO ,
105
+ self .tr ('Feature geometry error: One or more output features ignored due to invalid geometry. ' ))
82
106
else :
83
107
for id in intersects :
84
108
count += 1
@@ -93,9 +117,9 @@ def processAlgorithm(self, progress):
93
117
94
118
if int_geom is None :
95
119
# There was a problem creating the intersection
96
- raise GeoAlgorithmExecutionException (
97
- self .tr ('Geometry exception while computing '
98
- 'intersection' ) )
120
+ ProcessingLog . addToLog ( ProcessingLog . LOG_INFO ,
121
+ self .tr ('GEOS geoprocessing error: One or more input features have invalid geometry.' ))
122
+ int_geom = QgsGeometry ( )
99
123
else :
100
124
int_geom = QgsGeometry (int_geom )
101
125
@@ -105,38 +129,52 @@ def processAlgorithm(self, progress):
105
129
for i in temp_list :
106
130
if i .type () == geom .type ():
107
131
int_geom = QgsGeometry (i )
108
- try :
109
- outFeat .setGeometry (int_geom )
110
- attrs = []
111
- attrs .extend (atMapA )
112
- attrs .extend (atMapB )
113
- outFeat .setAttributes (attrs )
114
- writer .addFeature (outFeat )
115
- except Exception as err :
116
- raise GeoAlgorithmExecutionException (
117
- self .tr ('Feature exception while computing union' ))
118
-
132
+ try :
133
+ outFeat .setGeometry (int_geom )
134
+ outFeat .setAttributes (atMapA + atMapB )
135
+ writer .addFeature (outFeat )
136
+ except :
137
+ ProcessingLog .addToLog (ProcessingLog .LOG_INFO ,
138
+ self .tr ('Feature geometry error: One or more output features ignored due to invalid geometry.' ))
139
+ else :
140
+ # Geometry list: prevents writing error
141
+ # in geometries of different types
142
+ # produced by the intersection
143
+ # fix #3549
144
+ if int_geom .wkbType () in wkbTypeGroups [wkbTypeGroups [int_geom .wkbType ()]]:
145
+ try :
146
+ outFeat .setGeometry (int_geom )
147
+ outFeat .setAttributes (atMapA + atMapB )
148
+ writer .addFeature (outFeat )
149
+ except :
150
+ ProcessingLog .addToLog (ProcessingLog .LOG_INFO ,
151
+ self .tr ('Feature geometry error: One or more output features ignored due to invalid geometry.' ))
152
+
153
+ # the remaining bit of inFeatA's geometry
154
+ # if there is nothing left, this will just silently fail and we're good
155
+ diff_geom = QgsGeometry (geom )
156
+ if len (lstIntersectingB ) != 0 :
157
+ intB = QgsGeometry .unaryUnion (lstIntersectingB )
158
+ diff_geom = diff_geom .difference (intB )
159
+ if diff_geom .isGeosEmpty () or not diff_geom .isGeosValid ():
160
+ ProcessingLog .addToLog (ProcessingLog .LOG_ERROR ,
161
+ self .tr ('GEOS geoprocessing error: One or more input features have invalid geometry.' ))
162
+
163
+ if diff_geom .wkbType () == 0 or QgsWKBTypes .flatType (diff_geom .geometry ().wkbType ()) == QgsWKBTypes .GeometryCollection :
164
+ temp_list = diff_geom .asGeometryCollection ()
165
+ for i in temp_list :
166
+ if i .type () == geom .type ():
167
+ diff_geom = QgsGeometry (i )
119
168
try :
120
- # the remaining bit of inFeatA's geometry
121
- # if there is nothing left, this will just silently fail and we're good
122
- diff_geom = QgsGeometry (geom )
123
- if len (lstIntersectingB ) != 0 :
124
- intB = QgsGeometry .unaryUnion (lstIntersectingB )
125
- diff_geom = diff_geom .difference (intB )
126
-
127
- if diff_geom .wkbType () == 0 or QgsWKBTypes .flatType (int_geom .geometry ().wkbType ()) == QgsWKBTypes .GeometryCollection :
128
- temp_list = diff_geom .asGeometryCollection ()
129
- for i in temp_list :
130
- if i .type () == geom .type ():
131
- diff_geom = QgsGeometry (i )
132
169
outFeat .setGeometry (diff_geom )
133
170
outFeat .setAttributes (atMapA )
134
171
writer .addFeature (outFeat )
135
- except Exception as err :
136
- raise GeoAlgorithmExecutionException (
137
- self .tr ('Feature exception while computing union ' ))
172
+ except :
173
+ ProcessingLog . addToLog ( ProcessingLog . LOG_INFO ,
174
+ self .tr ('Feature geometry error: One or more output features ignored due to invalid geometry. ' ))
138
175
139
176
length = len (vproviderA .fields ())
177
+ atMapA = [None ] * length
140
178
141
179
featuresA = vector .features (vlayerB )
142
180
nFeat = len (featuresA )
@@ -154,53 +192,41 @@ def processAlgorithm(self, progress):
154
192
outFeat .setGeometry (geom )
155
193
outFeat .setAttributes (atMap )
156
194
writer .addFeature (outFeat )
157
- except Exception as err :
158
- raise GeoAlgorithmExecutionException (
159
- self .tr ('Feature exception while computing union ' ))
195
+ except :
196
+ ProcessingLog . addToLog ( ProcessingLog . LOG_INFO ,
197
+ self .tr ('Feature geometry error: One or more output features ignored due to invalid geometry. ' ))
160
198
else :
161
199
for id in intersects :
162
200
request = QgsFeatureRequest ().setFilterFid (id )
163
201
inFeatB = vlayerA .getFeatures (request ).next ()
164
202
atMapB = inFeatB .attributes ()
165
203
tmpGeom = QgsGeometry (inFeatB .geometry ())
166
- try :
167
- if diff_geom .intersects (tmpGeom ):
168
- add = True
169
- diff_geom = QgsGeometry (
170
- diff_geom .difference (tmpGeom ))
171
- else :
204
+
205
+ if diff_geom .intersects (tmpGeom ):
206
+ add = True
207
+ diff_geom = QgsGeometry (diff_geom .difference (tmpGeom ))
208
+ if diff_geom .isGeosEmpty () or not diff_geom .isGeosValid ():
209
+ ProcessingLog .addToLog (ProcessingLog .LOG_ERROR ,
210
+ self .tr ('GEOS geoprocessing error: One or more input features have invalid geometry.' ))
211
+ else :
212
+ try :
172
213
# Ihis only happends if the bounding box
173
214
# intersects, but the geometry doesn't
174
215
outFeat .setGeometry (diff_geom )
175
216
outFeat .setAttributes (atMap )
176
217
writer .addFeature (outFeat )
177
- except Exception as err :
178
- raise GeoAlgorithmExecutionException (
179
- self .tr ('Geometry exception while computing intersection ' ))
218
+ except :
219
+ ProcessingLog . addToLog ( ProcessingLog . LOG_INFO ,
220
+ self .tr ('Feature geometry error: One or more output features ignored due to invalid geometry. ' ))
180
221
181
222
if add :
182
223
try :
183
224
outFeat .setGeometry (diff_geom )
184
225
outFeat .setAttributes (atMap )
185
226
writer .addFeature (outFeat )
186
- except Exception as err :
187
- raise err
188
- FEATURE_EXCEPT = False
227
+ except :
228
+ ProcessingLog . addToLog ( ProcessingLog . LOG_INFO ,
229
+ self . tr ( 'Feature geometry error: One or more output features ignored due to invalid geometry.' ))
189
230
nElement += 1
190
231
191
232
del writer
192
- if not GEOS_EXCEPT :
193
- ProcessingLog .addToLog (ProcessingLog .LOG_WARNING ,
194
- self .tr ('Geometry exception while computing intersection' ))
195
- if not FEATURE_EXCEPT :
196
- ProcessingLog .addToLog (ProcessingLog .LOG_WARNING ,
197
- self .tr ('Feature exception while computing intersection' ))
198
-
199
- def defineCharacteristics (self ):
200
- self .name , self .i18n_name = self .trAlgorithm ('Union' )
201
- self .group , self .i18n_group = self .trAlgorithm ('Vector overlay tools' )
202
- self .addParameter (ParameterVector (Union .INPUT ,
203
- self .tr ('Input layer' ), [ParameterVector .VECTOR_TYPE_ANY ]))
204
- self .addParameter (ParameterVector (Union .INPUT2 ,
205
- self .tr ('Input layer 2' ), [ParameterVector .VECTOR_TYPE_ANY ]))
206
- self .addOutput (OutputVector (Union .OUTPUT , self .tr ('Union' )))
1 commit comments
rldhont commentedon Jun 10, 2016
Hi @alexbruy , Why did you restrict these process ?
Is it linked to GEOS version ?
We tests with 25D data and clip it's working.
http://hub.qgis.org/issues/14929