Skip to content
Permalink
Browse files

Respect painter clipping regions during vector tile rendering

  • Loading branch information
nyalldawson committed Jul 2, 2020
1 parent 2a17e7b commit 9ec6c213558288b8c42a6a07ca0dac32cc969b34
@@ -286,7 +286,7 @@ void QgsMeshLayerRenderer::copyVectorDatasetValues( QgsMeshLayer *layer )

bool QgsMeshLayerRenderer::render()
{
renderContext()->painter()->save();
QgsScopedQPainterState painterState( renderContext()->painter() );
if ( !mClippingRegions.empty() )
{
bool needsPainterClipPath = false;
@@ -299,7 +299,6 @@ bool QgsMeshLayerRenderer::render()
renderMesh();
renderVectorDataset();

renderContext()->painter()->restore();
return true;
}

@@ -140,6 +140,12 @@ QPainterPath QgsMapClippingUtils::calculatePainterClipRegion( const QList<QgsMap
continue;
break;

case QgsMapLayerType::VectorTileLayer:
// for now, we ignore the region's featureClip behavior when rendering vector tiles
// TODO: ideally we should apply this during rendering, just like we do for normal
// vector layers
break;

case QgsMapLayerType::MeshLayer:
case QgsMapLayerType::RasterLayer:
case QgsMapLayerType::PluginLayer:
@@ -283,7 +283,7 @@ bool QgsRasterLayerRenderer::render()
// procedure to use :
//

renderContext()->painter()->save();
QgsScopedQPainterState painterSate( renderContext()->painter() );
if ( !mClippingRegions.empty() )
{
bool needsPainterClipPath = false;
@@ -321,8 +321,6 @@ bool QgsRasterLayerRenderer::render()
mPipe->setResamplingStage( oldResamplingState );
}

renderContext()->painter()->restore();

const QStringList errors = mFeedback->errors();
for ( const QString &error : errors )
{
@@ -28,7 +28,7 @@

#include "qgslabelingengine.h"
#include "qgsvectortilelabeling.h"

#include "qgsmapclippingutils.h"

QgsVectorTileLayerRenderer::QgsVectorTileLayerRenderer( QgsVectorTileLayer *layer, QgsRenderContext &context )
: QgsMapLayerRenderer( layer->id(), &context )
@@ -53,6 +53,7 @@ QgsVectorTileLayerRenderer::QgsVectorTileLayerRenderer( QgsVectorTileLayer *laye
}
}

mClippingRegions = QgsMapClippingUtils::collectClippingRegionsForLayer( *renderContext(), layer );
}

bool QgsVectorTileLayerRenderer::render()
@@ -64,6 +65,14 @@ bool QgsVectorTileLayerRenderer::render()

QgsScopedQPainterState painterState( ctx.painter() );

if ( !mClippingRegions.empty() )
{
bool needsPainterClipPath = false;
const QPainterPath path = QgsMapClippingUtils::calculatePainterClipRegion( mClippingRegions, *renderContext(), QgsMapLayerType::VectorTileLayer, needsPainterClipPath );
if ( needsPainterClipPath )
renderContext()->painter()->setClipPath( path, Qt::IntersectClip );
}

QElapsedTimer tTotal;
tTotal.start();

@@ -25,6 +25,7 @@ class QgsVectorTileRawData;
class QgsVectorTileLabelProvider;

#include "qgsvectortilerenderer.h"
#include "qgsmapclippingregion.h"

/**
* \ingroup core
@@ -87,6 +88,8 @@ class QgsVectorTileLayerRenderer : public QgsMapLayerRenderer
int mTotalDecodeTime = 0;
//! Counter of total elapsed time to render tiles (ms)
int mTotalDrawTime = 0;

QList< QgsMapClippingRegion > mClippingRegions;
};


@@ -54,6 +54,7 @@ class TestQgsVectorTileLayer : public QObject

void test_basic();
void test_render();
void test_render_withClip();
void test_labeling();
void test_relativePaths();
};
@@ -137,6 +138,19 @@ void TestQgsVectorTileLayer::test_render()
QVERIFY( imageCheck( "render_test_basic", mLayer, mLayer->extent() ) );
}

void TestQgsVectorTileLayer::test_render_withClip()
{
QgsMapClippingRegion region( QgsGeometry::fromWkt( "Polygon ((-3584104.41462873760610819 9642431.51156153343617916, -3521836.1401221314445138 -3643384.67029104987159371, -346154.14028519613202661 -10787760.6154897827655077, 11515952.15322335436940193 -10530608.51481428928673267, 11982964.21202290244400501 11308099.1972544826567173, -3584104.41462873760610819 9642431.51156153343617916))" ) );
region.setFeatureClip( QgsMapClippingRegion::FeatureClippingType::PainterClip );
QgsMapClippingRegion region2( QgsGeometry::fromWkt( "Polygon ((836943.07534032803960145 12108307.34630974195897579, 1179418.58512666448950768 -8011790.66139839310199022, 17306901.68233776465058327 -8130936.37545258551836014, 17680511.32937740534543991 14072993.65374799631536007, 836943.07534032803960145 12108307.34630974195897579))" ) );
region2.setFeatureClip( QgsMapClippingRegion::FeatureClippingType::Intersect );
mMapSettings->addClippingRegion( region );
mMapSettings->addClippingRegion( region2 );
const bool res = imageCheck( "render_painterclip", mLayer, mLayer->extent() );
mMapSettings->setClippingRegions( QList< QgsMapClippingRegion >() );
QVERIFY( res );
}

void TestQgsVectorTileLayer::test_labeling()
{
QgsTextFormat format;
@@ -124,12 +124,12 @@ def testPainterClipPath(self):

rc = QgsRenderContext()

for t in [QgsMapLayerType.VectorLayer, QgsMapLayerType.RasterLayer, QgsMapLayerType.MeshLayer]:
for t in [QgsMapLayerType.VectorLayer, QgsMapLayerType.RasterLayer, QgsMapLayerType.MeshLayer, QgsMapLayerType.VectorTileLayer]:
path, should_clip = QgsMapClippingUtils.calculatePainterClipRegion([], rc, t)
self.assertFalse(should_clip)
self.assertEqual(path.elementCount(), 0)

for t in [QgsMapLayerType.VectorLayer, QgsMapLayerType.RasterLayer, QgsMapLayerType.MeshLayer]:
for t in [QgsMapLayerType.VectorLayer, QgsMapLayerType.RasterLayer, QgsMapLayerType.MeshLayer, QgsMapLayerType.VectorTileLayer]:
path, should_clip = QgsMapClippingUtils.calculatePainterClipRegion([region], rc, t)
self.assertTrue(should_clip)
self.assertEqual(QgsGeometry.fromQPolygonF(path.toFillPolygon()).asWkt(1), 'Polygon ((0 1, 1 1, 1 0, 0 0, 0 1))')
@@ -139,18 +139,18 @@ def testPainterClipPath(self):
self.assertFalse(should_clip)
self.assertEqual(path.elementCount(), 0)

for t in [QgsMapLayerType.RasterLayer, QgsMapLayerType.MeshLayer]:
for t in [QgsMapLayerType.RasterLayer, QgsMapLayerType.MeshLayer, QgsMapLayerType.VectorTileLayer]:
path, should_clip = QgsMapClippingUtils.calculatePainterClipRegion([region2], rc, t)
self.assertTrue(should_clip)
self.assertEqual(QgsGeometry.fromQPolygonF(path.toFillPolygon()).asWkt(1), 'Polygon ((0 1, 0.1 1, 0.1 -1, 0 -1, 0 1))')

for t in [QgsMapLayerType.VectorLayer, QgsMapLayerType.RasterLayer, QgsMapLayerType.MeshLayer]:
for t in [QgsMapLayerType.VectorLayer, QgsMapLayerType.RasterLayer, QgsMapLayerType.MeshLayer, QgsMapLayerType.VectorTileLayer]:
path, should_clip = QgsMapClippingUtils.calculatePainterClipRegion([region, region2, region3], rc, t)
self.assertTrue(should_clip)
self.assertEqual(QgsGeometry.fromQPolygonF(path.toFillPolygon()).asWkt(1), 'Polygon ((0.1 1, 0 1, 0 0, 0.1 0, 0.1 1))')

rc.setMapToPixel(QgsMapToPixel(5, 10, 11, 200, 150, 0))
for t in [QgsMapLayerType.VectorLayer, QgsMapLayerType.RasterLayer, QgsMapLayerType.MeshLayer]:
for t in [QgsMapLayerType.VectorLayer, QgsMapLayerType.RasterLayer, QgsMapLayerType.MeshLayer, QgsMapLayerType.VectorTileLayer]:
path, should_clip = QgsMapClippingUtils.calculatePainterClipRegion([region, region3], rc, t)
self.assertTrue(should_clip)
self.assertEqual(QgsGeometry.fromQPolygonF(path.toFillPolygon()).asWkt(0), 'Polygon ((98 77, 98 77, 98 77, 98 77, 98 77))')
Binary file not shown.

0 comments on commit 9ec6c21

Please sign in to comment.
You can’t perform that action at this time.