QGIS API Documentation 3.27.0-Master (f261cc1f8b)
qgspointcloudrendererregistry.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgspointcloudrendererregistry.cpp
3 ---------------------
4 begin : November 2020
5 copyright : (C) 2020 by Nyall Dawson
6 email : nyall dot dawson 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 ***************************************************************************/
17#include "qgsapplication.h"
19
20// default renderers
24#include "qgspointcloudlayer.h"
26
28{
29 // add default renderers
30 addRenderer( new QgsPointCloudRendererMetadata( QStringLiteral( "extent" ),
31 QObject::tr( "Extent Only" ),
33 addRenderer( new QgsPointCloudRendererMetadata( QStringLiteral( "ramp" ),
34 QObject::tr( "Attribute by Ramp" ),
36 addRenderer( new QgsPointCloudRendererMetadata( QStringLiteral( "rgb" ),
37 QObject::tr( "RGB" ),
39 addRenderer( new QgsPointCloudRendererMetadata( QStringLiteral( "classified" ),
40 QObject::tr( "Classification" ),
42}
43
45{
46 qDeleteAll( mRenderers );
47}
48
50{
51 if ( !metadata || mRenderers.contains( metadata->name() ) )
52 return false;
53
54 mRenderers[metadata->name()] = metadata;
55 mRenderersOrder << metadata->name();
56 return true;
57}
58
59bool QgsPointCloudRendererRegistry::removeRenderer( const QString &rendererName )
60{
61 if ( !mRenderers.contains( rendererName ) )
62 return false;
63
64 delete mRenderers[rendererName];
65 mRenderers.remove( rendererName );
66 mRenderersOrder.removeAll( rendererName );
67 return true;
68}
69
71{
72 return mRenderers.value( rendererName );
73}
74
76{
77 QStringList renderers;
78 for ( const QString &renderer : mRenderersOrder )
79 {
80 QgsPointCloudRendererAbstractMetadata *r = mRenderers.value( renderer );
81 if ( r )
82 renderers << renderer;
83 }
84 return renderers;
85}
86
88{
89 const QgsPointCloudDataProvider *provider = layer->dataProvider();
90 if ( !provider )
92
93 const QgsPointCloudStatistics stats = layer->statistics();
94
95 if ( ( provider->name() == QLatin1String( "pdal" ) ) && ( !provider->hasValidIndex() ) )
96 {
97 // for now, default to extent renderer only for las/laz files
98 return new QgsPointCloudExtentRenderer();
99 }
100
101 // If we are calculating statistics, we default to the extent renderer until the statistics calculation finishes
103 {
104 return new QgsPointCloudExtentRenderer();
105 }
106
107 const QgsPointCloudAttributeCollection attributes = provider->attributes();
108
109 //if red/green/blue attributes are present, then default to a RGB renderer
110 if ( attributes.indexOf( QLatin1String( "Red" ) ) >= 0 && attributes.indexOf( QLatin1String( "Green" ) ) >= 0 && attributes.indexOf( QLatin1String( "Blue" ) ) >= 0 )
111 {
112 std::unique_ptr< QgsPointCloudRgbRenderer > renderer = std::make_unique< QgsPointCloudRgbRenderer >();
113
114 // set initial guess for rgb ranges
115 const double redMax = stats.maximum( QStringLiteral( "Red" ) );
116 const double greenMax = stats.maximum( QStringLiteral( "Red" ) );
117 const double blueMax = stats.maximum( QStringLiteral( "Red" ) );
118 if ( !std::isnan( redMax ) && !std::isnan( greenMax ) && !std::isnan( blueMax ) )
119 {
120 const int maxValue = std::max( blueMax, std::max( redMax, greenMax ) );
121
122 if ( maxValue == 0 )
123 {
124 // r/g/b max value is 0 -- likely these attributes have been created by some process, but are empty.
125 // in any case they won't result in a useful render, so don't use RGB renderer for this dataset.
126 renderer.reset();
127 }
128 else
129 {
130 // try and guess suitable range from input max values -- we don't just take the provider max value directly here, but rather see if it's
131 // likely to be 8 bit or 16 bit color values
132 const int rangeGuess = maxValue > 255 ? 65535 : 255;
133
134 if ( rangeGuess > 255 )
135 {
136 // looks like 16 bit colors, so default to a stretch contrast enhancement
138 contrast.setMinimumValue( 0 );
139 contrast.setMaximumValue( rangeGuess );
141 renderer->setRedContrastEnhancement( new QgsContrastEnhancement( contrast ) );
142 renderer->setGreenContrastEnhancement( new QgsContrastEnhancement( contrast ) );
143 renderer->setBlueContrastEnhancement( new QgsContrastEnhancement( contrast ) );
144 }
145 }
146 }
147 else
148 {
150 contrast.setMinimumValue( std::numeric_limits<uint16_t>::lowest() );
151 contrast.setMaximumValue( std::numeric_limits<uint16_t>::max() );
153 renderer->setRedContrastEnhancement( new QgsContrastEnhancement( contrast ) );
154 renderer->setGreenContrastEnhancement( new QgsContrastEnhancement( contrast ) );
155 renderer->setBlueContrastEnhancement( new QgsContrastEnhancement( contrast ) );
156 }
157
158 if ( renderer )
159 return renderer.release();
160 }
161
162 // otherwise try a classified renderer...
163 if ( attributes.indexOf( QLatin1String( "Classification" ) ) >= 0 )
164 {
165 // are any classifications present?
166 QList<int> classes = stats.classesOf( QStringLiteral( "Classification" ) );
167 // ignore "not classified" classes, and see if any are left...
168 classes.removeAll( 0 );
169 classes.removeAll( 1 );
170 if ( !classes.empty() )
171 {
173 std::unique_ptr< QgsPointCloudClassifiedRenderer > renderer = std::make_unique< QgsPointCloudClassifiedRenderer >( QLatin1String( "Classification" ), categories );
174 return renderer.release();
175 }
176 }
177
178 // fallback to shading by Z
179 std::unique_ptr< QgsPointCloudAttributeByRampRenderer > renderer = std::make_unique< QgsPointCloudAttributeByRampRenderer >();
180 renderer->setAttribute( QStringLiteral( "Z" ) );
181
182 // set initial range for z values if possible
183 const double zMin = stats.minimum( QStringLiteral( "Z" ) );
184 const double zMax = stats.maximum( QStringLiteral( "Z" ) );
185 if ( !std::isnan( zMin ) && !std::isnan( zMax ) )
186 {
187 renderer->setMinimum( zMin );
188 renderer->setMaximum( zMax );
189
190 QgsColorRampShader shader = renderer->colorRampShader();
191 shader.setMinimumValue( zMin );
192 shader.setMaximumValue( zMax );
193 shader.classifyColorRamp( 5, -1, QgsRectangle(), nullptr );
194 renderer->setColorRampShader( shader );
195 }
196 return renderer.release();
197}
198
200{
201 if ( !layer )
203
204 const QgsPointCloudStatistics stats = layer->statistics();
205 const QList<int> layerClasses = stats.classesOf( QStringLiteral( "Classification" ) );
207
208 QgsPointCloudCategoryList categories;
209 for ( const int &layerClass : layerClasses )
210 {
211 const bool isDefaultCategory = layerClass >= 0 && layerClass < defaultCategories.size();
212 const QColor color = isDefaultCategory ? defaultCategories.at( layerClass ).color() : QgsApplication::colorSchemeRegistry()->fetchRandomStyleColor();
213 const QString label = isDefaultCategory ? QgsPointCloudDataProvider::translatedLasClassificationCodes().value( layerClass, QString::number( layerClass ) ) : QString::number( layerClass );
214 categories.append( QgsPointCloudCategory( layerClass, color, label ) );
215 }
216 return categories;
217}
@ UInt16
Sixteen bit unsigned integer (quint16)
@ UnknownDataType
Unknown or unspecified type.
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application's color scheme registry, used for managing color schemes.
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
void classifyColorRamp(int classes=0, int band=-1, const QgsRectangle &extent=QgsRectangle(), QgsRasterInterface *input=nullptr)
Classify color ramp shader.
QColor fetchRandomStyleColor() const
Returns a random color for use with a new symbol style (e.g.
Manipulates raster or point cloud pixel values so that they enhanceContrast or clip into a specified ...
@ StretchToMinimumMaximum
Linear histogram.
void setMinimumValue(double value, bool generateTable=true)
Sets the minimum value for the contrast enhancement range.
void setContrastEnhancementAlgorithm(ContrastEnhancementAlgorithm algorithm, bool generateTable=true)
Sets the contrast enhancement algorithm.
void setMaximumValue(double value, bool generateTable=true)
Sets the maximum value for the contrast enhancement range.
virtual QString name() const =0
Returns a provider name.
An RGB renderer for 2d visualisation of point clouds using embedded red, green and blue attributes.
static QgsPointCloudRenderer * create(QDomElement &element, const QgsReadWriteContext &context)
Creates an RGB renderer from an XML element.
Collection of point cloud attributes.
int indexOf(const QString &name) const
Returns the index of the attribute with the specified name.
Represents an individual category (class) from a QgsPointCloudClassifiedRenderer.
static QgsPointCloudRenderer * create(QDomElement &element, const QgsReadWriteContext &context)
Creates an RGB renderer from an XML element.
static QgsPointCloudCategoryList defaultCategories()
Returns the default list of categories.
Base class for providing data for QgsPointCloudLayer.
virtual QgsPointCloudAttributeCollection attributes() const =0
Returns the attributes available from this data provider.
static QMap< int, QString > translatedLasClassificationCodes()
Returns the map of LAS classification code to translated string value, corresponding to the ASPRS Sta...
bool hasValidIndex() const
Returns whether provider has index which is valid.
A renderer for 2d visualisation of point clouds which shows the dataset's extents using a fill symbol...
static QgsPointCloudRenderer * create(QDomElement &element, const QgsReadWriteContext &context)
Creates an extent renderer from an XML element.
Represents a map layer supporting display of point clouds.
@ Calculating
The statistics calculation task is running.
PointCloudStatisticsCalculationState statisticsCalculationState() const
Returns the status of point cloud statistics calculation.
QgsPointCloudDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
const QgsPointCloudStatistics statistics() const
Returns the object containing statistics.
Stores metadata about one point cloud renderer class.
QString name() const
Returns the unique name of the renderer.
Convenience metadata class that uses static functions to create point cloud renderer and its widget.
static QgsPointCloudCategoryList classificationAttributeCategories(const QgsPointCloudLayer *layer)
Returns a list of categories using the available Classification classes of a specified layer,...
QgsPointCloudRendererAbstractMetadata * rendererMetadata(const QString &rendererName)
Returns the metadata for a specified renderer.
static QgsPointCloudRenderer * defaultRenderer(const QgsPointCloudLayer *layer)
Returns a new default point cloud renderer for a specified layer.
bool addRenderer(QgsPointCloudRendererAbstractMetadata *metadata)
Adds a renderer to the registry.
bool removeRenderer(const QString &rendererName)
Removes a renderer from registry.
QStringList renderersList() const
Returns a list of available renderers.
Abstract base class for 2d point cloud renderers.
static QgsPointCloudRenderer * create(QDomElement &element, const QgsReadWriteContext &context)
Creates an RGB renderer from an XML element.
Class used to store statistics of a point cloud dataset.
double maximum(const QString &attribute) const
Returns the maximum value for the attribute attribute If no matching statistic is available then NaN ...
QList< int > classesOf(const QString &attribute) const
Returns a list of existing classes which are present for the specified attribute.
double minimum(const QString &attribute) const
Returns the minimum value for the attribute attribute If no matching statistic is available then NaN ...
virtual void setMaximumValue(double value)
Sets the maximum value for the raster shader.
virtual void setMinimumValue(double value)
Sets the minimum value for the raster shader.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QList< QgsPointCloudCategory > QgsPointCloudCategoryList