Skip to content

Commit c7a9d5a

Browse files
committedJan 4, 2021
Respect map clipping regions when rendering point clouds in 2d
1 parent 25e54a7 commit c7a9d5a

File tree

4 files changed

+71
-17
lines changed

4 files changed

+71
-17
lines changed
 

‎src/core/pointcloud/qgspointcloudlayerrenderer.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#include "qgspointcloudlayerelevationproperties.h"
3232
#include "qgsmessagelog.h"
3333
#include "qgscircle.h"
34-
34+
#include "qgsmapclippingutils.h"
3535

3636
QgsPointCloudLayerRenderer::QgsPointCloudLayerRenderer( QgsPointCloudLayer *layer, QgsRenderContext &context )
3737
: QgsMapLayerRenderer( layer->id(), &context )
@@ -58,6 +58,8 @@ QgsPointCloudLayerRenderer::QgsPointCloudLayerRenderer( QgsPointCloudLayer *laye
5858
}
5959

6060
mCloudExtent = mLayer->dataProvider()->polygonBounds();
61+
62+
mClippingRegions = QgsMapClippingUtils::collectClippingRegionsForLayer( *renderContext(), layer );
6163
}
6264

6365
bool QgsPointCloudLayerRenderer::render()
@@ -70,6 +72,14 @@ bool QgsPointCloudLayerRenderer::render()
7072
QgsScopedQPainterState painterState( painter );
7173
context.renderContext().setPainterFlagsUsingContext( painter );
7274

75+
if ( !mClippingRegions.empty() )
76+
{
77+
bool needsPainterClipPath = false;
78+
const QPainterPath path = QgsMapClippingUtils::calculatePainterClipRegion( mClippingRegions, *renderContext(), QgsMapLayerType::VectorTileLayer, needsPainterClipPath );
79+
if ( needsPainterClipPath )
80+
renderContext()->painter()->setClipPath( path, Qt::IntersectClip );
81+
}
82+
7383
if ( mRenderer->type() == QLatin1String( "extent" ) )
7484
{
7585
// special case for extent only renderer!

‎src/core/pointcloud/qgspointcloudlayerrenderer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "qgspointcloudindex.h"
3030
#include "qgsidentifycontext.h"
3131
#include "qgspointcloudrenderer.h"
32+
#include "qgsmapclippingregion.h"
3233

3334
#include <QDomElement>
3435
#include <QString>
@@ -77,6 +78,8 @@ class CORE_EXPORT QgsPointCloudLayerRenderer: public QgsMapLayerRenderer
7778
QgsPointCloudAttributeCollection mLayerAttributes;
7879
QgsPointCloudAttributeCollection mAttributes;
7980
QgsGeometry mCloudExtent;
81+
QList< QgsMapClippingRegion > mClippingRegions;
82+
8083
};
8184

8285
#endif // QGSPOINTCLOUDLAYERRENDERER_H

‎tests/src/python/test_qgspointcloudrgbrenderer.py

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
__copyright__ = 'Copyright 2020, The QGIS Project'
1212

1313
import qgis # NOQA
14-
14+
from qgis.PyQt.QtCore import QDir, QSize
15+
from qgis.PyQt.QtGui import QPainter
16+
from qgis.PyQt.QtXml import QDomDocument
1517
from qgis.core import (
1618
QgsProviderRegistry,
1719
QgsPointCloudLayer,
@@ -28,14 +30,12 @@
2830
QgsMapUnitScale,
2931
QgsCoordinateReferenceSystem,
3032
QgsDoubleRange,
31-
QgsPointCloudRenderer
33+
QgsPointCloudRenderer,
34+
QgsMapClippingRegion,
35+
QgsGeometry
3236
)
33-
34-
from qgis.PyQt.QtCore import QDir, QSize
35-
from qgis.PyQt.QtGui import QPainter
36-
from qgis.PyQt.QtXml import QDomDocument
37-
3837
from qgis.testing import start_app, unittest
38+
3939
from utilities import unitTestDataPath
4040

