28#include <Qt3DRender/QGeometryRenderer>
29#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
30#include <Qt3DRender/QAttribute>
31#include <Qt3DRender/QBuffer>
32#include <Qt3DRender/QGeometry>
38#include <Qt3DCore/QAttribute>
39#include <Qt3DCore/QBuffer>
40#include <Qt3DCore/QGeometry>
46#include <Qt3DRender/QTechnique>
47#include <Qt3DRender/QShaderProgram>
48#include <Qt3DRender/QGraphicsApiFilter>
49#include <Qt3DRender/QEffect>
53#include <delaunator.hpp>
55QgsPointCloud3DGeometry::QgsPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
64 , mByteStride( byteStride )
66 if ( !data.triangles.isEmpty() )
69 mTriangleIndexAttribute->setAttributeType( Qt3DQAttribute::IndexAttribute );
70 mTriangleIndexAttribute->setBuffer( mTriangleBuffer );
71 mTriangleIndexAttribute->setVertexBaseType( Qt3DQAttribute::UnsignedInt );
72 mTriangleBuffer->setData( data.triangles );
73 mTriangleIndexAttribute->setCount( data.triangles.size() /
sizeof( quint32 ) );
74 addAttribute( mTriangleIndexAttribute );
77 if ( !data.normals.isEmpty() )
80 mNormalsAttribute->setName( Qt3DQAttribute::defaultNormalAttributeName() );
81 mNormalsAttribute->setVertexBaseType( Qt3DQAttribute::Float );
82 mNormalsAttribute->setVertexSize( 3 );
83 mNormalsAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
84 mNormalsAttribute->setBuffer( mNormalsBuffer );
85 mNormalsBuffer->setData( data.normals );
86 mNormalsAttribute->setCount( data.normals.size() / ( 3 *
sizeof(
float ) ) );
87 addAttribute( mNormalsAttribute );
91QgsSingleColorPointCloud3DGeometry::QgsSingleColorPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
92 : QgsPointCloud3DGeometry( parent, data, byteStride )
94 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
95 mPositionAttribute->setBuffer( mVertexBuffer );
96 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
97 mPositionAttribute->setVertexSize( 3 );
98 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
99 mPositionAttribute->setByteOffset( 0 );
100 mPositionAttribute->setByteStride( mByteStride );
101 addAttribute( mPositionAttribute );
102 makeVertexBuffer( data );
105void QgsSingleColorPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
107 QByteArray vertexBufferData;
108 vertexBufferData.resize( data.positions.size() * mByteStride );
109 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
111 for (
int i = 0; i < data.positions.size(); ++i )
113 rawVertexArray[idx++] = data.positions.at( i ).x();
114 rawVertexArray[idx++] = data.positions.at( i ).y();
115 rawVertexArray[idx++] = data.positions.at( i ).z();
118 mVertexCount = data.positions.size();
119 mVertexBuffer->setData( vertexBufferData );
122QgsColorRampPointCloud3DGeometry::QgsColorRampPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
123 : QgsPointCloud3DGeometry( parent, data, byteStride )
125 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
126 mPositionAttribute->setBuffer( mVertexBuffer );
127 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
128 mPositionAttribute->setVertexSize( 3 );
129 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
130 mPositionAttribute->setByteOffset( 0 );
131 mPositionAttribute->setByteStride( mByteStride );
132 addAttribute( mPositionAttribute );
133 mParameterAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
134 mParameterAttribute->setBuffer( mVertexBuffer );
135 mParameterAttribute->setVertexBaseType( Qt3DQAttribute::Float );
136 mParameterAttribute->setVertexSize( 1 );
137 mParameterAttribute->setName(
"vertexParameter" );
138 mParameterAttribute->setByteOffset( 12 );
139 mParameterAttribute->setByteStride( mByteStride );
140 addAttribute( mParameterAttribute );
141 makeVertexBuffer( data );
144void QgsColorRampPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
146 QByteArray vertexBufferData;
147 vertexBufferData.resize( data.positions.size() * mByteStride );
148 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
150 Q_ASSERT( data.positions.size() == data.parameter.size() );
151 for (
int i = 0; i < data.positions.size(); ++i )
153 rawVertexArray[idx++] = data.positions.at( i ).x();
154 rawVertexArray[idx++] = data.positions.at( i ).y();
155 rawVertexArray[idx++] = data.positions.at( i ).z();
156 rawVertexArray[idx++] = data.parameter.at( i );
159 mVertexCount = data.positions.size();
160 mVertexBuffer->setData( vertexBufferData );
163QgsRGBPointCloud3DGeometry::QgsRGBPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
164 : QgsPointCloud3DGeometry( parent, data, byteStride )
166 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
167 mPositionAttribute->setBuffer( mVertexBuffer );
168 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
169 mPositionAttribute->setVertexSize( 3 );
170 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
171 mPositionAttribute->setByteOffset( 0 );
172 mPositionAttribute->setByteStride( mByteStride );
173 addAttribute( mPositionAttribute );
174 mColorAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
175 mColorAttribute->setBuffer( mVertexBuffer );
176 mColorAttribute->setVertexBaseType( Qt3DQAttribute::Float );
177 mColorAttribute->setVertexSize( 3 );
178 mColorAttribute->setName( QStringLiteral(
"vertexColor" ) );
179 mColorAttribute->setByteOffset( 12 );
180 mColorAttribute->setByteStride( mByteStride );
181 addAttribute( mColorAttribute );
182 makeVertexBuffer( data );
185void QgsRGBPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
187 QByteArray vertexBufferData;
188 vertexBufferData.resize( data.positions.size() * mByteStride );
189 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
191 Q_ASSERT( data.positions.size() == data.colors.size() );
192 for (
int i = 0; i < data.positions.size(); ++i )
194 rawVertexArray[idx++] = data.positions.at( i ).x();
195 rawVertexArray[idx++] = data.positions.at( i ).y();
196 rawVertexArray[idx++] = data.positions.at( i ).z();
197 rawVertexArray[idx++] = data.colors.at( i ).x();
198 rawVertexArray[idx++] = data.colors.at( i ).y();
199 rawVertexArray[idx++] = data.colors.at( i ).z();
201 mVertexCount = data.positions.size();
202 mVertexBuffer->setData( vertexBufferData );
205QgsClassificationPointCloud3DGeometry::QgsClassificationPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
206 : QgsPointCloud3DGeometry( parent, data, byteStride )
208 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
209 mPositionAttribute->setBuffer( mVertexBuffer );
210 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
211 mPositionAttribute->setVertexSize( 3 );
212 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
213 mPositionAttribute->setByteOffset( 0 );
214 mPositionAttribute->setByteStride( mByteStride );
215 addAttribute( mPositionAttribute );
216 mParameterAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
217 mParameterAttribute->setBuffer( mVertexBuffer );
218 mParameterAttribute->setVertexBaseType( Qt3DQAttribute::Float );
219 mParameterAttribute->setVertexSize( 1 );
220 mParameterAttribute->setName(
"vertexParameter" );
221 mParameterAttribute->setByteOffset( 12 );
222 mParameterAttribute->setByteStride( mByteStride );
223 addAttribute( mParameterAttribute );
224 mPointSizeAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
225 mPointSizeAttribute->setBuffer( mVertexBuffer );
226 mPointSizeAttribute->setVertexBaseType( Qt3DQAttribute::Float );
227 mPointSizeAttribute->setVertexSize( 1 );
228 mPointSizeAttribute->setName(
"vertexSize" );
229 mPointSizeAttribute->setByteOffset( 16 );
230 mPointSizeAttribute->setByteStride( mByteStride );
231 addAttribute( mPointSizeAttribute );
232 makeVertexBuffer( data );
235void QgsClassificationPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
237 QByteArray vertexBufferData;
238 vertexBufferData.resize( data.positions.size() * mByteStride );
239 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
241 Q_ASSERT( data.positions.size() == data.parameter.size() );
242 for (
int i = 0; i < data.positions.size(); ++i )
244 rawVertexArray[idx++] = data.positions.at( i ).x();
245 rawVertexArray[idx++] = data.positions.at( i ).y();
246 rawVertexArray[idx++] = data.positions.at( i ).z();
247 rawVertexArray[idx++] = data.parameter.at( i );
248 rawVertexArray[idx++] = data.pointSizes.at( i );
251 mVertexCount = data.positions.size();
252 mVertexBuffer->setData( vertexBufferData );
255QgsPointCloud3DSymbolHandler::QgsPointCloud3DSymbolHandler()
260void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const QgsPointCloud3DRenderContext &context,
const QgsPointCloud3DSymbolHandler::PointData &out,
bool selected )
264 if ( out.positions.empty() )
269 Qt3DRender::QGeometryRenderer *gr =
new Qt3DRender::QGeometryRenderer;
272 gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
273 gr->setVertexCount( out.triangles.size() /
sizeof( quint32 ) );
277 gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
278 gr->setVertexCount( out.positions.count() );
280 gr->setGeometry( geom );
283 Qt3DCore::QTransform *tr =
new Qt3DCore::QTransform;
286 Qt3DRender::QMaterial *mat =
new Qt3DRender::QMaterial;
290 Qt3DRender::QShaderProgram *shaderProgram =
new Qt3DRender::QShaderProgram( mat );
291 shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/pointcloud.vert" ) ) ) );
292 shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/pointcloud.frag" ) ) ) );
294 Qt3DRender::QRenderPass *renderPass =
new Qt3DRender::QRenderPass( mat );
295 renderPass->setShaderProgram( shaderProgram );
297 if ( out.triangles.isEmpty() )
299 Qt3DRender::QPointSize *pointSize =
new Qt3DRender::QPointSize( renderPass );
300 pointSize->setSizeMode( Qt3DRender::QPointSize::Programmable );
301 renderPass->addRenderState( pointSize );
305 Qt3DRender::QFilterKey *filterKey =
new Qt3DRender::QFilterKey;
306 filterKey->setName( QStringLiteral(
"renderingStyle" ) );
307 filterKey->setValue(
"forward" );
309 Qt3DRender::QTechnique *technique =
new Qt3DRender::QTechnique;
310 technique->addRenderPass( renderPass );
311 technique->addFilterKey( filterKey );
312 technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
313 technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
314 technique->graphicsApiFilter()->setMajorVersion( 3 );
315 technique->graphicsApiFilter()->setMinorVersion( 1 );
316 technique->addParameter(
new Qt3DRender::QParameter(
"triangulate", !out.triangles.isEmpty() ) );
318 Qt3DRender::QEffect *eff =
new Qt3DRender::QEffect;
319 eff->addTechnique( technique );
320 mat->setEffect( eff );
323 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
324 entity->addComponent( gr );
325 entity->addComponent( tr );
326 entity->addComponent( mat );
327 entity->setParent( parent );
336 bool hasColorData = !outNormal.colors.empty();
337 bool hasParameterData = !outNormal.parameter.empty();
340 std::vector<double> vertices( outNormal.positions.size() * 2 );
342 for (
int i = 0; i < outNormal.positions.size(); ++i )
344 vertices[idx++] = outNormal.positions.at( i ).x();
345 vertices[idx++] = outNormal.positions.at( i ).z();
351 int properPointsCount = outNormal.positions.count();
352 while ( parentNode.
d() >= 0 )
354 processNode( pc, parentNode, context );
358 PointData filteredExtraPointData;
360 double span = pc->
span();
363 double extraBoxFactor = 16 / span;
364 double extraX = extraBoxFactor * bbox.
xExtent();
365 double extraZ = extraBoxFactor * bbox.
zExtent();
368 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 );
370 for (
int i = properPointsCount; i < outNormal.positions.count(); ++i )
372 const QVector3D pos = outNormal.positions.at( i );
373 if ( extendedBBox.intersects( pos.x(), pos.y(), pos.z() ) )
375 filteredExtraPointData.positions.append( pos );
376 vertices.push_back( pos.x() );
377 vertices.push_back( pos.z() );
380 filteredExtraPointData.colors.append( outNormal.colors.at( i ) );
381 if ( hasParameterData )
382 filteredExtraPointData.parameter.append( outNormal.parameter.at( i ) );
386 outNormal.positions.resize( properPointsCount );
388 outNormal.colors.resize( properPointsCount );
389 if ( hasParameterData )
390 outNormal.parameter.resize( properPointsCount );
392 outNormal.positions.append( filteredExtraPointData.positions );
393 outNormal.colors.append( filteredExtraPointData.colors );
394 outNormal.parameter.append( filteredExtraPointData.parameter );
399void QgsPointCloud3DSymbolHandler::calculateNormals(
const std::vector<size_t> &triangles )
401 QVector<QVector3D> normals( outNormal.positions.count(), QVector3D( 0.0, 0.0, 0.0 ) );
402 for (
size_t i = 0; i < triangles.size(); i += 3 )
404 QVector<QVector3D> triangleVertices( 3 );
405 for (
size_t j = 0; j < 3; ++j )
407 size_t vertIndex = triangles.at( i + j );
408 triangleVertices[j] = outNormal.positions.at( vertIndex );
411 for (
size_t j = 0; j < 3; ++j )
412 normals[triangles.at( i + j )] += QVector3D::crossProduct(
413 triangleVertices.at( 1 ) - triangleVertices.at( 0 ),
414 triangleVertices.at( 2 ) - triangleVertices.at( 0 ) );
418 outNormal.normals.resize( ( outNormal.positions.count() ) *
sizeof(
float ) * 3 );
419 float *normPtr =
reinterpret_cast<float *
>( outNormal.normals.data() );
420 for (
int i = 0; i < normals.size(); ++i )
422 QVector3D normal = normals.at( i );
423 normal = normal.normalized();
425 *normPtr++ = normal.x();
426 *normPtr++ = normal.y();
427 *normPtr++ = normal.z();
433 outNormal.triangles.resize( triangleIndexes.size() *
sizeof( quint32 ) );
434 quint32 *indexPtr =
reinterpret_cast<quint32 *
>( outNormal.triangles.data() );
435 size_t effective = 0;
442 for (
size_t i = 0; i < triangleIndexes.size(); i += 3 )
444 bool atLeastOneInBox =
false;
445 bool horizontalSkip =
false;
446 bool verticalSkip =
false;
447 for (
size_t j = 0; j < 3; j++ )
449 QVector3D pos = outNormal.positions.at( triangleIndexes.at( i + j ) );
450 atLeastOneInBox |= bbox.
intersects( pos.x(), pos.y(), pos.z() );
452 if ( verticalFilter || horizontalFilter )
454 const QVector3D pos2 = outNormal.positions.at( triangleIndexes.at( i + ( j + 1 ) % 3 ) );
456 if ( verticalFilter )
457 verticalSkip |= std::fabs( pos.y() - pos2.y() ) > verticalThreshold;
459 if ( horizontalFilter && ! verticalSkip )
462 horizontalSkip |= sqrt( std::pow( pos.x() - pos2.x(), 2 ) +
463 std::pow( pos.z() - pos2.z(), 2 ) ) > horizontalThreshold;
466 if ( horizontalSkip || verticalSkip )
470 if ( atLeastOneInBox && !horizontalSkip && !verticalSkip )
472 for (
size_t j = 0; j < 3; j++ )
474 size_t vertIndex = triangleIndexes.at( i + j );
475 *indexPtr++ = quint32( vertIndex );
481 if ( effective != 0 )
483 outNormal.triangles.resize( effective * 3 *
sizeof( quint32 ) );
487 outNormal.triangles.clear();
488 outNormal.normals.clear();
494 if ( outNormal.positions.isEmpty() )
498 std::unique_ptr<delaunator::Delaunator> triangulation;
501 std::vector<double> vertices = getVertices( pc, n, context, bbox );
502 triangulation.reset(
new delaunator::Delaunator( vertices ) );
504 catch ( std::exception &e )
508 outNormal = PointData();
509 processNode( pc, n, context );
513 const std::vector<size_t> &triangleIndexes = triangulation->triangles;
515 calculateNormals( triangleIndexes );
516 filterTriangles( triangleIndexes, context, bbox );
521 std::unique_ptr<QgsPointCloudBlock> block;
531 bool loopAborted =
false;
550QgsSingleColorPointCloud3DSymbolHandler::QgsSingleColorPointCloud3DSymbolHandler()
551 : QgsPointCloud3DSymbolHandler()
572 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
576 const char *ptr = block->data();
577 const int count = block->pointCount();
578 const std::size_t recordSize = block->attributes().pointRecordSize();
584 bool alreadyPrintedDebug =
false;
586 for (
int i = 0; i < count; ++i )
591 const qint32 ix = *( qint32 * )( ptr + i * recordSize + 0 );
592 const qint32 iy = *( qint32 * )( ptr + i * recordSize + 4 );
593 const qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
595 double x = blockOffset.
x() + blockScale.
x() * ix;
596 double y = blockOffset.
y() + blockScale.
y() * iy;
597 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
604 if ( !alreadyPrintedDebug )
606 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
607 alreadyPrintedDebug =
true;
611 outNormal.positions.push_back( QVector3D(
static_cast<float>( point.
x() ),
static_cast<float>( point.
y() ),
static_cast<float>( point.
z() ) ) );
617 makeEntity( parent, context, outNormal,
false );
620Qt3DQGeometry *QgsSingleColorPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
622 return new QgsSingleColorPointCloud3DGeometry( parent, data, byteStride );
625QgsColorRampPointCloud3DSymbolHandler::QgsColorRampPointCloud3DSymbolHandler()
626 : QgsPointCloud3DSymbolHandler()
640 const int xOffset = 0;
647 QString attributeName;
648 bool attrIsX =
false;
649 bool attrIsY =
false;
650 bool attrIsZ =
false;
652 int attributeOffset = 0;
656 bool alreadyPrintedDebug =
false;
664 if ( symbol->
attribute() == QLatin1String(
"X" ) )
668 else if ( symbol->
attribute() == QLatin1String(
"Y" ) )
672 else if ( symbol->
attribute() == QLatin1String(
"Z" ) )
681 attributeType = attr->
type();
682 attributeName = attr->
name();
689 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
695 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
699 const char *ptr = block->data();
700 const int count = block->pointCount();
701 const std::size_t recordSize = block->attributes().pointRecordSize();
706 for (
int i = 0; i < count; ++i )
711 const qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
712 const qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
713 const qint32 iz = *( qint32 * )( ptr + i * recordSize + zOffset );
715 double x = blockOffset.
x() + blockScale.
x() * ix;
716 double y = blockOffset.
y() + blockScale.
y() * iy;
717 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
724 if ( !alreadyPrintedDebug )
726 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
727 alreadyPrintedDebug =
true;
731 outNormal.positions.push_back( QVector3D(
static_cast<float>( point.
x() ),
static_cast<float>( point.
y() ),
static_cast<float>( point.
z() ) ) );
734 outNormal.parameter.push_back( x );
736 outNormal.parameter.push_back( y );
738 outNormal.parameter.push_back( z );
742 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
743 outNormal.parameter.push_back( iParam );
750 makeEntity( parent, context, outNormal,
false );
753Qt3DQGeometry *QgsColorRampPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
755 return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );
758QgsRGBPointCloud3DSymbolHandler::QgsRGBPointCloud3DSymbolHandler()
759 : QgsPointCloud3DSymbolHandler()
800 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
804 const char *ptr = block->data();
805 const int count = block->pointCount();
806 const std::size_t recordSize = block->attributes().pointRecordSize();
813 bool alreadyPrintedDebug =
false;
826 for (
int i = 0; i < count; ++i )
831 const qint32 ix = *( qint32 * )( ptr + i * recordSize + 0 );
832 const qint32 iy = *( qint32 * )( ptr + i * recordSize + 4 );
833 const qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
834 double x = blockOffset.
x() + blockScale.
x() * ix;
835 double y = blockOffset.
y() + blockScale.
y() * iy;
836 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
843 if ( !alreadyPrintedDebug )
845 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
846 alreadyPrintedDebug =
true;
851 QVector3D color( 0.0f, 0.0f, 0.0f );
853 context.
getAttribute( ptr, i * recordSize + redOffset, redType, ir );
854 context.
getAttribute( ptr, i * recordSize + greenOffset, greenType, ig );
855 context.
getAttribute( ptr, i * recordSize + blueOffset, blueType, ib );
866 if ( useRedContrastEnhancement )
870 if ( useGreenContrastEnhancement )
874 if ( useBlueContrastEnhancement )
879 color.setX( ir / 255.0f );
880 color.setY( ig / 255.0f );
881 color.setZ( ib / 255.0f );
883 outNormal.positions.push_back( QVector3D(
static_cast<float>( point.
x() ),
static_cast<float>( point.
y() ),
static_cast<float>( point.
z() ) ) );
884 outNormal.colors.push_back( color );
890 makeEntity( parent, context, outNormal,
false );
893Qt3DQGeometry *QgsRGBPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
895 return new QgsRGBPointCloud3DGeometry( parent, data, byteStride );
898QgsClassificationPointCloud3DSymbolHandler::QgsClassificationPointCloud3DSymbolHandler()
899 : QgsPointCloud3DSymbolHandler()
913 const int xOffset = 0;
920 QString attributeName;
921 bool attrIsX =
false;
922 bool attrIsY =
false;
923 bool attrIsZ =
false;
925 int attributeOffset = 0;
932 if ( symbol->
attribute() == QLatin1String(
"X" ) )
936 else if ( symbol->
attribute() == QLatin1String(
"Y" ) )
940 else if ( symbol->
attribute() == QLatin1String(
"Z" ) )
949 attributeType = attr->
type();
950 attributeName = attr->
name();
957 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
963 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
967 const char *ptr = block->data();
968 const int count = block->pointCount();
969 const std::size_t recordSize = block->attributes().pointRecordSize();
976 bool alreadyPrintedDebug =
false;
978 QList<QgsPointCloudCategory> categoriesList = symbol->
categoriesList();
979 QVector<int> categoriesValues;
980 QHash<int, double> categoriesPointSizes;
983 categoriesValues.push_back(
c.value() );
984 categoriesPointSizes.insert(
c.value(),
c.pointSize() > 0 ?
c.pointSize() :
985 context.symbol() ? context.symbol()->pointSize() : 1.0 );
989 for (
int i = 0; i < count; ++i )
994 const qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
995 const qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
996 const qint32 iz = *( qint32 * )( ptr + i * recordSize + zOffset );
998 double x = blockOffset.
x() + blockScale.
x() * ix;
999 double y = blockOffset.
y() + blockScale.
y() * iy;
1000 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
1007 if ( !alreadyPrintedDebug )
1009 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
1010 alreadyPrintedDebug =
true;
1014 float iParam = 0.0f;
1022 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
1024 if ( filteredOutValues.contains( (
int ) iParam ) ||
1025 ! categoriesValues.contains( (
int ) iParam ) )
1027 outNormal.positions.push_back( QVector3D(
static_cast<float>( point.
x() ),
static_cast<float>( point.
y() ),
static_cast<float>( point.
z() ) ) );
1030 float iParam2 = categoriesValues.indexOf( (
int )iParam ) + 1;
1031 outNormal.parameter.push_back( iParam2 );
1032 outNormal.pointSizes.push_back( categoriesPointSizes.value( (
int ) iParam ) );
1038 makeEntity( parent, context, outNormal,
false );
1041Qt3DQGeometry *QgsClassificationPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
1043 return new QgsClassificationPointCloud3DGeometry( parent, data, byteStride );
Represents a indexed point cloud node in octree.
IndexedPointCloudNode parentNode() const
Returns the parent of the node.
float xExtent() const
Returns box width in X axis.
float zExtent() const
Returns box width in Z axis.
bool intersects(const QgsAABB &other) const
Determines whether the box intersects some other axis aligned box.
QgsPointCloudCategoryList categoriesList() const
Returns the list of categories of the classification.
QString attribute() const
Returns the attribute used to select the color of the point cloud.
QString attribute() const
Returns the attribute used to select the color of the point cloud.
Manipulates raster or point cloud pixel values so that they enhanceContrast or clip into a specified ...
@ NoEnhancement
Default color scaling algorithm, no scaling is applied.
bool isValueInDisplayableRange(double value)
Returns true if a pixel value is in displayable range, false if pixel is outside of range (i....
int enhanceContrast(double value)
Applies the contrast enhancement to a value.
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
Custom exception class for Coordinate Reference System related exceptions.
void canceled()
Internal routines can connect to this signal if they use event loop.
Encapsulates the render context for a 3D point cloud rendering operation.
QgsRectangle extent() const
Returns the 3D scene's extent in layer crs.
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...
QSet< int > getFilteredOutValues() const
Returns a set containing the filtered out values.
QgsPointCloud3DSymbol * symbol() const
Returns the symbol used for rendering the point cloud.
double zValueScale() const
Returns any constant scaling factor which must be applied to z values taken from the point cloud inde...
QgsFeedback * feedback() const
Returns the feedback object used to cancel rendering and check if rendering was canceled.
QgsPointCloudAttributeCollection attributes() const
Returns the attributes associated with the rendered block.
bool isCanceled() const
Returns true if the rendering is canceled.
QgsCoordinateTransform coordinateTransform() const
Returns the coordinate transform used to transform points from layer CRS to the map CRS.
double zValueFixedOffset() const
Returns any constant offset which must be applied to z values taken from the point cloud index.
bool verticalTriangleFilter() const
Returns whether triangles are filtered by vertical height for rendering.
float verticalFilterThreshold() const
Returns the threshold vertical height value for filtering triangles.
virtual unsigned int byteStride()=0
Returns the byte stride for the geometries used to for the vertex buffer.
float horizontalFilterThreshold() const
Returns the threshold horizontal size value for filtering triangles.
virtual void fillMaterial(Qt3DRender::QMaterial *material)=0SIP_SKIP
Used to fill material object with necessary QParameters (and consequently opengl uniforms)
bool renderAsTriangles() const
Returns whether points are triangulated to render solid surface.
bool horizontalTriangleFilter() const
Returns whether triangles are filtered by horizontal size for rendering.
Collection of point cloud attributes.
void push_back(const QgsPointCloudAttribute &attribute)
Adds extra attribute.
int pointRecordSize() const
Returns total size of record.
const QgsPointCloudAttribute * find(const QString &attributeName, int &offset) const
Finds the attribute with the name.
Attribute for point cloud data pair of name and size in bytes.
DataType
Systems of unit measurement.
QString name() const
Returns name of the attribute.
DataType type() const
Returns the data type.
Base class for handling loading QgsPointCloudBlock asynchronously.
void finished()
Emitted when the request processing has finished.
std::unique_ptr< QgsPointCloudBlock > takeBlock()
Returns the requested block.
Represents an individual category (class) from a QgsPointCloudClassifiedRenderer.
Represents a indexed point clouds data in octree.
int span() const
Returns the number of points in one direction in a single node.
virtual qint64 nodePointCount(const IndexedPointCloudNode &n) const
Returns the number of points of a given node n.
virtual QgsPointCloudBlockRequest * asyncNodeData(const IndexedPointCloudNode &n, const QgsPointCloudRequest &request)=0
Returns a handle responsible for loading a node data block.
@ Remote
Remote means it's loaded through a protocol like HTTP.
@ Local
Local means the source is a local file on the machine.
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...
virtual std::unique_ptr< QgsPointCloudBlock > nodeData(const IndexedPointCloudNode &n, const QgsPointCloudRequest &request)=0
Returns node data block.
Point cloud data request.
void setFilterRect(QgsRectangle extent)
Sets the rectangle from which points will be taken, in point cloud's crs.
void setAttributes(const QgsPointCloudAttributeCollection &attributes)
Set attributes filter in the request.
QString blueAttribute() const
Returns the attribute to use for the blue channel.
QString greenAttribute() const
Returns the attribute to use for the green channel.
QgsContrastEnhancement * blueContrastEnhancement()
Returns the contrast enhancement to use for the blue channel.
QString redAttribute() const
Returns the attribute to use for the red channel.
QgsContrastEnhancement * greenContrastEnhancement()
Returns the contrast enhancement to use for the green channel.
QgsContrastEnhancement * redContrastEnhancement()
Returns the contrast enhancement to use for the red channel.
Class for storage of 3D vectors similar to QVector3D, with the difference that it uses double precisi...
double y() const
Returns Y coordinate.
double z() const
Returns Z coordinate.
double x() const
Returns X coordinate.
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
Qt3DCore::QAttribute Qt3DQAttribute
Qt3DCore::QBuffer Qt3DQBuffer
Qt3DCore::QGeometry Qt3DQGeometry
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)