Skip to content

Commit

Permalink
Use direct QPainterPaths when clipping map renders using a QPainter b…
Browse files Browse the repository at this point in the history
…ased clip

Allows correct clipping to multipolygons, polygons with holes, etc
  • Loading branch information
nyalldawson committed Jul 3, 2020
1 parent 205273e commit 040dd56
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 9 deletions.
10 changes: 8 additions & 2 deletions src/core/geometry/qgscurvepolygon.cpp
Expand Up @@ -772,11 +772,17 @@ QPainterPath QgsCurvePolygon::asQPainterPath() const
{
QPainterPath p;
if ( mExteriorRing )
mExteriorRing->addToPainterPath( p );
{
QPainterPath ring = mExteriorRing->asQPainterPath();
ring.closeSubpath();
p.addPath( ring );
}

for ( const QgsCurve *ring : mInteriorRings )
{
p.addPath( ring->asQPainterPath() );
QPainterPath ringPath = ring->asQPainterPath();
ringPath.closeSubpath();
p.addPath( ringPath );
}

return p;
Expand Down
7 changes: 1 addition & 6 deletions src/core/qgsmapclippingutils.cpp
Expand Up @@ -169,15 +169,10 @@ QPainterPath QgsMapClippingUtils::calculatePainterClipRegion( const QList<QgsMap
if ( !shouldClip )
return QPainterPath();

// filter out polygon parts from result only
result.convertGeometryCollectionToSubclass( QgsWkbTypes::PolygonGeometry );

// transform to painter coordinates
result.mapToPixel( context.mapToPixel() );

QPainterPath path;
path.addPolygon( result.asQPolygonF() );
return path;
return result.constGet()->asQPainterPath();
}

QgsGeometry QgsMapClippingUtils::calculateLabelIntersectionGeometry( const QList<QgsMapClippingRegion> &regions, const QgsRenderContext &context, bool &shouldClip )
Expand Down
4 changes: 3 additions & 1 deletion tests/src/python/test_qgsgeometry.py
Expand Up @@ -5902,7 +5902,6 @@ def testGeometryDraw(self):
rendered_image = self.renderGeometry(geom, False, True)
assert self.imageCheck(test['name'] + '_aspolygon', test['as_polygon_reference_image'], rendered_image)


def testGeometryAsQPainterPath(self):
'''Tests conversion of different geometries to QPainterPath, including bad/odd geometries.'''

Expand Down Expand Up @@ -5980,6 +5979,9 @@ def testGeometryAsQPainterPath(self):
{'name': 'Collection Mixed',
'wkt': 'GeometryCollection(Point(1 2), MultiPoint(3 3, 2 3), LineString (0 0,3 4,4 3), MultiLineString((3 1, 3 2, 4 2)), Polygon((0 0, 1 0, 1 1, 2 1, 2 2, 0 2, 0 0)), MultiPolygon(((4 0, 5 0, 5 1, 6 1, 6 2, 4 2, 4 0)),(( 1 4, 2 4, 1 5, 1 4))))',
'reference_image': 'collection_mixed'},
{'name': 'MultiCurvePolygon',
'wkt': 'MultiSurface (CurvePolygon (CompoundCurve (CircularString (-12942312 4593500, -11871048 5481118, -11363838 5065730, -11551856 4038191, -12133399 4130014),(-12133399 4130014, -12942312 4593500)),(-12120281 5175043, -12456964 4694067, -11752991 4256817, -11569346 4943300, -12120281 5175043)),Polygon ((-10856627 5625411, -11083997 4995770, -10887235 4357384, -9684796 4851477, -10069576 5428648, -10856627 5625411)))',
'reference_image': 'multicurvepolygon_with_rings'}
]

for test in tests:
Expand Down
40 changes: 40 additions & 0 deletions tests/src/python/test_qgsvectorlayerrenderer.py
Expand Up @@ -229,6 +229,46 @@ def testRenderWithPainterClipRegions(self):
self.report += renderchecker.report()
self.assertTrue(result)

def testRenderWithPainterClipRegionsMultiPolygon(self):
poly_layer = QgsVectorLayer(os.path.join(TEST_DATA_DIR, 'polys.shp'))
self.assertTrue(poly_layer.isValid())

sym1 = QgsFillSymbol.createSimple({'color': '#ff00ff', 'outline_color': '#000000', 'outline_width': '1'})
renderer = QgsSingleSymbolRenderer(sym1)
poly_layer.setRenderer(renderer)

mapsettings = QgsMapSettings()
mapsettings.setOutputSize(QSize(400, 400))
mapsettings.setOutputDpi(96)
mapsettings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3857'))
mapsettings.setExtent(QgsRectangle(-13875783.2, 2266009.4, -8690110.7, 6673344.5))
mapsettings.setLayers([poly_layer])

region = QgsMapClippingRegion(QgsGeometry.fromWkt(
'MultiSurface (Polygon ((-10856627.66351187042891979 5625411.45629768911749125, -11083997.96136780828237534 4995770.63146586995571852, -10887235.20360786281526089 4357384.79517805296927691, -9684796.12840820662677288 4851477.9424419105052948, -10069576.63247209787368774 5428648.69853774644434452, -10856627.66351187042891979 5625411.45629768911749125)),Polygon ((-12045949.22152753174304962 5533588.83600971661508083, -12758667.65519132651388645 4868967.96535390708595514, -12478827.28859940730035305 4296169.71498607192188501, -11783598.87784760631620884 4077544.42858613422140479, -11223918.14466376602649689 4715930.26487395167350769, -11127723.01864779368042946 5673509.01930567622184753, -11359465.8222317285835743 5809056.69687363691627979, -12045949.22152753174304962 5533588.83600971661508083),(-11341975.79931973293423653 4790262.86224992945790291, -11722383.7976556234061718 4318032.24362606555223465, -12019714.18715953826904297 4606617.62167398259043694, -11757363.84347961470484734 4908320.51690589636564255, -11341975.79931973293423653 4790262.86224992945790291)))'))
region.setFeatureClip(QgsMapClippingRegion.FeatureClippingType.ClipPainterOnly)
mapsettings.addClippingRegion(region)

renderchecker = QgsMultiRenderChecker()
renderchecker.setMapSettings(mapsettings)
renderchecker.setControlPathPrefix('vectorlayerrenderer')
renderchecker.setControlName('expected_painterclip_region_multi')
result = renderchecker.runTest('expected_painterclip_region_multi')
self.report += renderchecker.report()
self.assertTrue(result)

# also try with symbol levels
renderer.setUsingSymbolLevels(True)
poly_layer.setRenderer(renderer)

renderchecker = QgsMultiRenderChecker()
renderchecker.setMapSettings(mapsettings)
renderchecker.setControlPathPrefix('vectorlayerrenderer')
renderchecker.setControlName('expected_painterclip_region_multi')
result = renderchecker.runTest('expected_painterclip_region_multi')
self.report += renderchecker.report()
self.assertTrue(result)


if __name__ == '__main__':
unittest.main()
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 040dd56

Please sign in to comment.