@@ -172,9 +172,7 @@ bool QgsInvertedPolygonRenderer::renderFeature( QgsFeature& feature, QgsRenderCo
172172
173173 if ( ! mSymbolCategories .contains ( catId ) )
174174 {
175- // the exterior ring must be a square in the destination CRS
176175 CombinedFeature cFeat;
177- cFeat.multiPolygon .append ( mExtentPolygon );
178176 // store the first feature
179177 cFeat.feature = feature;
180178 mSymbolCategories .insert ( catId, mSymbolCategories .count () );
@@ -197,61 +195,15 @@ bool QgsInvertedPolygonRenderer::renderFeature( QgsFeature& feature, QgsRenderCo
197195
198196 if ( mPreprocessingEnabled )
199197 {
200- // preprocessing
201- if ( ! cFeat. feature . geometry () )
198+ // fix the polygon if it is not valid
199+ if ( ! geom-> isGeosValid () )
202200 {
203- // first feature: add the current geometry
204- cFeat.feature .setGeometry ( new QgsGeometry ( *geom ) );
205- }
206- else
207- {
208- // other features: combine them (union)
209- QgsGeometry* combined = cFeat.feature .geometry ()->combine ( geom.data () );
210- if ( combined && combined->isGeosValid () )
211- {
212- cFeat.feature .setGeometry ( combined );
213- }
201+ geom.reset ( geom->buffer ( 0 , 0 ) );
214202 }
215203 }
216- else
217- {
218- // No preprocessing involved.
219- // We build here a "reversed" geometry of all the polygons
220- //
221- // The final geometry is a multipolygon F, with :
222- // * the first polygon of F having the current extent as its exterior ring
223- // * each polygon's exterior ring is added as interior ring of the first polygon of F
224- // * each polygon's interior ring is added as new polygons in F
225- //
226- // No validity check is done, on purpose, it will be very slow and painting
227- // operations do not need geometries to be valid
228-
229- QgsMultiPolygon multi;
230- if (( geom->wkbType () == QGis::WKBPolygon ) ||
231- ( geom->wkbType () == QGis::WKBPolygon25D ) )
232- {
233- multi.append ( geom->asPolygon () );
234- }
235- else if (( geom->wkbType () == QGis::WKBMultiPolygon ) ||
236- ( geom->wkbType () == QGis::WKBMultiPolygon25D ) )
237- {
238- multi = geom->asMultiPolygon ();
239- }
240-
241- for ( int i = 0 ; i < multi.size (); i++ )
242- {
243- // add the exterior ring as interior ring to the first polygon
244- cFeat.multiPolygon [0 ].append ( multi[i][0 ] );
204+ // add the geometry to the list of geometries for this feature
205+ cFeat.geometries .append ( geom.take () );
245206
246- // add interior rings as new polygons
247- for ( int j = 1 ; j < multi[i].size (); j++ )
248- {
249- QgsPolygon new_poly;
250- new_poly.append ( multi[i][j] );
251- cFeat.multiPolygon .append ( new_poly );
252- }
253- }
254- }
255207 return true ;
256208}
257209
@@ -268,23 +220,61 @@ void QgsInvertedPolygonRenderer::stopRender( QgsRenderContext& context )
268220
269221 for ( FeatureCategoryVector::iterator cit = mFeaturesCategories .begin (); cit != mFeaturesCategories .end (); ++cit )
270222 {
271- QgsFeature feat ( cit->feature ) ;
272- if ( ! mPreprocessingEnabled )
223+ QgsFeature& feat = cit->feature ;
224+ if ( mPreprocessingEnabled )
273225 {
274- // no preprocessing - the final polygon has already been prepared
275- feat.setGeometry ( QgsGeometry::fromMultiPolygon ( cit->multiPolygon ) );
226+ // compute the unary union on the polygons
227+ QScopedPointer<QgsGeometry> unioned ( QgsGeometryAlgorithms::unaryUnion ( cit->geometries ) );
228+ // compute the difference with the extent
229+ QScopedPointer<QgsGeometry> rect ( QgsGeometry::fromPolygon ( mExtentPolygon ) );
230+ QgsGeometry *final = rect->difference ( const_cast <QgsGeometry*>(unioned.data ()) );
231+ if ( final )
232+ {
233+ feat.setGeometry ( final );
234+ }
276235 }
277236 else
278237 {
279- // preprocessing mode - we still have to invert (using difference)
280- if ( feat.geometry () )
238+ // No preprocessing involved.
239+ // We build here a "reversed" geometry of all the polygons
240+ //
241+ // The final geometry is a multipolygon F, with :
242+ // * the first polygon of F having the current extent as its exterior ring
243+ // * each polygon's exterior ring is added as interior ring of the first polygon of F
244+ // * each polygon's interior ring is added as new polygons in F
245+ //
246+ // No validity check is done, on purpose, it will be very slow and painting
247+ // operations do not need geometries to be valid
248+ QgsMultiPolygon finalMulti;
249+ finalMulti.append ( mExtentPolygon );
250+ foreach ( QgsGeometry* geom, cit->geometries )
281251 {
282- QScopedPointer<QgsGeometry> rect ( QgsGeometry::fromPolygon ( mExtentPolygon ) );
283- QgsGeometry *final = rect->difference ( feat.geometry () );
284- if ( final )
252+ QgsMultiPolygon multi;
253+ if (( geom->wkbType () == QGis::WKBPolygon ) ||
254+ ( geom->wkbType () == QGis::WKBPolygon25D ) )
255+ {
256+ multi.append ( geom->asPolygon () );
257+ }
258+ else if (( geom->wkbType () == QGis::WKBMultiPolygon ) ||
259+ ( geom->wkbType () == QGis::WKBMultiPolygon25D ) )
260+ {
261+ multi = geom->asMultiPolygon ();
262+ }
263+
264+ for ( int i = 0 ; i < multi.size (); i++ )
285265 {
286- feat.setGeometry ( final );
266+ // add the exterior ring as interior ring to the first polygon
267+ finalMulti[0 ].append ( multi[i][0 ] );
268+
269+ // add interior rings as new polygons
270+ for ( int j = 1 ; j < multi[i].size (); j++ )
271+ {
272+ QgsPolygon new_poly;
273+ new_poly.append ( multi[i][j] );
274+ finalMulti.append ( new_poly );
275+ }
287276 }
277+ feat.setGeometry ( QgsGeometry::fromMultiPolygon ( finalMulti ) );
288278 }
289279 }
290280 mSubRenderer ->renderFeature ( feat, mContext );
0 commit comments