Skip to content

Commit

Permalink
Respect map clipping regions when rendering point clouds in 2d
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jan 4, 2021
1 parent 25e54a7 commit c7a9d5a
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 17 deletions.
12 changes: 11 additions & 1 deletion src/core/pointcloud/qgspointcloudlayerrenderer.cpp
Expand Up @@ -31,7 +31,7 @@
#include "qgspointcloudlayerelevationproperties.h"
#include "qgsmessagelog.h"
#include "qgscircle.h"

#include "qgsmapclippingutils.h"

QgsPointCloudLayerRenderer::QgsPointCloudLayerRenderer( QgsPointCloudLayer *layer, QgsRenderContext &context )
: QgsMapLayerRenderer( layer->id(), &context )
Expand All @@ -58,6 +58,8 @@ QgsPointCloudLayerRenderer::QgsPointCloudLayerRenderer( QgsPointCloudLayer *laye
}

mCloudExtent = mLayer->dataProvider()->polygonBounds();

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

bool QgsPointCloudLayerRenderer::render()
Expand All @@ -70,6 +72,14 @@ bool QgsPointCloudLayerRenderer::render()
QgsScopedQPainterState painterState( painter );
context.renderContext().setPainterFlagsUsingContext( 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 );
}

if ( mRenderer->type() == QLatin1String( "extent" ) )
{
// special case for extent only renderer!
Expand Down
3 changes: 3 additions & 0 deletions src/core/pointcloud/qgspointcloudlayerrenderer.h
Expand Up @@ -29,6 +29,7 @@
#include "qgspointcloudindex.h"
#include "qgsidentifycontext.h"
#include "qgspointcloudrenderer.h"
#include "qgsmapclippingregion.h"

#include <QDomElement>
#include <QString>
Expand Down Expand Up @@ -77,6 +78,8 @@ class CORE_EXPORT QgsPointCloudLayerRenderer: public QgsMapLayerRenderer
QgsPointCloudAttributeCollection mLayerAttributes;
QgsPointCloudAttributeCollection mAttributes;
QgsGeometry mCloudExtent;
QList< QgsMapClippingRegion > mClippingRegions;

};

#endif // QGSPOINTCLOUDLAYERRENDERER_H
73 changes: 57 additions & 16 deletions tests/src/python/test_qgspointcloudrgbrenderer.py
Expand Up @@ -11,7 +11,9 @@
__copyright__ = 'Copyright 2020, The QGIS Project'

import qgis # NOQA

from qgis.PyQt.QtCore import QDir, QSize
from qgis.PyQt.QtGui import QPainter
from qgis.PyQt.QtXml import QDomDocument
from qgis.core import (
QgsProviderRegistry,
QgsPointCloudLayer,
Expand All @@ -28,14 +30,12 @@
QgsMapUnitScale,
QgsCoordinateReferenceSystem,
QgsDoubleRange,
QgsPointCloudRenderer
QgsPointCloudRenderer,
QgsMapClippingRegion,
QgsGeometry
)

from qgis.PyQt.QtCore import QDir, QSize
from qgis.PyQt.QtGui import QPainter
from qgis.PyQt.QtXml import QDomDocument

from qgis.testing import start_app, unittest

from utilities import unitTestDataPath

start_app()
Expand Down Expand Up @@ -77,13 +77,16 @@ def testSetLayer16(self):
# for this point cloud, we should default to 0-65024 ranges with contrast enhancement
self.assertEqual(layer.renderer().redContrastEnhancement().minimumValue(), 0)
self.assertEqual(layer.renderer().redContrastEnhancement().maximumValue(), 65535.0)
self.assertEqual(layer.renderer().redContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.StretchToMinimumMaximum)
self.assertEqual(layer.renderer().redContrastEnhancement().contrastEnhancementAlgorithm(),
QgsContrastEnhancement.StretchToMinimumMaximum)
self.assertEqual(layer.renderer().greenContrastEnhancement().minimumValue(), 0)
self.assertEqual(layer.renderer().greenContrastEnhancement().maximumValue(), 65535.0)
self.assertEqual(layer.renderer().greenContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.StretchToMinimumMaximum)
self.assertEqual(layer.renderer().greenContrastEnhancement().contrastEnhancementAlgorithm(),
QgsContrastEnhancement.StretchToMinimumMaximum)
self.assertEqual(layer.renderer().blueContrastEnhancement().minimumValue(), 0)
self.assertEqual(layer.renderer().blueContrastEnhancement().maximumValue(), 65535.0)
self.assertEqual(layer.renderer().blueContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.StretchToMinimumMaximum)
self.assertEqual(layer.renderer().blueContrastEnhancement().contrastEnhancementAlgorithm(),
QgsContrastEnhancement.StretchToMinimumMaximum)

