QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgspointcloud3dsymbol_p.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspointcloud3dsymbol_p.cpp
3  ------------------------------
4  Date : December 2020
5  Copyright : (C) 2020 by Nedjima Belgacem
6  Email : belgacem dot nedjima 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 
19 
20 #include "qgspointcloud3dsymbol.h"
21 #include "qgsapplication.h"
22 #include "qgs3dsymbolregistry.h"
23 #include "qgspointcloudattribute.h"
24 #include "qgspointcloudrequest.h"
25 #include "qgscolorramptexture.h"
26 #include "qgs3dmapsettings.h"
27 #include "qgspointcloudindex.h"
29 #include "qgsfeedback.h"
30 
31 #include <Qt3DRender/QGeometryRenderer>
32 #include <Qt3DRender/QAttribute>
33 #include <Qt3DRender/QTechnique>
34 #include <Qt3DRender/QShaderProgram>
35 #include <Qt3DRender/QGraphicsApiFilter>
36 #include <Qt3DRender/QEffect>
37 #include <QPointSize>
38 #include <QUrl>
39 
40 #include <delaunator.hpp>
41 
42 QgsPointCloud3DGeometry::QgsPointCloud3DGeometry( Qt3DCore::QNode *parent, const QgsPointCloud3DSymbolHandler::PointData &data, unsigned int byteStride )
43  : Qt3DRender::QGeometry( parent )
44  , mPositionAttribute( new Qt3DRender::QAttribute( this ) )
45  , mParameterAttribute( new Qt3DRender::QAttribute( this ) )
46  , mColorAttribute( new Qt3DRender::QAttribute( this ) )
47  , mTriangleIndexAttribute( new Qt3DRender::QAttribute( this ) )
48  , mNormalsAttribute( new Qt3DRender::QAttribute( this ) )
49  , mVertexBuffer( new Qt3DRender::QBuffer( this ) )
50  , mByteStride( byteStride )
51 {
52  if ( !data.triangles.isEmpty() )
53  {
54  mTriangleBuffer = new Qt3DRender::QBuffer( this );
55  mTriangleIndexAttribute->setAttributeType( Qt3DRender::QAttribute::IndexAttribute );
56  mTriangleIndexAttribute->setBuffer( mTriangleBuffer );
57  mTriangleIndexAttribute->setVertexBaseType( Qt3DRender::QAttribute::UnsignedInt );
58  mTriangleBuffer->setData( data.triangles );
59  mTriangleIndexAttribute->setCount( data.triangles.size() / sizeof( quint32 ) );
60  addAttribute( mTriangleIndexAttribute );
61  }
62 
63  if ( !data.normals.isEmpty() )
64  {
65  mNormalsBuffer = new Qt3DRender::QBuffer( this );
66  mNormalsAttribute->setName( Qt3DRender::QAttribute::defaultNormalAttributeName() );
67  mNormalsAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
68  mNormalsAttribute->setVertexSize( 3 );
69  mNormalsAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
70  mNormalsAttribute->setBuffer( mNormalsBuffer );
71  mNormalsBuffer->setData( data.normals );
72  mNormalsAttribute->setCount( data.normals.size() / ( 3 * sizeof( float ) ) );
73  addAttribute( mNormalsAttribute );
74  }
75 }
76 
77 QgsSingleColorPointCloud3DGeometry::QgsSingleColorPointCloud3DGeometry( Qt3DCore::QNode *parent, const QgsPointCloud3DSymbolHandler::PointData &data, unsigned int byteStride )
78  : QgsPointCloud3DGeometry( parent, data, byteStride )
79 {
80  mPositionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
81  mPositionAttribute->setBuffer( mVertexBuffer );
82  mPositionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
83  mPositionAttribute->setVertexSize( 3 );
84  mPositionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
85  mPositionAttribute->setByteOffset( 0 );
86  mPositionAttribute->setByteStride( mByteStride );
87  addAttribute( mPositionAttribute );
88  makeVertexBuffer( data );
89 }
90 
91 void QgsSingleColorPointCloud3DGeometry::makeVertexBuffer( const QgsPointCloud3DSymbolHandler::PointData &data )
92 {
93  QByteArray vertexBufferData;
94  vertexBufferData.resize( data.positions.size() * mByteStride );
95  float *rawVertexArray = reinterpret_cast<float *>( vertexBufferData.data() );
96  int idx = 0;
97  for ( int i = 0; i < data.positions.size(); ++i )
98  {
99  rawVertexArray[idx++] = data.positions.at( i ).x();
100  rawVertexArray[idx++] = data.positions.at( i ).y();
101  rawVertexArray[idx++] = data.positions.at( i ).z();
102  }
103 
104  mVertexCount = data.positions.size();
105  mVertexBuffer->setData( vertexBufferData );
106 }
107 
108 QgsColorRampPointCloud3DGeometry::QgsColorRampPointCloud3DGeometry( Qt3DCore::QNode *parent, const QgsPointCloud3DSymbolHandler::PointData &data, unsigned int byteStride )
109  : QgsPointCloud3DGeometry( parent, data, byteStride )
110 {
111  mPositionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
112  mPositionAttribute->setBuffer( mVertexBuffer );
113  mPositionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
114  mPositionAttribute->setVertexSize( 3 );
115  mPositionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
116  mPositionAttribute->setByteOffset( 0 );
117  mPositionAttribute->setByteStride( mByteStride );
118  addAttribute( mPositionAttribute );
119  mParameterAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
120  mParameterAttribute->setBuffer( mVertexBuffer );
121  mParameterAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
122  mParameterAttribute->setVertexSize( 1 );
123  mParameterAttribute->setName( "vertexParameter" );
124  mParameterAttribute->setByteOffset( 12 );
125  mParameterAttribute->setByteStride( mByteStride );
126  addAttribute( mParameterAttribute );
127  makeVertexBuffer( data );
128 }
129 
130 void QgsColorRampPointCloud3DGeometry::makeVertexBuffer( const QgsPointCloud3DSymbolHandler::PointData &data )
131 {
132  QByteArray vertexBufferData;
133  vertexBufferData.resize( data.positions.size() * mByteStride );
134  float *rawVertexArray = reinterpret_cast<float *>( vertexBufferData.data() );
135  int idx = 0;
136  Q_ASSERT( data.positions.size() == data.parameter.size() );
137  for ( int i = 0; i < data.positions.size(); ++i )
138  {
139  rawVertexArray[idx++] = data.positions.at( i ).x();
140  rawVertexArray[idx++] = data.positions.at( i ).y();
141  rawVertexArray[idx++] = data.positions.at( i ).z();
142  rawVertexArray[idx++] = data.parameter.at( i );
143  }
144 
145  mVertexCount = data.positions.size();
146  mVertexBuffer->setData( vertexBufferData );
147 }
148 
149 QgsRGBPointCloud3DGeometry::QgsRGBPointCloud3DGeometry( Qt3DCore::QNode *parent, const QgsPointCloud3DSymbolHandler::PointData &data, unsigned int byteStride )
150  : QgsPointCloud3DGeometry( parent, data, byteStride )
151 {
152  mPositionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
153  mPositionAttribute->setBuffer( mVertexBuffer );
154  mPositionAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
155  mPositionAttribute->setVertexSize( 3 );
156  mPositionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName() );
157  mPositionAttribute->setByteOffset( 0 );
158  mPositionAttribute->setByteStride( mByteStride );
159  addAttribute( mPositionAttribute );
160  mColorAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute );
161  mColorAttribute->setBuffer( mVertexBuffer );
162  mColorAttribute->setVertexBaseType( Qt3DRender::QAttribute::Float );
163  mColorAttribute->setVertexSize( 3 );
164  mColorAttribute->setName( QStringLiteral( "vertexColor" ) );
165  mColorAttribute->setByteOffset( 12 );
166  mColorAttribute->setByteStride( mByteStride );
167  addAttribute( mColorAttribute );
168  makeVertexBuffer( data );
169 }
170 
171 void QgsRGBPointCloud3DGeometry::makeVertexBuffer( const QgsPointCloud3DSymbolHandler::PointData &data )
172 {
173  QByteArray vertexBufferData;
174  vertexBufferData.resize( data.positions.size() * mByteStride );
175  float *rawVertexArray = reinterpret_cast<float *>( vertexBufferData.data() );
176  int idx = 0;
177  Q_ASSERT( data.positions.size() == data.colors.size() );
178  for ( int i = 0; i < data.positions.size(); ++i )
179  {
180  rawVertexArray[idx++] = data.positions.at( i ).x();
181  rawVertexArray[idx++] = data.positions.at( i ).y();
182  rawVertexArray[idx++] = data.positions.at( i ).z();
183  rawVertexArray[idx++] = data.colors.at( i ).x();
184  rawVertexArray[idx++] = data.colors.at( i ).y();
185  rawVertexArray[idx++] = data.colors.at( i ).z();
186  }
187  mVertexCount = data.positions.size();
188  mVertexBuffer->setData( vertexBufferData );
189 }
190 
191 QgsPointCloud3DSymbolHandler::QgsPointCloud3DSymbolHandler()
192 {
193 }
194 
195 
196 void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const QgsPointCloud3DRenderContext &context, const QgsPointCloud3DSymbolHandler::PointData &out, bool selected )
197 {
198  Q_UNUSED( selected )
199 
200  if ( out.positions.empty() )
201  return;
202 
203  // Geometry
204  Qt3DRender::QGeometry *geom = makeGeometry( parent, out, context.symbol()->byteStride() );
205  Qt3DRender::QGeometryRenderer *gr = new Qt3DRender::QGeometryRenderer;
206  if ( context.symbol()->renderAsTriangles() && ! out.triangles.isEmpty() )
207  {
208  gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
209  gr->setVertexCount( out.triangles.size() / sizeof( quint32 ) );
210  }
211  else
212  {
213  gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
214  gr->setVertexCount( out.positions.count() );
215  }
216  gr->setGeometry( geom );
217 
218  // Transform
219  Qt3DCore::QTransform *tr = new Qt3DCore::QTransform;
220 
221  // Material
222  Qt3DRender::QMaterial *mat = new Qt3DRender::QMaterial;
223  if ( context.symbol() )
224  context.symbol()->fillMaterial( mat );
225 
226  Qt3DRender::QShaderProgram *shaderProgram = new Qt3DRender::QShaderProgram( mat );
227  shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/pointcloud.vert" ) ) ) );
228  shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral( "qrc:/shaders/pointcloud.frag" ) ) ) );
229 
230  Qt3DRender::QRenderPass *renderPass = new Qt3DRender::QRenderPass( mat );
231  renderPass->setShaderProgram( shaderProgram );
232 
233  if ( out.triangles.isEmpty() )
234  {
235  Qt3DRender::QPointSize *pointSize = new Qt3DRender::QPointSize( renderPass );
236  pointSize->setSizeMode( Qt3DRender::QPointSize::Programmable ); // supported since OpenGL 3.2
237  pointSize->setValue( context.symbol() ? context.symbol()->pointSize() : 1.0f );
238  renderPass->addRenderState( pointSize );
239  }
240 
241  // without this filter the default forward renderer would not render this
242  Qt3DRender::QFilterKey *filterKey = new Qt3DRender::QFilterKey;
243  filterKey->setName( QStringLiteral( "renderingStyle" ) );
244  filterKey->setValue( "forward" );
245 
246  Qt3DRender::QTechnique *technique = new Qt3DRender::QTechnique;
247  technique->addRenderPass( renderPass );
248  technique->addFilterKey( filterKey );
249  technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
250  technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
251  technique->graphicsApiFilter()->setMajorVersion( 3 );
252  technique->graphicsApiFilter()->setMinorVersion( 1 );
253  technique->addParameter( new Qt3DRender::QParameter( "triangulate", !out.triangles.isEmpty() ) );
254 
255  Qt3DRender::QEffect *eff = new Qt3DRender::QEffect;
256  eff->addTechnique( technique );
257  mat->setEffect( eff );
258 
259  // All together
260  Qt3DCore::QEntity *entity = new Qt3DCore::QEntity;
261  entity->addComponent( gr );
262  entity->addComponent( tr );
263  entity->addComponent( mat );
264  entity->setParent( parent );
265  // cppcheck wrongly believes entity will leak
266  // cppcheck-suppress memleak
267 }
268 
269 
270 std::vector<double> QgsPointCloud3DSymbolHandler::getVertices( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, const QgsAABB &bbox )
271 {
272 
273  bool hasColorData = !outNormal.colors.empty();
274  bool hasParameterData = !outNormal.parameter.empty();
275 
276  // first, get the points of the concerned node
277  std::vector<double> vertices( outNormal.positions.size() * 2 );
278  size_t idx = 0;
279  for ( int i = 0; i < outNormal.positions.size(); ++i )
280  {
281  vertices[idx++] = outNormal.positions.at( i ).x();
282  vertices[idx++] = outNormal.positions.at( i ).z();
283  }
284 
285  // next, we also need all points of all parents nodes to make the triangulation (also external points)
286  IndexedPointCloudNode parentNode = n.parentNode();
287 
288  int properPointsCount = outNormal.positions.count();
289  while ( parentNode.d() >= 0 )
290  {
291  processNode( pc, parentNode, context );
292  parentNode = parentNode.parentNode();
293  }
294 
295  PointData filteredExtraPointData;
296 
297  double span = pc->span();
298  //factor to take account of the density of the point to calculate extension of the bounding box
299  // with a usual value span = 128, bounding box is extended by 12.5 % on each side.
300  double extraBoxFactor = 16 / span;
301  double extraX = extraBoxFactor * bbox.xExtent();
302  double extraZ = extraBoxFactor * bbox.zExtent();
303 
304  // We keep all points in vertical direction to avoid odd triangulation if points are isolated on top
305  const QgsAABB extendedBBox( bbox.xMin - extraX, -std::numeric_limits<float>::max(), bbox.zMin - extraZ, bbox.xMax + extraX, std::numeric_limits<float>::max(), bbox.zMax + extraZ );
306 
307  for ( int i = properPointsCount; i < outNormal.positions.count(); ++i )
308  {
309  const QVector3D pos = outNormal.positions.at( i );
310  if ( extendedBBox.intersects( pos.x(), pos.y(), pos.z() ) )
311  {
312  filteredExtraPointData.positions.append( pos );
313  vertices.push_back( pos.x() );
314  vertices.push_back( pos.z() );
315 
316  if ( hasColorData )
317  filteredExtraPointData.colors.append( outNormal.colors.at( i ) );
318  if ( hasParameterData )
319  filteredExtraPointData.parameter.append( outNormal.parameter.at( i ) );
320  }
321  }
322 
323  outNormal.positions.resize( properPointsCount );
324  if ( hasColorData )
325  outNormal.colors.resize( properPointsCount );
326  if ( hasParameterData )
327  outNormal.parameter.resize( properPointsCount );
328 
329  outNormal.positions.append( filteredExtraPointData.positions );
330  outNormal.colors.append( filteredExtraPointData.colors );
331  outNormal.parameter.append( filteredExtraPointData.parameter );
332 
333  return vertices;
334 }
335 
336 void QgsPointCloud3DSymbolHandler::calculateNormals( const std::vector<size_t> &triangles )
337 {
338  QVector<QVector3D> normals( outNormal.positions.count(), QVector3D( 0.0, 0.0, 0.0 ) );
339  for ( size_t i = 0; i < triangles.size(); i += 3 )
340  {
341  QVector<QVector3D> triangleVertices( 3 );
342  for ( size_t j = 0; j < 3; ++j )
343  {
344  size_t vertIndex = triangles.at( i + j );
345  triangleVertices[j] = outNormal.positions.at( vertIndex );
346  }
347  //calculate normals
348  for ( size_t j = 0; j < 3; ++j )
349  normals[triangles.at( i + j )] += QVector3D::crossProduct(
350  triangleVertices.at( 1 ) - triangleVertices.at( 0 ),
351  triangleVertices.at( 2 ) - triangleVertices.at( 0 ) );
352  }
353 
354  // Build now normals array
355  outNormal.normals.resize( ( outNormal.positions.count() ) * sizeof( float ) * 3 );
356  float *normPtr = reinterpret_cast<float *>( outNormal.normals.data() );
357  for ( int i = 0; i < normals.size(); ++i )
358  {
359  QVector3D normal = normals.at( i );
360  normal = normal.normalized();
361 
362  *normPtr++ = normal.x();
363  *normPtr++ = normal.y();
364  *normPtr++ = normal.z();
365  }
366 }
367 
368 void QgsPointCloud3DSymbolHandler::filterTriangles( const std::vector<size_t> &triangleIndexes, const QgsPointCloud3DRenderContext &context, const QgsAABB &bbox )
369 {
370  outNormal.triangles.resize( triangleIndexes.size() * sizeof( quint32 ) );
371  quint32 *indexPtr = reinterpret_cast<quint32 *>( outNormal.triangles.data() );
372  size_t effective = 0;
373 
374  bool horizontalFilter = context.symbol()->horizontalTriangleFilter();
375  bool verticalFilter = context.symbol()->verticalTriangleFilter();
376  float horizontalThreshold = context.symbol()->horizontalFilterThreshold();
377  float verticalThreshold = context.symbol()->verticalFilterThreshold();
378 
379  for ( size_t i = 0; i < triangleIndexes.size(); i += 3 )
380  {
381  bool atLeastOneInBox = false;
382  bool horizontalSkip = false;
383  bool verticalSkip = false;
384  for ( size_t j = 0; j < 3; j++ )
385  {
386  QVector3D pos = outNormal.positions.at( triangleIndexes.at( i + j ) );
387  atLeastOneInBox |= bbox.intersects( pos.x(), pos.y(), pos.z() );
388 
389  if ( verticalFilter || horizontalFilter )
390  {
391  const QVector3D pos2 = outNormal.positions.at( triangleIndexes.at( i + ( j + 1 ) % 3 ) );
392 
393  if ( verticalFilter )
394  verticalSkip |= std::fabs( pos.y() - pos2.y() ) > verticalThreshold;
395 
396  if ( horizontalFilter && ! verticalSkip )
397  {
398  // filter only in the horizontal plan, it is a 2.5D triangulation.
399  horizontalSkip |= sqrt( std::pow( pos.x() - pos2.x(), 2 ) +
400  std::pow( pos.z() - pos2.z(), 2 ) ) > horizontalThreshold;
401  }
402 
403  if ( horizontalSkip || verticalSkip )
404  break;
405  }
406  }
407  if ( atLeastOneInBox && !horizontalSkip && !verticalSkip )
408  {
409  for ( size_t j = 0; j < 3; j++ )
410  {
411  size_t vertIndex = triangleIndexes.at( i + j );
412  *indexPtr++ = quint32( vertIndex );
413  }
414  effective++;
415  }
416  }
417 
418  if ( effective != 0 )
419  {
420  outNormal.triangles.resize( effective * 3 * sizeof( quint32 ) );
421  }
422  else
423  {
424  outNormal.triangles.clear();
425  outNormal.normals.clear();
426  }
427 }
428 
429 void QgsPointCloud3DSymbolHandler::triangulate( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, const QgsAABB &bbox )
430 {
431  if ( outNormal.positions.isEmpty() )
432  return;
433 
434  // Triangulation happens here
435  std::unique_ptr<delaunator::Delaunator> triangulation;
436  try
437  {
438  std::vector<double> vertices = getVertices( pc, n, context, bbox );
439  triangulation.reset( new delaunator::Delaunator( vertices ) );
440  }
441  catch ( std::exception &e )
442  {
443  // something went wrong, better to retrieve initial state
444  QgsDebugMsgLevel( QStringLiteral( "Error with triangulation" ), 4 );
445  outNormal = PointData();
446  processNode( pc, n, context );
447  return;
448  }
449 
450  const std::vector<size_t> &triangleIndexes = triangulation->triangles;
451 
452  calculateNormals( triangleIndexes );
453  filterTriangles( triangleIndexes, context, bbox );
454 }
455 
456 QgsPointCloudBlock *QgsPointCloud3DSymbolHandler::pointCloudBlock( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloudRequest &request, const QgsPointCloud3DRenderContext &context )
457 {
458  QgsPointCloudBlock *block = nullptr;
459  if ( pc->accessType() == QgsPointCloudIndex::AccessType::Local )
460  {
461  block = pc->nodeData( n, request );
462  }
463  else if ( pc->accessType() == QgsPointCloudIndex::AccessType::Remote )
464  {
465  bool loopAborted = false;
466  QEventLoop loop;
467  QgsPointCloudBlockRequest *req = pc->asyncNodeData( n, request );
468  QObject::connect( req, &QgsPointCloudBlockRequest::finished, &loop, &QEventLoop::quit );
469  QObject::connect( context.feedback(), &QgsFeedback::canceled, &loop, [ & ]()
470  {
471  loopAborted = true;
472  loop.quit();
473  } );
474  loop.exec();
475 
476  if ( !loopAborted )
477  block = req->block();
478  }
479  return block;
480 }
481 
482 //
483 
484 QgsSingleColorPointCloud3DSymbolHandler::QgsSingleColorPointCloud3DSymbolHandler()
485  : QgsPointCloud3DSymbolHandler()
486 {
487 
488 }
489 
490 bool QgsSingleColorPointCloud3DSymbolHandler::prepare( const QgsPointCloud3DRenderContext &context )
491 {
492  Q_UNUSED( context )
493  return true;
494 }
495 
496 void QgsSingleColorPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context )
497 {
499  attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "X" ), QgsPointCloudAttribute::Int32 ) );
500  attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "Y" ), QgsPointCloudAttribute::Int32 ) );
501  attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "Z" ), QgsPointCloudAttribute::Int32 ) );
502 
503  QgsPointCloudRequest request;
504  request.setAttributes( attributes );
505  std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
506  if ( !block )
507  return;
508 
509  const char *ptr = block->data();
510  const int count = block->pointCount();
511  const std::size_t recordSize = block->attributes().pointRecordSize();
512  const QgsVector3D blockScale = block->scale();
513  const QgsVector3D blockOffset = block->offset();
514  const double zValueScale = context.zValueScale();
515  const double zValueOffset = context.zValueFixedOffset();
516  const QgsCoordinateTransform coordinateTransform = context.coordinateTransform();
517  bool alreadyPrintedDebug = false;
518 
519  for ( int i = 0; i < count; ++i )
520  {
521  if ( context.isCanceled() )
522  break;
523 
524  const qint32 ix = *( qint32 * )( ptr + i * recordSize + 0 );
525  const qint32 iy = *( qint32 * )( ptr + i * recordSize + 4 );
526  const qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
527 
528  double x = blockOffset.x() + blockScale.x() * ix;
529  double y = blockOffset.y() + blockScale.y() * iy;
530  double z = ( blockOffset.z() + blockScale.z() * iz ) * zValueScale + zValueOffset;
531  try
532  {
533  coordinateTransform.transformInPlace( x, y, z );
534  }
535  catch ( QgsCsException &e )
536  {
537  if ( !alreadyPrintedDebug )
538  {
539  QgsDebugMsg( QStringLiteral( "Error transforming point coordinate" ) );
540  alreadyPrintedDebug = true;
541  }
542  }
543  const QgsVector3D point( x, y, z );
544  const QgsVector3D p = context.map().mapToWorldCoordinates( QgsVector3D( x, y, z ) );
545  outNormal.positions.push_back( QVector3D( p.x(), p.y(), p.z() ) );
546  }
547 }
548 
549 void QgsSingleColorPointCloud3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const QgsPointCloud3DRenderContext &context )
550 {
551  makeEntity( parent, context, outNormal, false );
552 }
553 
554 Qt3DRender::QGeometry *QgsSingleColorPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent, const QgsPointCloud3DSymbolHandler::PointData &data, unsigned int byteStride )
555 {
556  return new QgsSingleColorPointCloud3DGeometry( parent, data, byteStride );
557 }
558 
559 QgsColorRampPointCloud3DSymbolHandler::QgsColorRampPointCloud3DSymbolHandler()
560  : QgsPointCloud3DSymbolHandler()
561 {
562 
563 }
564 
565 bool QgsColorRampPointCloud3DSymbolHandler::prepare( const QgsPointCloud3DRenderContext &context )
566 {
567  Q_UNUSED( context )
568  return true;
569 }
570 
571 void QgsColorRampPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context )
572 {
574  const int xOffset = 0;
575  attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "X" ), QgsPointCloudAttribute::Int32 ) );
576  const int yOffset = attributes.pointRecordSize();
577  attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "Y" ), QgsPointCloudAttribute::Int32 ) );
578  const int zOffset = attributes.pointRecordSize();
579  attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "Z" ), QgsPointCloudAttribute::Int32 ) );
580 
581  QString attributeName;
582  bool attrIsX = false;
583  bool attrIsY = false;
584  bool attrIsZ = false;
586  int attributeOffset = 0;
587  const double zValueScale = context.zValueScale();
588  const double zValueOffset = context.zValueFixedOffset();
589  const QgsCoordinateTransform coordinateTransform = context.coordinateTransform();
590  bool alreadyPrintedDebug = false;
591 
592  QgsColorRampPointCloud3DSymbol *symbol = dynamic_cast<QgsColorRampPointCloud3DSymbol *>( context.symbol() );
593  if ( symbol )
594  {
595  int offset = 0;
596  const QgsPointCloudAttributeCollection collection = context.attributes();
597 
598  if ( symbol->attribute() == QLatin1String( "X" ) )
599  {
600  attrIsX = true;
601  }
602  else if ( symbol->attribute() == QLatin1String( "Y" ) )
603  {
604  attrIsY = true;
605  }
606  else if ( symbol->attribute() == QLatin1String( "Z" ) )
607  {
608  attrIsZ = true;
609  }
610  else
611  {
612  const QgsPointCloudAttribute *attr = collection.find( symbol->attribute(), offset );
613  if ( attr )
614  {
615  attributeType = attr->type();
616  attributeName = attr->name();
617  attributeOffset = attributes.pointRecordSize();
618  attributes.push_back( *attr );
619  }
620  }
621  }
622 
623  if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
624  return;
625 
626  QgsPointCloudRequest request;
627  request.setAttributes( attributes );
628  std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
629  if ( !block )
630  return;
631 
632  const char *ptr = block->data();
633  const int count = block->pointCount();
634  const std::size_t recordSize = block->attributes().pointRecordSize();
635 
636  const QgsVector3D blockScale = block->scale();
637  const QgsVector3D blockOffset = block->offset();
638 
639  for ( int i = 0; i < count; ++i )
640  {
641  if ( context.isCanceled() )
642  break;
643 
644  const qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
645  const qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
646  const qint32 iz = *( qint32 * )( ptr + i * recordSize + zOffset );
647 
648  double x = blockOffset.x() + blockScale.x() * ix;
649  double y = blockOffset.y() + blockScale.y() * iy;
650  double z = ( blockOffset.z() + blockScale.z() * iz ) * zValueScale + zValueOffset;
651  try
652  {
653  coordinateTransform.transformInPlace( x, y, z );
654  }
655  catch ( QgsCsException & )
656  {
657  if ( !alreadyPrintedDebug )
658  {
659  QgsDebugMsg( QStringLiteral( "Error transforming point coordinate" ) );
660  alreadyPrintedDebug = true;
661  }
662  }
663  QgsVector3D point( x, y, z );
664  point = context.map().mapToWorldCoordinates( point );
665  outNormal.positions.push_back( QVector3D( point.x(), point.y(), point.z() ) );
666 
667  if ( attrIsX )
668  outNormal.parameter.push_back( x );
669  else if ( attrIsY )
670  outNormal.parameter.push_back( y );
671  else if ( attrIsZ )
672  outNormal.parameter.push_back( z );
673  else
674  {
675  float iParam = 0.0f;
676  context.getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
677  outNormal.parameter.push_back( iParam );
678  }
679  }
680 }
681 
682 void QgsColorRampPointCloud3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const QgsPointCloud3DRenderContext &context )
683 {
684  makeEntity( parent, context, outNormal, false );
685 }
686 
687 Qt3DRender::QGeometry *QgsColorRampPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent, const QgsPointCloud3DSymbolHandler::PointData &data, unsigned int byteStride )
688 {
689  return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );
690 }
691 
692 QgsRGBPointCloud3DSymbolHandler::QgsRGBPointCloud3DSymbolHandler()
693  : QgsPointCloud3DSymbolHandler()
694 {
695 
696 }
697 
698 bool QgsRGBPointCloud3DSymbolHandler::prepare( const QgsPointCloud3DRenderContext &context )
699 {
700  Q_UNUSED( context )
701  return true;
702 }
703 
704 void QgsRGBPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context )
705 {
707  attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "X" ), QgsPointCloudAttribute::Int32 ) );
708  attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "Y" ), QgsPointCloudAttribute::Int32 ) );
709  attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "Z" ), QgsPointCloudAttribute::Int32 ) );
710 
711  QgsRgbPointCloud3DSymbol *symbol = dynamic_cast<QgsRgbPointCloud3DSymbol *>( context.symbol() );
712 
713  // we have to get the RGB attributes using their real data types -- they aren't always short! (sometimes unsigned short)
714  int attrOffset = 0 ;
715 
716  const int redOffset = attributes.pointRecordSize();
717  const QgsPointCloudAttribute *colorAttribute = context.attributes().find( symbol->redAttribute(), attrOffset );
718  attributes.push_back( *colorAttribute );
719  const QgsPointCloudAttribute::DataType redType = colorAttribute->type();
720 
721  const int greenOffset = attributes.pointRecordSize();
722  colorAttribute = context.attributes().find( symbol->greenAttribute(), attrOffset );
723  attributes.push_back( *colorAttribute );
724  const QgsPointCloudAttribute::DataType greenType = colorAttribute->type();
725 
726  const int blueOffset = attributes.pointRecordSize();
727  colorAttribute = context.attributes().find( symbol->blueAttribute(), attrOffset );
728  attributes.push_back( *colorAttribute );
729  const QgsPointCloudAttribute::DataType blueType = colorAttribute->type();
730 
731  QgsPointCloudRequest request;
732  request.setAttributes( attributes );
733  std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
734  if ( !block )
735  return;
736 
737  const char *ptr = block->data();
738  const int count = block->pointCount();
739  const std::size_t recordSize = block->attributes().pointRecordSize();
740 
741  const QgsVector3D blockScale = block->scale();
742  const QgsVector3D blockOffset = block->offset();
743  const double zValueScale = context.zValueScale();
744  const double zValueOffset = context.zValueFixedOffset();
745  const QgsCoordinateTransform coordinateTransform = context.coordinateTransform();
746  bool alreadyPrintedDebug = false;
747 
748  QgsContrastEnhancement *redContrastEnhancement = symbol->redContrastEnhancement();
749  QgsContrastEnhancement *greenContrastEnhancement = symbol->greenContrastEnhancement();
750  QgsContrastEnhancement *blueContrastEnhancement = symbol->blueContrastEnhancement();
751 
752  const bool useRedContrastEnhancement = redContrastEnhancement && redContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement;
753  const bool useBlueContrastEnhancement = blueContrastEnhancement && blueContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement;
754  const bool useGreenContrastEnhancement = greenContrastEnhancement && greenContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement;
755 
756  int ir = 0;
757  int ig = 0;
758  int ib = 0;
759  for ( int i = 0; i < count; ++i )
760  {
761  if ( context.isCanceled() )
762  break;
763 
764  const qint32 ix = *( qint32 * )( ptr + i * recordSize + 0 );
765  const qint32 iy = *( qint32 * )( ptr + i * recordSize + 4 );
766  const qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
767  double x = blockOffset.x() + blockScale.x() * ix;
768  double y = blockOffset.y() + blockScale.y() * iy;
769  double z = ( blockOffset.z() + blockScale.z() * iz ) * zValueScale + zValueOffset;
770  try
771  {
772  coordinateTransform.transformInPlace( x, y, z );
773  }
774  catch ( QgsCsException & )
775  {
776  if ( !alreadyPrintedDebug )
777  {
778  QgsDebugMsg( QStringLiteral( "Error transforming point coordinate" ) );
779  alreadyPrintedDebug = true;
780  }
781  }
782  const QgsVector3D point( x, y, z );
783  const QgsVector3D p = context.map().mapToWorldCoordinates( point );
784 
785  QVector3D color( 0.0f, 0.0f, 0.0f );
786 
787  context.getAttribute( ptr, i * recordSize + redOffset, redType, ir );
788  context.getAttribute( ptr, i * recordSize + greenOffset, greenType, ig );
789  context.getAttribute( ptr, i * recordSize + blueOffset, blueType, ib );
790 
791  //skip if red, green or blue not in displayable range
792  if ( ( useRedContrastEnhancement && !redContrastEnhancement->isValueInDisplayableRange( ir ) )
793  || ( useGreenContrastEnhancement && !greenContrastEnhancement->isValueInDisplayableRange( ig ) )
794  || ( useBlueContrastEnhancement && !blueContrastEnhancement->isValueInDisplayableRange( ib ) ) )
795  {
796  continue;
797  }
798 
799  //stretch color values
800  if ( useRedContrastEnhancement )
801  {
802  ir = redContrastEnhancement->enhanceContrast( ir );
803  }
804  if ( useGreenContrastEnhancement )
805  {
806  ig = greenContrastEnhancement->enhanceContrast( ig );
807  }
808  if ( useBlueContrastEnhancement )
809  {
810  ib = blueContrastEnhancement->enhanceContrast( ib );
811  }
812 
813  color.setX( ir / 255.0f );
814  color.setY( ig / 255.0f );
815  color.setZ( ib / 255.0f );
816 
817  outNormal.positions.push_back( QVector3D( p.x(), p.y(), p.z() ) );
818  outNormal.colors.push_back( color );
819  }
820 }
821 
822 void QgsRGBPointCloud3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const QgsPointCloud3DRenderContext &context )
823 {
824  makeEntity( parent, context, outNormal, false );
825 }
826 
827 Qt3DRender::QGeometry *QgsRGBPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent, const QgsPointCloud3DSymbolHandler::PointData &data, unsigned int byteStride )
828 {
829  return new QgsRGBPointCloud3DGeometry( parent, data, byteStride );
830 }
831 
832 QgsClassificationPointCloud3DSymbolHandler::QgsClassificationPointCloud3DSymbolHandler()
833  : QgsPointCloud3DSymbolHandler()
834 {
835 
836 }
837 
838 bool QgsClassificationPointCloud3DSymbolHandler::prepare( const QgsPointCloud3DRenderContext &context )
839 {
840  Q_UNUSED( context )
841  return true;
842 }
843 
844 void QgsClassificationPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context )
845 {
847  const int xOffset = 0;
848  attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "X" ), QgsPointCloudAttribute::Int32 ) );
849  const int yOffset = attributes.pointRecordSize();
850  attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "Y" ), QgsPointCloudAttribute::Int32 ) );
851  const int zOffset = attributes.pointRecordSize();
852  attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "Z" ), QgsPointCloudAttribute::Int32 ) );
853 
854  QString attributeName;
855  bool attrIsX = false;
856  bool attrIsY = false;
857  bool attrIsZ = false;
859  int attributeOffset = 0;
861  if ( symbol )
862  {
863  int offset = 0;
864  const QgsPointCloudAttributeCollection collection = context.attributes();
865 
866  if ( symbol->attribute() == QLatin1String( "X" ) )
867  {
868  attrIsX = true;
869  }
870  else if ( symbol->attribute() == QLatin1String( "Y" ) )
871  {
872  attrIsY = true;
873  }
874  else if ( symbol->attribute() == QLatin1String( "Z" ) )
875  {
876  attrIsZ = true;
877  }
878  else
879  {
880  const QgsPointCloudAttribute *attr = collection.find( symbol->attribute(), offset );
881  if ( attr )
882  {
883  attributeType = attr->type();
884  attributeName = attr->name();
885  attributeOffset = attributes.pointRecordSize();
886  attributes.push_back( *attr );
887  }
888  }
889  }
890 
891  if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
892  return;
893 
894  QgsPointCloudRequest request;
895  request.setAttributes( attributes );
896  std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
897  if ( !block )
898  return;
899 
900  const char *ptr = block->data();
901  const int count = block->pointCount();
902  const std::size_t recordSize = block->attributes().pointRecordSize();
903 
904  const QgsVector3D blockScale = block->scale();
905  const QgsVector3D blockOffset = block->offset();
906  const double zValueScale = context.zValueScale();
907  const double zValueOffset = context.zValueFixedOffset();
908  const QgsCoordinateTransform coordinateTransform = context.coordinateTransform();
909  bool alreadyPrintedDebug = false;
910 
911  QList<QgsPointCloudCategory> categoriesList = symbol->categoriesList();
912  QVector<int> categoriesValues;
913  for ( QgsPointCloudCategory &c : categoriesList )
914  {
915  categoriesValues.push_back( c.value() );
916  }
917 
918  const QSet<int> filteredOutValues = context.getFilteredOutValues();
919  for ( int i = 0; i < count; ++i )
920  {
921  if ( context.isCanceled() )
922  break;
923 
924  const qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
925  const qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
926  const qint32 iz = *( qint32 * )( ptr + i * recordSize + zOffset );
927 
928  double x = blockOffset.x() + blockScale.x() * ix;
929  double y = blockOffset.y() + blockScale.y() * iy;
930  double z = ( blockOffset.z() + blockScale.z() * iz ) * zValueScale + zValueOffset;
931  try
932  {
933  coordinateTransform.transformInPlace( x, y, z );
934  }
935  catch ( QgsCsException & )
936  {
937  if ( !alreadyPrintedDebug )
938  {
939  QgsDebugMsg( QStringLiteral( "Error transforming point coordinate" ) );
940  alreadyPrintedDebug = true;
941  }
942  }
943  const QgsVector3D point( x, y, z );
944  const QgsVector3D p = context.map().mapToWorldCoordinates( point );
945  float iParam = 0.0f;
946  if ( attrIsX )
947  iParam = x;
948  else if ( attrIsY )
949  iParam = y;
950  else if ( attrIsZ )
951  iParam = z;
952  else
953  context.getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
954 
955  if ( filteredOutValues.contains( ( int ) iParam ) ||
956  ! categoriesValues.contains( ( int ) iParam ) )
957  continue;
958  outNormal.positions.push_back( QVector3D( p.x(), p.y(), p.z() ) );
959 
960  // find iParam actual index in the categories list
961  float iParam2 = categoriesValues.indexOf( ( int )iParam ) + 1;
962  outNormal.parameter.push_back( iParam2 );
963  }
964 }
965 
966 void QgsClassificationPointCloud3DSymbolHandler::finalize( Qt3DCore::QEntity *parent, const QgsPointCloud3DRenderContext &context )
967 {
968  makeEntity( parent, context, outNormal, false );
969 }
970 
971 Qt3DRender::QGeometry *QgsClassificationPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent, const QgsPointCloud3DSymbolHandler::PointData &data, unsigned int byteStride )
972 {
973  return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );
974 }
975 
QgsRgbPointCloud3DSymbol::blueContrastEnhancement
QgsContrastEnhancement * blueContrastEnhancement()
Returns the contrast enhancement to use for the blue channel.
Definition: qgspointcloud3dsymbol.cpp:446
QgsRgbPointCloud3DSymbol::redContrastEnhancement
QgsContrastEnhancement * redContrastEnhancement()
Returns the contrast enhancement to use for the red channel.
Definition: qgspointcloud3dsymbol.cpp:426
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
QgsRgbPointCloud3DSymbol
3D symbol that draws point cloud geometries as 3D objects using RGB colors in the dataset
Definition: qgspointcloud3dsymbol.h:314
QgsPointCloudBlockRequest::block
QgsPointCloudBlock * block()
Returns the requested block.
QgsPointCloudAttribute::DataType
DataType
Systems of unit measurement.
Definition: qgspointcloudattribute.h:44
QgsPointCloudAttributeCollection::find
const QgsPointCloudAttribute * find(const QString &attributeName, int &offset) const
Finds the attribute with the name.
Definition: qgspointcloudattribute.cpp:168
QgsPointCloudIndex::nodeData
virtual QgsPointCloudBlock * nodeData(const IndexedPointCloudNode &n, const QgsPointCloudRequest &request)=0
Returns node data block.
qgspointcloudblockrequest.h
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsVector3D::y
double y() const
Returns Y coordinate.
Definition: qgsvector3d.h:64
QgsPointCloud3DRenderContext::getAttribute
void getAttribute(const char *data, std::size_t offset, QgsPointCloudAttribute::DataType type, T &value) const
Retrieves the attribute value from data at the specified offset, where type indicates the original da...
Definition: qgspointcloudlayer3drenderer.h:109
QgsPointCloudBlock::data
const char * data() const
Returns raw pointer to data.
Definition: qgspointcloudblock.cpp:37
QgsPointCloud3DSymbol::horizontalFilterThreshold
float horizontalFilterThreshold() const
Returns the threshold horizontal size value for filtering triangles.
Definition: qgspointcloud3dsymbol.cpp:60
QgsVector3D
Class for storage of 3D vectors similar to QVector3D, with the difference that it uses double precisi...
Definition: qgsvector3d.h:31
QgsFeedback::canceled
void canceled()
Internal routines can connect to this signal if they use event loop.
QgsAABB::xExtent
float xExtent() const
Returns box width in X axis.
Definition: qgsaabb.h:43
QgsPointCloud3DSymbol::verticalTriangleFilter
bool verticalTriangleFilter() const
Returns whether triangles are filtered by vertical height for rendering.
Definition: qgspointcloud3dsymbol.cpp:70
QgsPointCloudBlock::attributes
QgsPointCloudAttributeCollection attributes() const
Returns the attributes that are stored in the data block, along with their size.
Definition: qgspointcloudblock.cpp:47
QgsClassificationPointCloud3DSymbol::attribute
QString attribute() const
Returns the attribute used to select the color of the point cloud.
Definition: qgspointcloud3dsymbol.cpp:529
QgsPointCloud3DSymbol::fillMaterial
virtual void fillMaterial(Qt3DRender::QMaterial *material)=0SIP_SKIP
Used to fill material object with necessary QParameters (and consequently opengl uniforms)
QgsRgbPointCloud3DSymbol::blueAttribute
QString blueAttribute() const
Returns the attribute to use for the blue channel.
Definition: qgspointcloud3dsymbol.cpp:416
QgsClassificationPointCloud3DSymbol::categoriesList
QgsPointCloudCategoryList categoriesList() const
Returns the list of categories of the classification.
Definition: qgspointcloud3dsymbol.h:502
QgsPointCloudCategory
Represents an individual category (class) from a QgsPointCloudClassifiedRenderer.
Definition: qgspointcloudclassifiedrenderer.h:32
qgspointcloudattribute.h
QgsPointCloudBlock
Base class for storing raw data from point cloud nodes.
Definition: qgspointcloudblock.h:38
QgsRgbPointCloud3DSymbol::greenContrastEnhancement
QgsContrastEnhancement * greenContrastEnhancement()
Returns the contrast enhancement to use for the green channel.
Definition: qgspointcloud3dsymbol.cpp:436
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsPointCloud3DRenderContext::zValueFixedOffset
double zValueFixedOffset() const
Returns any constant offset which must be applied to z values taken from the point cloud index.
Definition: qgspointcloudlayer3drenderer.h:162
QgsPointCloudAttribute::name
QString name() const
Returns name of the attribute.
Definition: qgspointcloudattribute.h:64
QgsAABB::zMax
float zMax
Definition: qgsaabb.h:86
qgs3dsymbolregistry.h
IndexedPointCloudNode::d
int d() const
Returns d.
Definition: qgspointcloudindex.cpp:63
QgsPointCloudIndex::accessType
virtual AccessType accessType() const =0
Returns the access type of the data If the access type is Remote, data will be fetched from an HTTP s...
QgsPointCloudBlock::pointCount
int pointCount() const
Returns number of points that are stored in the block.
Definition: qgspointcloudblock.cpp:42
QgsPointCloudRequest
Point cloud data request.
Definition: qgspointcloudrequest.h:39
QgsPointCloud3DSymbol::renderAsTriangles
bool renderAsTriangles() const
Returns whether points are triangulated to render solid surface.
Definition: qgspointcloud3dsymbol.cpp:40
IndexedPointCloudNode::parentNode
IndexedPointCloudNode parentNode() const
Returns the parent of the node.
Definition: qgspointcloudindex.cpp:45
qgsapplication.h
QgsPointCloud3DRenderContext::coordinateTransform
QgsCoordinateTransform coordinateTransform() const
Returns the coordinate transform used to transform points from layer CRS to the map CRS.
Definition: qgspointcloudlayer3drenderer.h:183
QgsPointCloud3DRenderContext::getFilteredOutValues
QSet< int > getFilteredOutValues() const
Returns a set containing the filtered out values.
Definition: qgspointcloudlayer3drenderer.cpp:55
IndexedPointCloudNode
Represents a indexed point cloud node in octree.
Definition: qgspointcloudindex.h:57
qgspointcloud3dsymbol.h
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
QgsPointCloudAttribute::Int32
@ Int32
Int32 4 bytes.
Definition: qgspointcloudattribute.h:50
QgsPointCloudAttributeCollection::pointRecordSize
int pointRecordSize() const
Returns total size of record.
Definition: qgspointcloudattribute.h:187
QgsContrastEnhancement::enhanceContrast
int enhanceContrast(double value)
Applies the contrast enhancement to a value.
Definition: qgscontrastenhancement.cpp:72
QgsVector3D::z
double z() const
Returns Z coordinate.
Definition: qgsvector3d.h:66
QgsContrastEnhancement::NoEnhancement
@ NoEnhancement
Default color scaling algorithm, no scaling is applied.
Definition: qgscontrastenhancement.h:50
QgsPointCloud3DSymbol::horizontalTriangleFilter
bool horizontalTriangleFilter() const
Returns whether triangles are filtered by horizontal size for rendering.
Definition: qgspointcloud3dsymbol.cpp:50
QgsPointCloudAttributeCollection
Collection of point cloud attributes.
Definition: qgspointcloudattribute.h:141
Qt3DRender
Definition: qgs3dmapscene.h:28
QgsAABB::xMin
float xMin
Definition: qgsaabb.h:81
QgsAABB
Axis-aligned bounding box - in world coords.
Definition: qgsaabb.h:33
QgsPointCloud3DRenderContext::zValueScale
double zValueScale() const
Returns any constant scaling factor which must be applied to z values taken from the point cloud inde...
Definition: qgspointcloudlayer3drenderer.h:155
QgsPointCloudAttribute
Attribute for point cloud data pair of name and size in bytes.
Definition: qgspointcloudattribute.h:40
QgsContrastEnhancement::contrastEnhancementAlgorithm
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
Definition: qgscontrastenhancement.h:160
QgsPointCloud3DRenderContext::attributes
QgsPointCloudAttributeCollection attributes() const
Returns the attributes associated with the rendered block.
Definition: qgspointcloudlayer3drenderer.h:69
QgsContrastEnhancement
Manipulates raster or point cloud pixel values so that they enhanceContrast or clip into a specified ...
Definition: qgscontrastenhancement.h:42
qgspointcloudindex.h
QgsPointCloudIndex::asyncNodeData
virtual QgsPointCloudBlockRequest * asyncNodeData(const IndexedPointCloudNode &n, const QgsPointCloudRequest &request)=0
Returns a handle responsible for loading a node data block.
QgsColorRampPointCloud3DSymbol
3D symbol that draws point cloud geometries as 3D objects.using color ramp shader
Definition: qgspointcloud3dsymbol.h:241
QgsRgbPointCloud3DSymbol::greenAttribute
QString greenAttribute() const
Returns the attribute to use for the green channel.
Definition: qgspointcloud3dsymbol.cpp:406
qgs3dmapsettings.h
QgsPointCloud3DRenderContext
Encapsulates the render context for a 3D point cloud rendering operation.
Definition: qgspointcloudlayer3drenderer.h:42
QgsPointCloud3DSymbol::verticalFilterThreshold
float verticalFilterThreshold() const
Returns the threshold vertical height value for filtering triangles.
Definition: qgspointcloud3dsymbol.cpp:80
c
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Definition: porting_processing.dox:1
QgsPointCloudBlockRequest
Base class for handling loading QgsPointCloudBlock asynchronously.
Definition: qgspointcloudblockrequest.h:36
qgscolorramptexture.h
QgsPointCloudBlock::offset
QgsVector3D offset() const
Returns the custom offset of the block.
Definition: qgspointcloudblock.cpp:57
QgsPointCloudRequest::setAttributes
void setAttributes(const QgsPointCloudAttributeCollection &attributes)
Set attributes filter in the request.
Definition: qgspointcloudrequest.cpp:29
QgsPointCloudBlockRequest::finished
void finished()
Emitted when the request processing has finished.
QgsPointCloudIndex::span
int span() const
Returns the number of points in one direction in a single node.
Definition: qgspointcloudindex.cpp:247
QgsPointCloud3DSymbol::byteStride
virtual unsigned int byteStride()=0
Returns the byte stride for the geometries used to for the vertex buffer.
QgsPointCloud3DRenderContext::symbol
QgsPointCloud3DSymbol * symbol() const
Returns the symbol used for rendering the point cloud.
Definition: qgspointcloudlayer3drenderer.h:83
QgsAABB::intersects
bool intersects(const QgsAABB &other) const
Determines whether the box intersects some other axis aligned box.
Definition: qgsaabb.cpp:35
QgsPointCloud3DRenderContext::isCanceled
bool isCanceled() const
Returns true if the rendering is canceled.
Definition: qgspointcloudlayer3drenderer.cpp:68
QgsPointCloudIndex
Represents a indexed point clouds data in octree.
Definition: qgspointcloudindex.h:163
QgsContrastEnhancement::isValueInDisplayableRange
bool isValueInDisplayableRange(double value)
Returns true if a pixel value is in displayable range, false if pixel is outside of range (i....
Definition: qgscontrastenhancement.cpp:122
QgsPointCloud3DSymbol::pointSize
float pointSize() const
Returns the point size of the point cloud.
Definition: qgspointcloud3dsymbol.h:88
QgsPointCloudAttributeCollection::push_back
void push_back(const QgsPointCloudAttribute &attribute)
Adds extra attribute.
Definition: qgspointcloudattribute.cpp:142
QgsPointCloud3DRenderContext::feedback
QgsFeedback * feedback() const
Returns the feedback object used to cancel rendering and check if rendering was canceled.
Definition: qgspointcloudlayer3drenderer.h:188
QgsAABB::zMin
float zMin
Definition: qgsaabb.h:83
qgspointcloudrequest.h
QgsAABB::xMax
float xMax
Definition: qgsaabb.h:84
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:57
qgsfeedback.h
QgsVector3D::x
double x() const
Returns X coordinate.
Definition: qgsvector3d.h:62
QgsPointCloudAttribute::Float
@ Float
Float 4 bytes.
Definition: qgspointcloudattribute.h:54
QgsRgbPointCloud3DSymbol::redAttribute
QString redAttribute() const
Returns the attribute to use for the red channel.
Definition: qgspointcloud3dsymbol.cpp:396
QgsColorRampPointCloud3DSymbol::attribute
QString attribute() const
Returns the attribute used to select the color of the point cloud.
Definition: qgspointcloud3dsymbol.cpp:227
QgsClassificationPointCloud3DSymbol
3D symbol that draws point cloud geometries as 3D objects using classification of the dataset
Definition: qgspointcloud3dsymbol.h:474
qgspointcloud3dsymbol_p.h
QgsPointCloudBlock::scale
QgsVector3D scale() const
Returns the custom scale of the block.
Definition: qgspointcloudblock.cpp:52
QgsPointCloudAttribute::type
DataType type() const
Returns the data type.
Definition: qgspointcloudattribute.h:74
QgsAABB::zExtent
float zExtent() const
Returns box width in Z axis.
Definition: qgsaabb.h:47