QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgspointcloudclassifiedrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspointcloudclassifiedrenderer.h
3  --------------------
4  begin : October 2020
5  copyright : (C) 2020 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
19 #include "qgspointcloudblock.h"
20 #include "qgsstyle.h"
21 #include "qgscolorramp.h"
22 #include "qgssymbollayerutils.h"
25 
26 QgsPointCloudCategory::QgsPointCloudCategory( const int value, const QColor &color, const QString &label, bool render )
27  : mValue( value )
28  , mColor( color )
29  , mLabel( label )
30  , mRender( render )
31 {
32 }
33 
35 {
36  return mValue == other.value() &&
37  mColor == other.color() &&
38  mLabel == other.label() &&
39  mRender == other.renderState();
40 }
41 
42 //
43 // QgsPointCloudClassifiedRenderer
44 //
45 
47  : mAttribute( attributeName )
48  , mCategories( categories )
49 {
50 }
51 
53 {
54  return QStringLiteral( "classified" );
55 }
56 
58 {
59  std::unique_ptr< QgsPointCloudClassifiedRenderer > res = std::make_unique< QgsPointCloudClassifiedRenderer >();
60  res->mAttribute = mAttribute;
61  res->mCategories = mCategories;
62 
63  copyCommonProperties( res.get() );
64 
65  return res.release();
66 }
67 
69 {
70  const QgsRectangle visibleExtent = context.renderContext().extent();
71 
72  const char *ptr = block->data();
73  int count = block->pointCount();
74  const QgsPointCloudAttributeCollection request = block->attributes();
75 
76  const std::size_t recordSize = request.pointRecordSize();
77  int attributeOffset = 0;
78  const QgsPointCloudAttribute *attribute = request.find( mAttribute, attributeOffset );
79  if ( !attribute )
80  return;
81  const QgsPointCloudAttribute::DataType attributeType = attribute->type();
82 
83  const QgsDoubleRange zRange = context.renderContext().zRange();
84  const bool considerZ = !zRange.isInfinite();
85 
86  int rendered = 0;
87  double x = 0;
88  double y = 0;
89  double z = 0;
91  const bool reproject = ct.isValid();
92 
93  QHash< int, QColor > colors;
94  for ( const QgsPointCloudCategory &category : std::as_const( mCategories ) )
95  {
96  if ( !category.renderState() )
97  continue;
98 
99  colors.insert( category.value(), category.color() );
100  }
101 
102  for ( int i = 0; i < count; ++i )
103  {
104  if ( context.renderContext().renderingStopped() )
105  {
106  break;
107  }
108 
109  if ( considerZ )
110  {
111  // z value filtering is cheapest, if we're doing it...
112  z = pointZ( context, ptr, i );
113  if ( !zRange.contains( z ) )
114  continue;
115  }
116 
117  int attributeValue = 0;
118  context.getAttribute( ptr, i * recordSize + attributeOffset, attributeType, attributeValue );
119  const QColor color = colors.value( attributeValue );
120  if ( !color.isValid() )
121  continue;
122 
123  pointXY( context, ptr, i, x, y );
124  if ( visibleExtent.contains( x, y ) )
125  {
126  if ( reproject )
127  {
128  try
129  {
130  ct.transformInPlace( x, y, z );
131  }
132  catch ( QgsCsException & )
133  {
134  continue;
135  }
136  }
137 
138  drawPoint( x, y, color, context );
139  rendered++;
140  }
141  }
142  context.incrementPointsRendered( rendered );
143 }
144 
145 bool QgsPointCloudClassifiedRenderer::willRenderPoint( const QVariantMap &pointAttributes )
146 {
147  if ( !pointAttributes.contains( mAttribute ) )
148  return false;
149  bool parsedCorrectly;
150  int attributeInt = pointAttributes[ mAttribute ].toInt( &parsedCorrectly );
151  if ( !parsedCorrectly )
152  return false;
153  for ( const QgsPointCloudCategory &category : std::as_const( mCategories ) )
154  {
155  if ( category.value() == attributeInt )
156  return category.renderState();
157  }
158  return false;
159 }
160 
162 {
163  std::unique_ptr< QgsPointCloudClassifiedRenderer > r = std::make_unique< QgsPointCloudClassifiedRenderer >();
164 
165  r->setAttribute( element.attribute( QStringLiteral( "attribute" ), QStringLiteral( "Classification" ) ) );
166 
168  const QDomElement catsElem = element.firstChildElement( QStringLiteral( "categories" ) );
169  if ( !catsElem.isNull() )
170  {
171  QDomElement catElem = catsElem.firstChildElement();
172  while ( !catElem.isNull() )
173  {
174  if ( catElem.tagName() == QLatin1String( "category" ) )
175  {
176  const int value = catElem.attribute( QStringLiteral( "value" ) ).toInt();
177  const QString label = catElem.attribute( QStringLiteral( "label" ) );
178  const bool render = catElem.attribute( QStringLiteral( "render" ) ) != QLatin1String( "false" );
179  const QColor color = QgsSymbolLayerUtils::decodeColor( catElem.attribute( QStringLiteral( "color" ) ) );
180  categories.append( QgsPointCloudCategory( value, color, label, render ) );
181  }
182  catElem = catElem.nextSiblingElement();
183  }
184  r->setCategories( categories );
185  }
186 
187  r->restoreCommonProperties( element, context );
188 
189  return r.release();
190 }
191 
193 {
212  << QgsPointCloudCategory( 18, QColor( "#646464" ), QgsPointCloudDataProvider::translatedLasClassificationCodes().value( 18 ) );
213 }
214 
215 QDomElement QgsPointCloudClassifiedRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context ) const
216 {
217  QDomElement rendererElem = doc.createElement( QStringLiteral( "renderer" ) );
218 
219  rendererElem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "classified" ) );
220  rendererElem.setAttribute( QStringLiteral( "attribute" ), mAttribute );
221 
222  // categories
223  QDomElement catsElem = doc.createElement( QStringLiteral( "categories" ) );
224  for ( const QgsPointCloudCategory &category : mCategories )
225  {
226  QDomElement catElem = doc.createElement( QStringLiteral( "category" ) );
227  catElem.setAttribute( QStringLiteral( "value" ), QString::number( category.value() ) );
228  catElem.setAttribute( QStringLiteral( "label" ), category.label() );
229  catElem.setAttribute( QStringLiteral( "color" ), QgsSymbolLayerUtils::encodeColor( category.color() ) );
230  catElem.setAttribute( QStringLiteral( "render" ), category.renderState() ? "true" : "false" );
231  catsElem.appendChild( catElem );
232  }
233  rendererElem.appendChild( catsElem );
234 
235  saveCommonProperties( rendererElem, context );
236 
237  return rendererElem;
238 }
239 
241 {
242  QSet<QString> res;
243  res << mAttribute;
244  return res;
245 }
246 
247 QList<QgsLayerTreeModelLegendNode *> QgsPointCloudClassifiedRenderer::createLegendNodes( QgsLayerTreeLayer *nodeLayer )
248 {
249  QList<QgsLayerTreeModelLegendNode *> nodes;
250 
251  for ( const QgsPointCloudCategory &category : std::as_const( mCategories ) )
252  {
253  nodes << new QgsRasterSymbolLegendNode( nodeLayer, category.color(), category.label(), nullptr, true, QString::number( category.value() ) );
254  }
255 
256  return nodes;
257 }
258 
260 {
261  QStringList res;
262  for ( const QgsPointCloudCategory &category : std::as_const( mCategories ) )
263  {
264  res << QString::number( category.value() );
265  }
266  return res;
267 }
268 
270 {
271  bool ok = false;
272  const int value = key.toInt( &ok );
273  if ( !ok )
274  return false;
275 
276  for ( const QgsPointCloudCategory &category : std::as_const( mCategories ) )
277  {
278  if ( category.value() == value )
279  return category.renderState();
280  }
281  return false;
282 }
283 
284 void QgsPointCloudClassifiedRenderer::checkLegendItem( const QString &key, bool state )
285 {
286  bool ok = false;
287  const int value = key.toInt( &ok );
288  if ( !ok )
289  return;
290 
291  for ( auto it = mCategories.begin(); it != mCategories.end(); ++it )
292  {
293  if ( it->value() == value )
294  {
295  it->setRenderState( state );
296  return;
297  }
298  }
299 }
300 
302 {
303  return mAttribute;
304 }
305 
306 void QgsPointCloudClassifiedRenderer::setAttribute( const QString &attribute )
307 {
308  mAttribute = attribute;
309 }
310 
312 {
313  return mCategories;
314 }
315 
317 {
318  mCategories = categories;
319 }
320 
322 {
323  mCategories.append( category );
324 }
325 
326 std::unique_ptr<QgsPreparedPointCloudRendererData> QgsPointCloudClassifiedRenderer::prepare()
327 {
328  std::unique_ptr< QgsPointCloudClassifiedRendererPreparedData > data = std::make_unique< QgsPointCloudClassifiedRendererPreparedData >();
329  data->attributeName = mAttribute;
330 
331  for ( const QgsPointCloudCategory &category : std::as_const( mCategories ) )
332  {
333  if ( !category.renderState() )
334  continue;
335 
336  data->colors.insert( category.value(), category.color() );
337  }
338 
339  return data;
340 }
341 
343 {
344  return { attributeName };
345 }
346 
348 {
349  const QgsPointCloudAttributeCollection attributes = block->attributes();
350  const QgsPointCloudAttribute *attribute = attributes.find( attributeName, attributeOffset );
351  if ( !attribute )
352  return false;
353 
354  attributeType = attribute->type();
355  return true;
356 }
357 
359 {
360  int attributeValue = 0;
362  return colors.value( attributeValue );
363 }
364 
365 
QgsPointCloudClassifiedRenderer::type
QString type() const override
Returns the identifier of the renderer type.
Definition: qgspointcloudclassifiedrenderer.cpp:52
QgsPointCloudClassifiedRenderer::legendItemChecked
bool legendItemChecked(const QString &key) override
Returns true if the legend item with the specified key is checked.
Definition: qgspointcloudclassifiedrenderer.cpp:269
QgsPointCloudClassifiedRenderer::defaultCategories
static QgsPointCloudCategoryList defaultCategories()
Returns the default list of categories.
Definition: qgspointcloudclassifiedrenderer.cpp:192
QgsCoordinateTransform::transformInPlace
void transformInPlace(double &x, double &y, double &z, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward) const SIP_THROW(QgsCsException)
Transforms an array of x, y and z double coordinates in place, from the source CRS to the destination...
Definition: qgscoordinatetransform.cpp:364
QgsSymbolLayerUtils::encodeColor
static QString encodeColor(const QColor &color)
Definition: qgssymbollayerutils.cpp:64
QgsPointCloudClassifiedRenderer::prepare
std::unique_ptr< QgsPreparedPointCloudRendererData > prepare() override
Returns prepared data container for bulk point color retrieval.
Definition: qgspointcloudclassifiedrenderer.cpp:326
QgsPointCloudClassifiedRenderer::attribute
QString attribute() const
Returns the attribute to use for the renderer.
Definition: qgspointcloudclassifiedrenderer.cpp:301
qgslayertreemodellegendnode.h
QgsPointCloudAttribute::DataType
DataType
Systems of unit measurement.
Definition: qgspointcloudattribute.h:44
QgsPointCloudClassifiedRendererPreparedData::pointColor
QColor pointColor(const QgsPointCloudBlock *block, int i, double z) override
An optimised method of retrieving the color of a point from a point cloud block.
Definition: qgspointcloudclassifiedrenderer.cpp:358
QgsReadWriteContext
The class is used as a container of context for various read/write operations on other objects.
Definition: qgsreadwritecontext.h:34
QgsPointCloudAttributeCollection::find
const QgsPointCloudAttribute * find(const QString &attributeName, int &offset) const
Finds the attribute with the name.
Definition: qgspointcloudattribute.cpp:168
QgsPointCloudClassifiedRendererPreparedData::prepareBlock
bool prepareBlock(const QgsPointCloudBlock *block) override
Prepares the renderer for using the specified block.
Definition: qgspointcloudclassifiedrenderer.cpp:347
QgsPointCloudClassifiedRenderer::legendRuleKeys
QStringList legendRuleKeys() const override
Returns a list of all rule keys for legend nodes created by the renderer.
Definition: qgspointcloudclassifiedrenderer.cpp:259
QgsPointCloudBlock::data
const char * data() const
Returns raw pointer to data.
Definition: qgspointcloudblock.cpp:37
QgsPointCloudBlock::attributes
QgsPointCloudAttributeCollection attributes() const
Returns the attributes that are stored in the data block, along with their size.
Definition: qgspointcloudblock.cpp:47
qgssymbollayerutils.h
QgsPointCloudClassifiedRenderer::create
static QgsPointCloudRenderer * create(QDomElement &element, const QgsReadWriteContext &context)
Creates an RGB renderer from an XML element.
Definition: qgspointcloudclassifiedrenderer.cpp:161
QgsPointCloudCategoryList
QList< QgsPointCloudCategory > QgsPointCloudCategoryList
Definition: qgspointcloudclassifiedrenderer.h:116
QgsPointCloudClassifiedRenderer::willRenderPoint
bool willRenderPoint(const QVariantMap &pointAttributes) override
Definition: qgspointcloudclassifiedrenderer.cpp:145
QgsPointCloudClassifiedRendererPreparedData::attributeName
QString attributeName
Definition: qgspointcloudclassifiedrenderer.h:138
QgsPointCloudCategory
Represents an individual category (class) from a QgsPointCloudClassifiedRenderer.
Definition: qgspointcloudclassifiedrenderer.h:32
QgsPointCloudRenderer::copyCommonProperties
void copyCommonProperties(QgsPointCloudRenderer *destination) const
Copies common point cloud properties (such as point size and screen error) to the destination rendere...
Definition: qgspointcloudrenderer.cpp:162
QgsPointCloudClassifiedRenderer::categories
QgsPointCloudCategoryList categories() const
Returns the classification categories used for rendering.
Definition: qgspointcloudclassifiedrenderer.cpp:311
QgsPointCloudBlock
Base class for storing raw data from point cloud nodes.
Definition: qgspointcloudblock.h:38
QgsPointCloudCategory::color
QColor color() const
Returns the color which will be used to render this category.
Definition: qgspointcloudclassifiedrenderer.h:80
QgsCoordinateTransform::isValid
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
Definition: qgscoordinatetransform.cpp:900
QgsPointCloudCategory::mColor
QColor mColor
Definition: qgspointcloudclassifiedrenderer.h:124
QgsRenderContext::extent
const QgsRectangle & extent() const
When rendering a map layer, calling this method returns the "clipping" extent for the layer (in the l...
Definition: qgsrendercontext.h:239
QgsSymbolLayerUtils::decodeColor
static QColor decodeColor(const QString &str)
Definition: qgssymbollayerutils.cpp:69
QgsPointCloudClassifiedRendererPreparedData::usedAttributes
QSet< QString > usedAttributes() const override
Returns the set of attributes used by the prepared point cloud renderer.
Definition: qgspointcloudclassifiedrenderer.cpp:342
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsPointCloudClassifiedRendererPreparedData::attributeType
QgsPointCloudAttribute::DataType attributeType
Definition: qgspointcloudclassifiedrenderer.h:136
QgsPointCloudBlock::pointCount
int pointCount() const
Returns number of points that are stored in the block.
Definition: qgspointcloudblock.cpp:42
QgsPointCloudCategory::label
QString label() const
Returns the label for this category, which is used to represent the category within legends and the l...
Definition: qgspointcloudclassifiedrenderer.h:87
QgsPointCloudRenderContext::getAttribute
static void getAttribute(const char *data, std::size_t offset, QgsPointCloudAttribute::DataType type, T &value)
Retrieves the attribute value from data at the specified offset, where type indicates the original da...
Definition: qgspointcloudrenderer.h:183
QgsRenderContext::renderingStopped
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
Definition: qgsrendercontext.h:285
QgsPointCloudClassifiedRenderer::usedAttributes
QSet< QString > usedAttributes(const QgsPointCloudRenderContext &context) const override
Returns a list of attributes required by this renderer.
Definition: qgspointcloudclassifiedrenderer.cpp:240
QgsRenderContext::coordinateTransform
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
Definition: qgsrendercontext.h:178
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
QgsPointCloudRenderer::drawPoint
void drawPoint(double x, double y, const QColor &color, QgsPointCloudRenderContext &context) const
Draws a point using a color at the specified x and y (in map coordinates).
Definition: qgspointcloudrenderer.h:600
QgsPointCloudCategory::renderState
bool renderState() const
Returns true if the category is currently enabled and should be rendered.
Definition: qgspointcloudclassifiedrenderer.h:114
QgsPointCloudRenderContext
Encapsulates the render context for a 2D point cloud rendering operation.
Definition: qgspointcloudrenderer.h:41
QgsPointCloudAttributeCollection::pointRecordSize
int pointRecordSize() const
Returns total size of record.
Definition: qgspointcloudattribute.h:187
QgsPointCloudRenderContext::incrementPointsRendered
void incrementPointsRendered(long count)
Increments the count of points rendered by the specified amount.
Definition: qgspointcloudrenderer.cpp:46
qgspointcloudclassifiedrenderer.h
qgscolorramp.h
QgsLayerTreeLayer
Layer tree node points to a map layer.
Definition: qgslayertreelayer.h:43
QgsPointCloudAttributeCollection
Collection of point cloud attributes.
Definition: qgspointcloudattribute.h:141
QgsRectangle::contains
bool contains(const QgsRectangle &rect) const SIP_HOLDGIL
Returns true when rectangle contains other rectangle.
Definition: qgsrectangle.h:363
QgsPointCloudClassifiedRenderer::setCategories
void setCategories(const QgsPointCloudCategoryList &categories)
Sets the classification categories used for rendering.
Definition: qgspointcloudclassifiedrenderer.cpp:316
QgsPointCloudAttribute
Attribute for point cloud data pair of name and size in bytes.
Definition: qgspointcloudattribute.h:40
QgsPointCloudRenderer::pointXY
static void pointXY(QgsPointCloudRenderContext &context, const char *ptr, int i, double &x, double &y)
Retrieves the x and y coordinate for the point at index i.
Definition: qgspointcloudrenderer.h:576
QgsPointCloudCategory::QgsPointCloudCategory
QgsPointCloudCategory()=default
Constructor for QgsPointCloudCategory.
QgsPointCloudCategory::mRender
bool mRender
Definition: qgspointcloudclassifiedrenderer.h:126
qgsstyle.h
QgsDoubleRange::isInfinite
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition: qgsrange.h:247
QgsRenderContext::zRange
QgsDoubleRange zRange() const
Returns the range of z-values which should be rendered.
Definition: qgsrendercontext.cpp:650
QgsPointCloudClassifiedRenderer::setAttribute
void setAttribute(const QString &attribute)
Sets the attribute to use for the renderer.
Definition: qgspointcloudclassifiedrenderer.cpp:306
QgsPointCloudClassifiedRenderer::renderBlock
void renderBlock(const QgsPointCloudBlock *block, QgsPointCloudRenderContext &context) override
Renders a block of point cloud data using the specified render context.
Definition: qgspointcloudclassifiedrenderer.cpp:68
QgsPointCloudBlock::pointRecordSize
int pointRecordSize() const
Returns the total size of each individual point record.
Definition: qgspointcloudblock.h:72
QgsDoubleRange
QgsRange which stores a range of double values.
Definition: qgsrange.h:202
QgsPointCloudCategory::mValue
int mValue
Definition: qgspointcloudclassifiedrenderer.h:123
QgsPointCloudClassifiedRenderer::checkLegendItem
void checkLegendItem(const QString &key, bool state=true) override
Called when the check state of the legend item with the specified key is changed.
Definition: qgspointcloudclassifiedrenderer.cpp:284
qgspointclouddataprovider.h
QgsPointCloudRenderer
Abstract base class for 2d point cloud renderers.
Definition: qgspointcloudrenderer.h:296
qgspointcloudblock.h
QgsPointCloudCategory::value
int value() const
Returns the value corresponding to this category.
Definition: qgspointcloudclassifiedrenderer.h:74
QgsPointCloudClassifiedRendererPreparedData::colors
QHash< int, QColor > colors
Definition: qgspointcloudclassifiedrenderer.h:137
QgsRange::contains
bool contains(const QgsRange< T > &other) const
Returns true if this range contains another range.
Definition: qgsrange.h:108
QgsPointCloudClassifiedRenderer::addCategory
void addCategory(const QgsPointCloudCategory &category)
Adds a category to the renderer.
Definition: qgspointcloudclassifiedrenderer.cpp:321
QgsPointCloudClassifiedRenderer::QgsPointCloudClassifiedRenderer
QgsPointCloudClassifiedRenderer(const QString &attributeName=QString(), const QgsPointCloudCategoryList &categories=QgsPointCloudCategoryList())
Constructor for QgsPointCloudClassifiedRenderer.
Definition: qgspointcloudclassifiedrenderer.cpp:46
QgsPointCloudClassifiedRendererPreparedData::attributeOffset
int attributeOffset
Definition: qgspointcloudclassifiedrenderer.h:139
QgsPointCloudClassifiedRenderer::clone
QgsPointCloudRenderer * clone() const override
Create a deep copy of this renderer.
Definition: qgspointcloudclassifiedrenderer.cpp:57
QgsPointCloudCategory::operator==
bool operator==(const QgsPointCloudCategory &other) const
Equality operator.
Definition: qgspointcloudclassifiedrenderer.cpp:34
QgsRasterSymbolLegendNode
Implementation of legend node interface for displaying raster legend entries.
Definition: qgslayertreemodellegendnode.h:606
QgsPointCloudRenderer::saveCommonProperties
void saveCommonProperties(QDomElement &element, const QgsReadWriteContext &context) const
Saves common renderer properties (such as point size and screen error) to the specified DOM element.
Definition: qgspointcloudrenderer.cpp:185
QgsPointCloudClassifiedRenderer::createLegendNodes
QList< QgsLayerTreeModelLegendNode * > createLegendNodes(QgsLayerTreeLayer *nodeLayer) override
Creates a set of legend nodes representing the renderer.
Definition: qgspointcloudclassifiedrenderer.cpp:247
QgsPointCloudRenderContext::renderContext
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
Definition: qgspointcloudrenderer.h:69
QgsPointCloudRenderer::pointZ
static double pointZ(QgsPointCloudRenderContext &context, const char *ptr, int i)
Retrieves the z value for the point at index i.
Definition: qgspointcloudrenderer.h:589
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:57
QgsPointCloudDataProvider::translatedLasClassificationCodes
static QMap< int, QString > translatedLasClassificationCodes()
Returns the map of LAS classification code to translated string value, corresponding to the ASPRS Sta...
Definition: qgspointclouddataprovider.cpp:105
QgsPointCloudCategory::mLabel
QString mLabel
Definition: qgspointcloudclassifiedrenderer.h:125
QgsPointCloudClassifiedRenderer::save
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) const override
Saves the renderer configuration to an XML element.
Definition: qgspointcloudclassifiedrenderer.cpp:215
QgsPointCloudAttribute::type
DataType type() const
Returns the data type.
Definition: qgspointcloudattribute.h:74