4141
start_app()
@@ -77,13 +77,16 @@ def testSetLayer16(self):
7777
# for this point cloud, we should default to 0-65024 ranges with contrast enhancement
7878
self.assertEqual(layer.renderer().redContrastEnhancement().minimumValue(), 0)
7979
self.assertEqual(layer.renderer().redContrastEnhancement().maximumValue(), 65535.0)
80-
self.assertEqual(layer.renderer().redContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.StretchToMinimumMaximum)
80+
self.assertEqual(layer.renderer().redContrastEnhancement().contrastEnhancementAlgorithm(),
81+
QgsContrastEnhancement.StretchToMinimumMaximum)
8182
self.assertEqual(layer.renderer().greenContrastEnhancement().minimumValue(), 0)
8283
self.assertEqual(layer.renderer().greenContrastEnhancement().maximumValue(), 65535.0)
83-
self.assertEqual(layer.renderer().greenContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.StretchToMinimumMaximum)
84+
self.assertEqual(layer.renderer().greenContrastEnhancement().contrastEnhancementAlgorithm(),
85+
QgsContrastEnhancement.StretchToMinimumMaximum)
8486
self.assertEqual(layer.renderer().blueContrastEnhancement().minimumValue(), 0)
8587
self.assertEqual(layer.renderer().blueContrastEnhancement().maximumValue(), 65535.0)
86-
self.assertEqual(layer.renderer().blueContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.StretchToMinimumMaximum)
88+
self.assertEqual(layer.renderer().blueContrastEnhancement().contrastEnhancementAlgorithm(),
89+
QgsContrastEnhancement.StretchToMinimumMaximum)
8790

8891
def testBasic(self):
8992
renderer = QgsPointCloudRgbRenderer()
@@ -131,13 +134,16 @@ def testBasic(self):
131134
self.assertEqual(rr.redAttribute(), 'r')
132135
self.assertEqual(rr.redContrastEnhancement().minimumValue(), 100)
133136
self.assertEqual(rr.redContrastEnhancement().maximumValue(), 120)
134-
self.assertEqual(rr.redContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.StretchAndClipToMinimumMaximum)
137+
self.assertEqual(rr.redContrastEnhancement().contrastEnhancementAlgorithm(),
138+
QgsContrastEnhancement.StretchAndClipToMinimumMaximum)
135139
self.assertEqual(rr.greenContrastEnhancement().minimumValue(), 130)
136140
self.assertEqual(rr.greenContrastEnhancement().maximumValue(), 150)
137-
self.assertEqual(rr.greenContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.StretchToMinimumMaximum)
141+
self.assertEqual(rr.greenContrastEnhancement().contrastEnhancementAlgorithm(),
142+
QgsContrastEnhancement.StretchToMinimumMaximum)
138143
self.assertEqual(rr.blueContrastEnhancement().minimumValue(), 170)
139144
self.assertEqual(rr.blueContrastEnhancement().maximumValue(), 190)
140-
self.assertEqual(rr.blueContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.ClipToMinimumMaximum)
145+
self.assertEqual(rr.blueContrastEnhancement().contrastEnhancementAlgorithm(),
146+
QgsContrastEnhancement.ClipToMinimumMaximum)
141147