def testBasic(self):
renderer = QgsPointCloudRgbRenderer()
Expand Down Expand Up @@ -131,13 +134,16 @@ def testBasic(self):
self.assertEqual(rr.redAttribute(), 'r')
self.assertEqual(rr.redContrastEnhancement().minimumValue(), 100)
self.assertEqual(rr.redContrastEnhancement().maximumValue(), 120)
self.assertEqual(rr.redContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.StretchAndClipToMinimumMaximum)
self.assertEqual(rr.redContrastEnhancement().contrastEnhancementAlgorithm(),
QgsContrastEnhancement.StretchAndClipToMinimumMaximum)
self.assertEqual(rr.greenContrastEnhancement().minimumValue(), 130)
self.assertEqual(rr.greenContrastEnhancement().maximumValue(), 150)
self.assertEqual(rr.greenContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.StretchToMinimumMaximum)
self.assertEqual(rr.greenContrastEnhancement().contrastEnhancementAlgorithm(),
QgsContrastEnhancement.StretchToMinimumMaximum)
self.assertEqual(rr.blueContrastEnhancement().minimumValue(), 170)
self.assertEqual(rr.blueContrastEnhancement().maximumValue(), 190)
self.assertEqual(rr.blueContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.ClipToMinimumMaximum)
self.assertEqual(rr.blueContrastEnhancement().contrastEnhancementAlgorithm(),
QgsContrastEnhancement.ClipToMinimumMaximum)

doc = QDomDocument("testdoc")
elem = renderer.save(doc, QgsReadWriteContext())
Expand All @@ -155,13 +161,16 @@ def testBasic(self):
self.assertEqual(r2.redAttribute(), 'r')
self.assertEqual(r2.redContrastEnhancement().minimumValue(), 100)
self.assertEqual(r2.redContrastEnhancement().maximumValue(), 120)
self.assertEqual(r2.redContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.StretchAndClipToMinimumMaximum)
self.assertEqual(r2.redContrastEnhancement().contrastEnhancementAlgorithm(),
QgsContrastEnhancement.StretchAndClipToMinimumMaximum)
self.assertEqual(r2.greenContrastEnhancement().minimumValue(), 130)
self.assertEqual(r2.greenContrastEnhancement().maximumValue(), 150)
self.assertEqual(r2.greenContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.StretchToMinimumMaximum)
self.assertEqual(r2.greenContrastEnhancement().contrastEnhancementAlgorithm(),
QgsContrastEnhancement.StretchToMinimumMaximum)
self.assertEqual(r2.blueContrastEnhancement().minimumValue(), 170)
self.assertEqual(r2.blueContrastEnhancement().maximumValue(), 190)
self.assertEqual(r2.blueContrastEnhancement().contrastEnhancementAlgorithm(), QgsContrastEnhancement.ClipToMinimumMaximum)
self.assertEqual(r2.blueContrastEnhancement().contrastEnhancementAlgorithm(),
QgsContrastEnhancement.ClipToMinimumMaximum)

def testUsedAttributes(self):
renderer = QgsPointCloudRgbRenderer()
Expand Down Expand Up @@ -381,6 +390,38 @@ def testRenderZRange(self):
TestQgsPointCloudRgbRenderer.report += renderchecker.report()
self.assertTrue(result)

@unittest.skipIf('ept' not in QgsProviderRegistry.instance().providerList(), 'EPT provider not available')
def testRenderClipRegion(self):
layer = QgsPointCloudLayer(unitTestDataPath() + '/point_clouds/ept/rgb/ept.json', 'test', 'ept')
self.assertTrue(layer.isValid())

layer.renderer().setPointSize(2)
layer.renderer().setPointSizeUnit(QgsUnitTypes.RenderMillimeters)

mapsettings = QgsMapSettings()
mapsettings.setOutputSize(QSize(400, 400))
mapsettings.setOutputDpi(96)
mapsettings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
mapsettings.setExtent(QgsRectangle(152.977434544, -26.663017454, 152.977424882, -26.663009624))
mapsettings.setLayers([layer])

region = QgsMapClippingRegion(QgsGeometry.fromWkt(
'Polygon ((152.97742833685992991 -26.66301088198133584, 152.97742694456141521 -26.66301085776744983, 152.97742676295726483 -26.66301358182974468, 152.97742895431403554 -26.66301349708113833, 152.97742833685992991 -26.66301088198133584))'))
region.setFeatureClip(QgsMapClippingRegion.FeatureClippingType.ClipPainterOnly)
region2 = QgsMapClippingRegion(QgsGeometry.fromWkt(
'Polygon ((152.97743215054714483 -26.66301111201326535, 152.97742715037946937 -26.66301116044103736, 152.97742754990858316 -26.66301436878107367, 152.97743264693181686 -26.66301491359353193, 152.97743215054714483 -26.66301111201326535))'))
region2.setFeatureClip(QgsMapClippingRegion.FeatureClippingType.ClipToIntersection)
mapsettings.addClippingRegion(region)
mapsettings.addClippingRegion(region2)

renderchecker = QgsMultiRenderChecker()
renderchecker.setMapSettings(mapsettings)
renderchecker.setControlPathPrefix('pointcloudrenderer')
renderchecker.setControlName('expected_clip_region')
result = renderchecker.runTest('expected_clip_region')
TestQgsPointCloudRgbRenderer.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.

0 comments on commit c7a9d5a

Please sign in to comment.