QGIS API Documentation 3.41.0-Master (88383c3d16f)
Loading...
Searching...
No Matches
qgspointcloudlayer3drenderer.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgspointcloudlayer3drenderer.cpp
3 --------------------------------------
4 Date : October 2020
5 Copyright : (C) 2020 by Peter Petrik
6 Email : zilolv dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17
18#include "qgs3dutils.h"
20
21#include "qgspointcloudindex.h"
22#include "qgspointcloudlayer.h"
24#include "qgsxmlutils.h"
25#include "qgs3dsymbolregistry.h"
28
29QgsPointCloud3DRenderContext::QgsPointCloud3DRenderContext( const Qgs3DRenderContext &context, const QgsCoordinateTransform &coordinateTransform, std::unique_ptr<QgsPointCloud3DSymbol> symbol, double zValueScale, double zValueFixedOffset )
30 : Qgs3DRenderContext( context )
31 , mSymbol( std::move( symbol ) )
32 , mZValueScale( zValueScale )
33 , mZValueFixedOffset( zValueFixedOffset )
34 , mCoordinateTransform( coordinateTransform )
35 , mFeedback( new QgsFeedback )
36{
37 updateExtent();
38}
39
44
46{
47 mSymbol.reset( symbol );
48}
49
51{
52 mFilteredOutCategories = categories;
53}
54
56{
57 QSet<int> filteredOut;
58 for ( const QgsPointCloudCategory &category : mFilteredOutCategories )
59 filteredOut.insert( category.value() );
60 return filteredOut;
61}
62
64{
65 mCoordinateTransform = coordinateTransform;
66 updateExtent();
67}
68
70{
71 return mFeedback->isCanceled();
72}
73
75{
76 mFeedback->cancel();
77}
78
79void QgsPointCloud3DRenderContext::updateExtent()
80{
81 if ( extent().isEmpty() )
82 {
83 // an empty extent means no filter, so let's pass it without transformation
84 mLayerExtent = QgsRectangle();
85 }
86 else
87 {
88 try
89 {
90 mLayerExtent = mCoordinateTransform.transformBoundingBox( extent(), Qgis::TransformDirection::Reverse );
91 }
92 catch ( const QgsCsException & )
93 {
94 // bad luck, can't reproject for some reason. Let's use an empty extent to skip filtering.
95 QgsDebugError( QStringLiteral( "Transformation of extent failed!" ) );
96 mLayerExtent = QgsRectangle();
97 }
98 }
99}
100// ---------
101
102
107
109{
111 r->readXml( elem, context );
112 return r;
113}
114
115
116// ---------
117
118
122
127
129{
130 return qobject_cast<QgsPointCloudLayer *>( mLayerRef.layer );
131}
132
134{
135 return QStringLiteral( "pointcloud" );
136}
137
139{
141 if ( mSymbol )
142 {
143 QgsAbstract3DSymbol *symbolClone = mSymbol->clone();
144 r->setSymbol( dynamic_cast<QgsPointCloud3DSymbol *>( symbolClone ) );
145 }
146 r->setMaximumScreenError( mMaximumScreenError );
147 r->setShowBoundingBoxes( mShowBoundingBoxes );
148 r->setZoomOutBehavior( mZoomOutBehavior );
149 return r;
150}
151
153{
154 QgsPointCloudLayer *pcl = layer();
155 if ( !pcl || !pcl->dataProvider() )
156 return nullptr;
157 if ( !mSymbol )
158 return nullptr;
159
160 const QgsCoordinateTransform coordinateTransform( pcl->crs3D(), map->crs(), map->transformContext() );
161
162 Qt3DCore::QEntity *entity = nullptr;
163 if ( pcl->index() )
164 {
165 entity = new QgsPointCloudLayerChunkedEntity( map, pcl, pcl->index(), coordinateTransform, dynamic_cast<QgsPointCloud3DSymbol *>( mSymbol->clone() ), static_cast<float>( maximumScreenError() ), showBoundingBoxes(), static_cast<const QgsPointCloudLayerElevationProperties *>( pcl->elevationProperties() )->zScale(), static_cast<const QgsPointCloudLayerElevationProperties *>( pcl->elevationProperties() )->zOffset(), mPointBudget );
166 }
167 else if ( !pcl->dataProvider()->subIndexes().isEmpty() )
168 {
169 entity = new QgsVirtualPointCloudEntity( map, pcl, coordinateTransform, dynamic_cast<QgsPointCloud3DSymbol *>( mSymbol->clone() ), static_cast<float>( maximumScreenError() ), showBoundingBoxes(), static_cast<const QgsPointCloudLayerElevationProperties *>( pcl->elevationProperties() )->zScale(), static_cast<const QgsPointCloudLayerElevationProperties *>( pcl->elevationProperties() )->zOffset(), mPointBudget );
170 }
171 return entity;
172}
173
175{
176 mSymbol.reset( symbol );
177}
178
179void QgsPointCloudLayer3DRenderer::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
180{
181 Q_UNUSED( context )
182
183 QDomDocument doc = elem.ownerDocument();
184
185 elem.setAttribute( QStringLiteral( "layer" ), mLayerRef.layerId );
186 elem.setAttribute( QStringLiteral( "max-screen-error" ), maximumScreenError() );
187 elem.setAttribute( QStringLiteral( "show-bounding-boxes" ), showBoundingBoxes() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
188 elem.setAttribute( QStringLiteral( "point-budget" ), mPointBudget );
189 elem.setAttribute( QStringLiteral( "zoom-out-behavior" ), qgsEnumValueToKey( mZoomOutBehavior ) );
190
191 QDomElement elemSymbol = doc.createElement( QStringLiteral( "symbol" ) );
192 if ( mSymbol )
193 {
194 elemSymbol.setAttribute( QStringLiteral( "type" ), mSymbol->symbolType() );
195 mSymbol->writeXml( elemSymbol, context );
196 }
197 elem.appendChild( elemSymbol );
198}
199
200void QgsPointCloudLayer3DRenderer::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
201{
202 mLayerRef = QgsMapLayerRef( elem.attribute( QStringLiteral( "layer" ) ) );
203
204 const QDomElement elemSymbol = elem.firstChildElement( QStringLiteral( "symbol" ) );
205
206 const QString symbolType = elemSymbol.attribute( QStringLiteral( "type" ) );
207 mShowBoundingBoxes = elem.attribute( QStringLiteral( "show-bounding-boxes" ), QStringLiteral( "0" ) ).toInt();
208 mMaximumScreenError = elem.attribute( QStringLiteral( "max-screen-error" ), QStringLiteral( "3.0" ) ).toDouble();
209 mPointBudget = elem.attribute( QStringLiteral( "point-budget" ), QStringLiteral( "5000000" ) ).toInt();
210 mZoomOutBehavior = qgsEnumKeyToValue( elem.attribute( QStringLiteral( "zoom-out-behavior" ) ), Qgis::PointCloudZoomOutRenderBehavior::RenderExtents );
211
212 if ( symbolType == QLatin1String( "single-color" ) )
213 mSymbol.reset( new QgsSingleColorPointCloud3DSymbol );
214 else if ( symbolType == QLatin1String( "color-ramp" ) )
215 mSymbol.reset( new QgsColorRampPointCloud3DSymbol );
216 else if ( symbolType == QLatin1String( "rgb" ) )
217 mSymbol.reset( new QgsRgbPointCloud3DSymbol );
218 else if ( symbolType == QLatin1String( "classification" ) )
219 mSymbol.reset( new QgsClassificationPointCloud3DSymbol );
220 else
221 mSymbol.reset();
222
223 if ( mSymbol )
224 mSymbol->readXml( elemSymbol, context );
225}
226
228{
229 mLayerRef.setLayer( project.mapLayer( mLayerRef.layerId ) );
230}
231
233{
234 return mMaximumScreenError;
235}
236
238{
239 mMaximumScreenError = error;
240}
241
243{
244 return mShowBoundingBoxes;
245}
246
248{
249 mShowBoundingBoxes = showBoundingBoxes;
250}
251
253{
254 mPointBudget = budget;
255}
256
258{
259 std::unique_ptr<QgsPointCloudLayer3DRenderer> renderer3D = Qgs3DUtils::convert2DPointCloudRendererTo3D( renderer );
260 if ( !renderer3D )
261 {
262 setSymbol( nullptr );
263 return false;
264 }
265
266 QgsPointCloud3DSymbol *newSymbol = const_cast<QgsPointCloud3DSymbol *>(
267 static_cast<QgsPointCloud3DSymbol *>( renderer3D->symbol()->clone() )
268 );
269 // we need to retain some settings from the previous symbol, like point size
270 const QgsPointCloud3DSymbol *oldSymbol = symbol();
271 if ( oldSymbol )
272 oldSymbol->copyBaseSettings( newSymbol );
273 setSymbol( newSymbol );
274 return true;
275}
@ RenderExtents
Render only point cloud extents when zoomed out.
@ Reverse
Reverse/inverse transform (from destination to source)
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used in the 3D scene.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
QgsRectangle extent() const
Returns the 3D scene's 2D extent in the 3D scene's CRS.
Base metadata class for 3D renderers.
static std::unique_ptr< QgsPointCloudLayer3DRenderer > convert2DPointCloudRendererTo3D(QgsPointCloudRenderer *renderer)
Creates a QgsPointCloudLayer3DRenderer matching the symbol settings of a given QgsPointCloudRenderer.
Base class for all renderers that may to participate in 3D view.
Class for doing transforms between two map coordinate systems.
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const
Transforms a rectangle from the source CRS to the destination CRS.
Custom exception class for Coordinate Reference System related exceptions.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition qgsfeedback.h:44
double zScale() const
Returns the z scale, which is a scaling factor which should be applied to z values from the layer.
double zOffset() const
Returns the z offset, which is a fixed offset amount which should be added to z values from the layer...
QgsCoordinateReferenceSystem crs3D
Definition qgsmaplayer.h:85
QSet< int > getFilteredOutValues() const
Returns a set containing the filtered out values.
QgsPointCloud3DSymbol * symbol() const
Returns the symbol used for rendering the point cloud.
void setFilteredOutCategories(const QgsPointCloudCategoryList &categories)
Sets the list of categories of the classification that won't be rendered.
QgsPointCloudAttributeCollection attributes() const
Returns the attributes associated with the rendered block.
void setSymbol(QgsPointCloud3DSymbol *symbol)
Sets the symbol used for rendering the point cloud Takes ownership over the passed symbol.
bool isCanceled() const
Returns true if the rendering is canceled.
void setCoordinateTransform(const QgsCoordinateTransform &coordinateTransform)
Sets the coordinate transform used to transform points from layer CRS to the map CRS.
QgsCoordinateTransform coordinateTransform() const
Returns the coordinate transform used to transform points from layer CRS to the map CRS.
void cancelRendering() const
Cancels rendering.
QgsPointCloud3DRenderContext(const Qgs3DRenderContext &context, const QgsCoordinateTransform &coordinateTransform, std::unique_ptr< QgsPointCloud3DSymbol > symbol, double zValueScale, double zValueFixedOffset)
Constructor for QgsPointCloud3DRenderContext.
void setAttributes(const QgsPointCloudAttributeCollection &attributes)
Sets the attributes associated with the rendered block.
void copyBaseSettings(QgsAbstract3DSymbol *destination) const override
Collection of point cloud attributes.
Represents an individual category (class) from a QgsPointCloudClassifiedRenderer.
virtual QVector< QgsPointCloudSubIndex > subIndexes()
Returns a list of sub indexes available if the provider supports multiple indexes,...
QgsAbstract3DRenderer * createRenderer(QDomElement &elem, const QgsReadWriteContext &context) override
Creates an instance of a 3D renderer based on a DOM element with renderer configuration.
3D renderer that renders all points from a point cloud layer
void resolveReferences(const QgsProject &project) override
Resolves references to other objects - second phase of loading - after readXml()
void setLayer(QgsPointCloudLayer *layer)
Sets point cloud layer associated with the renderer.
double maximumScreenError() const
Returns the maximum screen error allowed when rendering the point cloud.
void setPointRenderingBudget(int budget)
Sets the maximum number of points to be rendered in the scene.
void writeXml(QDomElement &elem, const QgsReadWriteContext &context) const override
Writes renderer's properties to given XML element.
const QgsPointCloud3DSymbol * symbol() const
Returns 3D symbol associated with the renderer.
QString type() const override
Returns unique identifier of the renderer class (used to identify subclass)
bool showBoundingBoxes() const
Returns whether bounding boxes will be visible when rendering the point cloud.
QgsPointCloudLayer3DRenderer()
Takes ownership of the symbol object.
QgsPointCloudLayer3DRenderer * clone() const override
Returns a cloned instance.
QgsPointCloudLayer * layer() const
Returns point cloud layer associated with the renderer.
void setSymbol(QgsPointCloud3DSymbol *symbol)
Sets the 3D symbol associated with the renderer.
void setMaximumScreenError(double error)
Sets the maximum screen error allowed when rendering the point cloud.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context) override
Reads renderer's properties from given XML element.
bool convertFrom2DRenderer(QgsPointCloudRenderer *renderer) override
Updates the 3D renderer's symbol to match that of a given QgsPointCloudRenderer.
void setShowBoundingBoxes(bool showBoundingBoxes)
Sets whether bounding boxes will be visible when rendering the point cloud.
Qt3DCore::QEntity * createEntity(Qgs3DMapSettings *map) const override
Returns a 3D entity that will be used to show renderer's data in 3D scene.
void setZoomOutBehavior(const Qgis::PointCloudZoomOutRenderBehavior behavior)
Sets the renderer behavior when zoomed out.
Point cloud layer specific subclass of QgsMapLayerElevationProperties.
Represents a map layer supporting display of point clouds.
QgsMapLayerElevationProperties * elevationProperties() override
Returns the layer's elevation properties.
QgsPointCloudIndex index() const
Returns the point cloud index associated with the layer.
QgsPointCloudDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
Abstract base class for 2d point cloud renderers.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:107
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
The class is used as a container of context for various read/write operations on other objects.
A rectangle specified with double values.
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
Definition qgis.h:6335
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition qgis.h:6316
#define QgsDebugError(str)
Definition qgslogger.h:40
_LayerRef< QgsMapLayer > QgsMapLayerRef
QList< QgsPointCloudCategory > QgsPointCloudCategoryList
QPointer< TYPE > layer
Weak pointer to map layer.
void setLayer(TYPE *l)
Sets the reference to point to a specified layer.
QString layerId
Original layer ID.