142148
doc = QDomDocument("testdoc")
143149
elem = renderer.save(doc, QgsReadWriteContext())
@@ -155,13 +161,16 @@ def testBasic(self):
155161
self.assertEqual(r2.redAttribute(), 'r')
156162
self.assertEqual(r2.redContrastEnhancement().minimumValue(), 100)
157163
self.assertEqual(r2.redContrastEnhancement().maximumValue(), 120)
158-
self.assertEqual(r2.redContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.StretchAndClipToMinimumMaximum)
164+
self.assertEqual(r2.redContrastEnhancement().contrastEnhancementAlgorithm(),
165+
QgsContrastEnhancement.StretchAndClipToMinimumMaximum)
159166
self.assertEqual(r2.greenContrastEnhancement().minimumValue(), 130)
160167
self.assertEqual(r2.greenContrastEnhancement().maximumValue(), 150)
161-
self.assertEqual(r2.greenContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.StretchToMinimumMaximum)
168+
self.assertEqual(r2.greenContrastEnhancement().contrastEnhancementAlgorithm(),
169+
QgsContrastEnhancement.StretchToMinimumMaximum)
162170
self.assertEqual(r2.blueContrastEnhancement().minimumValue(), 170)
163171
self.assertEqual(r2.blueContrastEnhancement().maximumValue(), 190)
164-
self.assertEqual(r2.blueContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.ClipToMinimumMaximum)
172+
self.assertEqual(r2.blueContrastEnhancement().contrastEnhancementAlgorithm(),
173+
QgsContrastEnhancement.ClipToMinimumMaximum)
165174

166175
def testUsedAttributes(self):
167176
renderer = QgsPointCloudRgbRenderer()
@@ -381,6 +390,38 @@ def testRenderZRange(self):
381390
TestQgsPointCloudRgbRenderer.report += renderchecker.report()
382391
self.assertTrue(result)
383392

393+
@unittest.skipIf('ept' not in QgsProviderRegistry.instance().providerList(), 'EPT provider not available')
394+
def testRenderClipRegion(self):
395+
layer = QgsPointCloudLayer(unitTestDataPath() + '/point_clouds/ept/rgb/ept.json', 'test', 'ept')
396+
self.assertTrue(layer.isValid())
397+
398+
layer.renderer().setPointSize(2)
399+
layer.renderer().setPointSizeUnit(QgsUnitTypes.RenderMillimeters)
400+
401+
mapsettings = QgsMapSettings()
402+
mapsettings.setOutputSize(QSize(400, 400))
403+
mapsettings.setOutputDpi(96)
404+
mapsettings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
405+
mapsettings.setExtent(QgsRectangle(152.977434544, -26.663017454, 152.977424882, -26.663009624))
406+
mapsettings.setLayers([layer])
407+
408+
region = QgsMapClippingRegion(QgsGeometry.fromWkt(
409+
'Polygon ((152.97742833685992991 -26.66301088198133584, 152.97742694456141521 -26.66301085776744983, 152.97742676295726483 -26.66301358182974468, 152.97742895431403554 -26.66301349708113833, 152.97742833685992991 -26.66301088198133584))'))
410+
region.setFeatureClip(QgsMapClippingRegion.FeatureClippingType.ClipPainterOnly)
411+
region2 = QgsMapClippingRegion(QgsGeometry.fromWkt(
412+
'Polygon ((152.97743215054714483 -26.66301111201326535, 152.97742715037946937 -26.66301116044103736, 152.97742754990858316 -26.66301436878107367, 152.97743264693181686 -26.66301491359353193, 152.97743215054714483 -26.66301111201326535))'))
413+
region2.setFeatureClip(QgsMapClippingRegion.FeatureClippingType.ClipToIntersection)
414+
mapsettings.addClippingRegion(region)
415+
mapsettings.addClippingRegion(region2)
416+
417+
renderchecker = QgsMultiRenderChecker()
418+
renderchecker.setMapSettings(mapsettings)
419+
renderchecker.setControlPathPrefix('pointcloudrenderer')
420+
renderchecker.setControlName('expected_clip_region')
421+
result = renderchecker.runTest('expected_clip_region')
422+
TestQgsPointCloudRgbRenderer.report += renderchecker.report()
423+
self.assertTrue(result)
424+
384425

385426
if __name__ == '__main__':
386427
unittest.main()

0 commit comments

Comments
 (0)
Please sign in to comment.