QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
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 <memory>
19
20#include "qgs3dsymbolregistry.h"
21#include "qgs3dutils.h"
23#include "qgspointcloudindex.h"
24#include "qgspointcloudlayer.h"
28#include "qgsxmlutils.h"
29
30#include <QString>
31
32using namespace Qt::StringLiterals;
33
35 const Qgs3DRenderContext &context, const QgsCoordinateTransform &coordinateTransform, std::unique_ptr<QgsPointCloud3DSymbol> symbol, double zValueScale, double zValueFixedOffset
36)
37 : Qgs3DRenderContext( context )
38 , mSymbol( std::move( symbol ) )
39 , mZValueScale( zValueScale )
40 , mZValueFixedOffset( zValueFixedOffset )
41 , mCoordinateTransform( coordinateTransform )
42 , mFeedback( new QgsFeedback )
43{
44 updateExtent();
45}
46
51
56
58{
59 mFilteredOutCategories = categories;
60}
61
63{
64 QSet<int> filteredOut;
65 for ( const QgsPointCloudCategory &category : mFilteredOutCategories )
66 filteredOut.insert( category.value() );
67 return filteredOut;
68}
69
75
77{
78 return mFeedback->isCanceled();
79}
80
82{
83 mFeedback->cancel();
84}
85
86void QgsPointCloud3DRenderContext::updateExtent()
87{
88 if ( extent().isEmpty() )
89 {
90 // an empty extent means no filter, so let's pass it without transformation
91 mLayerExtent = QgsRectangle();
92 }
93 else
94 {
95 try
96 {
97 mLayerExtent = mCoordinateTransform.transformBoundingBox( extent(), Qgis::TransformDirection::Reverse );
98 }
99 catch ( const QgsCsException & )
100 {
101 // bad luck, can't reproject for some reason. Let's use an empty extent to skip filtering.
102 QgsDebugError( u"Transformation of extent failed!"_s );
103 mLayerExtent = QgsRectangle();
104 }
105 }
106}
107// ---------
108
109
113
115{
117 r->readXml( elem, context );
118 return r;
119}
120
121
122// ---------
123
124
127
132
134{
135 return qobject_cast<QgsPointCloudLayer *>( mLayerRef.layer );
136}
137
139{
140 return u"pointcloud"_s;
141}
142
144{
146 if ( mSymbol )
147 {
148 QgsAbstract3DSymbol *symbolClone = mSymbol->clone();
149 r->setSymbol( dynamic_cast<QgsPointCloud3DSymbol *>( symbolClone ) );
150 }
151 r->setMaximumScreenError( mMaximumScreenError );
152 r->setShowBoundingBoxes( mShowBoundingBoxes );
153 r->setZoomOutBehavior( mZoomOutBehavior );
154 r->setOverviewSwitchingScale( mOverviewSwitchingScale );
155 return r;
156}
157
159{
160 QgsPointCloudLayer *pcl = layer();
161 if ( !pcl || !pcl->dataProvider() )
162 return nullptr;
163 if ( !mSymbol )
164 return nullptr;
165
166 const QgsCoordinateTransform coordinateTransform( pcl->crs3D(), map->crs(), map->transformContext() );
167
168 Qt3DCore::QEntity *entity = nullptr;
169 if ( pcl->index() )
170 {
171 entity = new QgsPointCloudLayerChunkedEntity(
172 map,
173 pcl,
174 -1,
175 coordinateTransform,
176 mSymbol->clone(),
177 static_cast<float>( maximumScreenError() ),
179 static_cast<const QgsPointCloudLayerElevationProperties *>( pcl->elevationProperties() )->zScale(),
180 static_cast<const QgsPointCloudLayerElevationProperties *>( pcl->elevationProperties() )->zOffset(),
181 mPointBudget
182 );
183 }
184 else if ( !pcl->dataProvider()->subIndexes().isEmpty() )
185 {
186 entity = new QgsVirtualPointCloudEntity(
187 map,
188 pcl,
189 coordinateTransform,
190 mSymbol->clone(),
191 static_cast<float>( maximumScreenError() ),
193 static_cast<const QgsPointCloudLayerElevationProperties *>( pcl->elevationProperties() )->zScale(),
194 static_cast<const QgsPointCloudLayerElevationProperties *>( pcl->elevationProperties() )->zOffset(),
195 mPointBudget
196 );
197 }
198 return entity;
199}
200
205
206void QgsPointCloudLayer3DRenderer::writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const
207{
208 Q_UNUSED( context )
209
210 QDomDocument doc = elem.ownerDocument();
211
212 elem.setAttribute( u"layer"_s, mLayerRef.layerId );
213 elem.setAttribute( u"max-screen-error"_s, maximumScreenError() );
214 elem.setAttribute( u"show-bounding-boxes"_s, showBoundingBoxes() ? u"1"_s : u"0"_s );
215 elem.setAttribute( u"point-budget"_s, mPointBudget );
216 elem.setAttribute( u"zoom-out-behavior"_s, qgsEnumValueToKey( mZoomOutBehavior ) );
217 elem.setAttribute( u"overview-switching-scale"_s, mOverviewSwitchingScale );
218
219 QDomElement elemSymbol = doc.createElement( u"symbol"_s );
220 if ( mSymbol )
221 {
222 elemSymbol.setAttribute( u"type"_s, mSymbol->symbolType() );
223 mSymbol->writeXml( elemSymbol, context );
224 }
225 elem.appendChild( elemSymbol );
226}
227
228void QgsPointCloudLayer3DRenderer::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
229{
230 mLayerRef = QgsMapLayerRef( elem.attribute( u"layer"_s ) );
231
232 const QDomElement elemSymbol = elem.firstChildElement( u"symbol"_s );
233
234 const QString symbolType = elemSymbol.attribute( u"type"_s );
235 mShowBoundingBoxes = elem.attribute( u"show-bounding-boxes"_s, u"0"_s ).toInt();
236 mMaximumScreenError = elem.attribute( u"max-screen-error"_s, u"3.0"_s ).toDouble();
237 mPointBudget = elem.attribute( u"point-budget"_s, u"5000000"_s ).toInt();
238 mZoomOutBehavior = qgsEnumKeyToValue( elem.attribute( u"zoom-out-behavior"_s ), Qgis::PointCloudZoomOutRenderBehavior::RenderExtents );
239 mOverviewSwitchingScale = elem.attribute( u"overview-switching-scale"_s, u"1.0"_s ).toDouble();
240
241 if ( symbolType == "single-color"_L1 )
242 mSymbol = std::make_unique<QgsSingleColorPointCloud3DSymbol>();
243 else if ( symbolType == "color-ramp"_L1 )
244 mSymbol = std::make_unique<QgsColorRampPointCloud3DSymbol>();
245 else if ( symbolType == "rgb"_L1 )
246 mSymbol = std::make_unique<QgsRgbPointCloud3DSymbol>();
247 else if ( symbolType == "classification"_L1 )
248 mSymbol = std::make_unique<QgsClassificationPointCloud3DSymbol>();
249 else
250 mSymbol.reset();
251
252 if ( mSymbol )
253 mSymbol->readXml( elemSymbol, context );
254}
255
257{
258 mLayerRef.setLayer( project.mapLayer( mLayerRef.layerId ) );
259}
260
262{
263 return mMaximumScreenError;
264}
265
267{
268 mMaximumScreenError = error;
269}
270
272{
273 return mShowBoundingBoxes;
274}
275
280
282{
283 mPointBudget = budget;
284}
285
287{
288 std::unique_ptr<QgsPointCloudLayer3DRenderer> renderer3D = Qgs3DUtils::convert2DPointCloudRendererTo3D( renderer );
289 if ( !renderer3D )
290 {
291 setSymbol( nullptr );
292 return false;
293 }
294
295 QgsPointCloud3DSymbol *newSymbol = const_cast<QgsPointCloud3DSymbol *>( static_cast<QgsPointCloud3DSymbol *>( renderer3D->symbol()->clone() ) );
296 // we need to retain some settings from the previous symbol, like point size
297 const QgsPointCloud3DSymbol *oldSymbol = symbol();
298 if ( oldSymbol )
299 oldSymbol->copyBaseSettings( newSymbol );
300 setSymbol( newSymbol );
301 return true;
302}
@ RenderExtents
Render only point cloud extents when zoomed out.
Definition qgis.h:6444
@ Reverse
Reverse/inverse transform (from destination to source).
Definition qgis.h:2766
Definition of the world.
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...
Qgs3DRenderContext()=default
QgsRectangle extent() const
Returns the 3D scene's 2D extent in the 3D scene's CRS.
Qgs3DRendererAbstractMetadata(const QString &type)
Constructor of the base class.
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 participate in 3D views.
Abstract base class for 3D symbols that are used by VectorLayer3DRenderer objects.
virtual QgsAbstract3DSymbol * clone() const =0
Returns a new instance of the symbol with the same settings.
Handles coordinate transforms between two coordinate systems.
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:92
QSet< int > getFilteredOutValues() const
Returns a set containing the filtered out values.
QgsPointCloud3DSymbol * symbol() const
Returns the symbol used for rendering the point cloud.
double zValueScale() const
Returns any constant scaling factor which must be applied to z values taken from the point cloud inde...
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.
double zValueFixedOffset() const
Returns any constant offset which must be applied to z values taken from the point cloud index.
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.
3D symbol that draws point cloud geometries as 3D objects.
void copyBaseSettings(QgsAbstract3DSymbol *destination) const override
A 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.
void setOverviewSwitchingScale(double scale)
Sets the overview switching scale.
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:113
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
A container for the context for various read/write operations on 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:7176
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition qgis.h:7157
#define QgsDebugError(str)
Definition qgslogger.h:59
_LayerRef< QgsMapLayer > QgsMapLayerRef
QList< QgsPointCloudCategory > QgsPointCloudCategoryList