QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
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  ***************************************************************************/
16 #include "qgspointcloudrenderer.h"
17 
18 // default renderers
22 #include "qgspointcloudlayer.h"
24 
26 {
27  // add default renderers
28  addRenderer( new QgsPointCloudRendererMetadata( QStringLiteral( "extent" ),
29  QObject::tr( "Extent Only" ),
31  addRenderer( new QgsPointCloudRendererMetadata( QStringLiteral( "ramp" ),
32  QObject::tr( "Attribute by Ramp" ),
34  addRenderer( new QgsPointCloudRendererMetadata( QStringLiteral( "rgb" ),
35  QObject::tr( "RGB" ),
37  addRenderer( new QgsPointCloudRendererMetadata( QStringLiteral( "classified" ),
38  QObject::tr( "Classification" ),
40 }
41 
43 {
44  qDeleteAll( mRenderers );
45 }
46 
48 {
49  if ( !metadata || mRenderers.contains( metadata->name() ) )
50  return false;
51 
52  mRenderers[metadata->name()] = metadata;
53  mRenderersOrder << metadata->name();
54  return true;
55 }
56 
57 bool QgsPointCloudRendererRegistry::removeRenderer( const QString &rendererName )
58 {
59  if ( !mRenderers.contains( rendererName ) )
60  return false;
61 
62  delete mRenderers[rendererName];
63  mRenderers.remove( rendererName );
64  mRenderersOrder.removeAll( rendererName );
65  return true;
66 }
67 
69 {
70  return mRenderers.value( rendererName );
71 }
72 
74 {
75  QStringList renderers;
76  for ( const QString &renderer : mRenderersOrder )
77  {
78  QgsPointCloudRendererAbstractMetadata *r = mRenderers.value( renderer );
79  if ( r )
80  renderers << renderer;
81  }
82  return renderers;
83 }
84 
86 {
87  if ( !provider )
89 
90  if ( ( provider->name() == QLatin1String( "pdal" ) ) && ( !provider->hasValidIndex() ) )
91  {
92  // for now, default to extent renderer only for las/laz files
93  return new QgsPointCloudExtentRenderer();
94  }
95 
96  const QgsPointCloudAttributeCollection attributes = provider->attributes();
97 
98  //if red/green/blue attributes are present, then default to a RGB renderer
99  if ( attributes.indexOf( QLatin1String( "Red" ) ) >= 0 && attributes.indexOf( QLatin1String( "Green" ) ) >= 0 && attributes.indexOf( QLatin1String( "Blue" ) ) >= 0 )
100  {
101  std::unique_ptr< QgsPointCloudRgbRenderer > renderer = std::make_unique< QgsPointCloudRgbRenderer >();
102 
103  // set initial guess for rgb ranges
104  const QVariant redMax = provider->metadataStatistic( QStringLiteral( "Red" ), QgsStatisticalSummary::Max );
105  const QVariant greenMax = provider->metadataStatistic( QStringLiteral( "Red" ), QgsStatisticalSummary::Max );
106  const QVariant blueMax = provider->metadataStatistic( QStringLiteral( "Red" ), QgsStatisticalSummary::Max );
107  if ( redMax.isValid() && greenMax.isValid() && blueMax.isValid() )
108  {
109  const int maxValue = std::max( blueMax.toInt(), std::max( redMax.toInt(), greenMax.toInt() ) );
110 
111  if ( maxValue == 0 )
112  {
113  // r/g/b max value is 0 -- likely these attributes have been created by some process, but are empty.
114  // in any case they won't result in a useful render, so don't use RGB renderer for this dataset.
115  renderer.reset();
116  }
117  else
118  {
119  // 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
120  // likely to be 8 bit or 16 bit color values
121  const int rangeGuess = maxValue > 255 ? 65535 : 255;
122 
123  if ( rangeGuess > 255 )
124  {
125  // looks like 16 bit colors, so default to a stretch contrast enhancement
127  contrast.setMinimumValue( 0 );
128  contrast.setMaximumValue( rangeGuess );
130  renderer->setRedContrastEnhancement( new QgsContrastEnhancement( contrast ) );
131  renderer->setGreenContrastEnhancement( new QgsContrastEnhancement( contrast ) );
132  renderer->setBlueContrastEnhancement( new QgsContrastEnhancement( contrast ) );
133  }
134  }
135  }
136 
137  if ( renderer )
138  return renderer.release();
139  }
140 
141  // otherwise try a classified renderer...
142  if ( attributes.indexOf( QLatin1String( "Classification" ) ) >= 0 )
143  {
144  // are any classifications present?
145  QVariantList classes = provider->metadataClasses( QStringLiteral( "Classification" ) );
146  // ignore "not classified" classes, and see if any are left...
147  classes.removeAll( 0 );
148  classes.removeAll( 1 );
149  if ( !classes.empty() )
150  {
151  std::unique_ptr< QgsPointCloudClassifiedRenderer > renderer = std::make_unique< QgsPointCloudClassifiedRenderer >();
152  renderer->setAttribute( QStringLiteral( "Classification" ) );
153  return renderer.release();
154  }
155  }
156 
157  // fallback to shading by Z
158  std::unique_ptr< QgsPointCloudAttributeByRampRenderer > renderer = std::make_unique< QgsPointCloudAttributeByRampRenderer >();
159  renderer->setAttribute( QStringLiteral( "Z" ) );
160 
161  // set initial range for z values if possible
162  const QVariant zMin = provider->metadataStatistic( QStringLiteral( "Z" ), QgsStatisticalSummary::Min );
163  const QVariant zMax = provider->metadataStatistic( QStringLiteral( "Z" ), QgsStatisticalSummary::Max );
164  if ( zMin.isValid() && zMax.isValid() )
165  {
166  renderer->setMinimum( zMin.toDouble() );
167  renderer->setMaximum( zMax.toDouble() );
168 
169  QgsColorRampShader shader = renderer->colorRampShader();
170  shader.setMinimumValue( zMin.toDouble() );
171  shader.setMaximumValue( zMax.toDouble() );
172  shader.classifyColorRamp( 5, -1, QgsRectangle(), nullptr );
173  renderer->setColorRampShader( shader );
174  }
175  return renderer.release();
176 }
177 
@ UnknownDataType
Unknown or unspecified type.
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.
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.
static QgsPointCloudRenderer * create(QDomElement &element, const QgsReadWriteContext &context)
Creates an RGB renderer from an XML element.
Base class for providing data for QgsPointCloudLayer.
virtual QgsPointCloudAttributeCollection attributes() const =0
Returns the attributes available from this data provider.
virtual QVariant metadataStatistic(const QString &attribute, QgsStatisticalSummary::Statistic statistic) const
Returns a statistic for the specified attribute, taken only from the metadata of the point cloud data...
bool hasValidIndex() const
Returns whether provider has index which is valid.
virtual QVariantList metadataClasses(const QString &attribute) const
Returns a list of existing classes which are present for the specified attribute, taken only from the...
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.
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 QgsPointCloudRenderer * defaultRenderer(const QgsPointCloudDataProvider *provider)
Returns a new default point cloud renderer for a layer with the specified provider.
QgsPointCloudRendererAbstractMetadata * rendererMetadata(const QString &rendererName)
Returns the metadata for a specified renderer.
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.
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