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;
612 outNormal.positions.push_back( QVector3D( p.
x(), p.
y(), p.
z() ) );
618 makeEntity( parent, context, outNormal,
false );
621Qt3DQGeometry *QgsSingleColorPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
623 return new QgsSingleColorPointCloud3DGeometry( parent, data, byteStride );
626QgsColorRampPointCloud3DSymbolHandler::QgsColorRampPointCloud3DSymbolHandler()
627 : QgsPointCloud3DSymbolHandler()
641 const int xOffset = 0;
648 QString attributeName;
649 bool attrIsX =
false;
650 bool attrIsY =
false;
651 bool attrIsZ =
false;
653 int attributeOffset = 0;
657 bool alreadyPrintedDebug =
false;
665 if ( symbol->
attribute() == QLatin1String(
"X" ) )
669 else if ( symbol->
attribute() == QLatin1String(
"Y" ) )
673 else if ( symbol->
attribute() == QLatin1String(
"Z" ) )
682 attributeType = attr->
type();
683 attributeName = attr->
name();
690 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
696 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
700 const char *ptr = block->data();
701 const int count = block->pointCount();
702 const std::size_t recordSize = block->attributes().pointRecordSize();
707 for (
int i = 0; i < count; ++i )
712 const qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
713 const qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
714 const qint32 iz = *( qint32 * )( ptr + i * recordSize + zOffset );
716 double x = blockOffset.
x() + blockScale.
x() * ix;
717 double y = blockOffset.
y() + blockScale.
y() * iy;
718 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
725 if ( !alreadyPrintedDebug )
727 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
728 alreadyPrintedDebug =
true;
732 point = context.map().mapToWorldCoordinates( point );
733 outNormal.positions.push_back( QVector3D( point.x(), point.y(), point.z() ) );
736 outNormal.parameter.push_back( x );
738 outNormal.parameter.push_back( y );
740 outNormal.parameter.push_back( z );
744 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
745 outNormal.parameter.push_back( iParam );
752 makeEntity( parent, context, outNormal,
false );
755Qt3DQGeometry *QgsColorRampPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
757 return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );
760QgsRGBPointCloud3DSymbolHandler::QgsRGBPointCloud3DSymbolHandler()
761 : QgsPointCloud3DSymbolHandler()
802 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
806 const char *ptr = block->data();
807 const int count = block->pointCount();
808 const std::size_t recordSize = block->attributes().pointRecordSize();
815 bool alreadyPrintedDebug =
false;
828 for (
int i = 0; i < count; ++i )
833 const qint32 ix = *( qint32 * )( ptr + i * recordSize + 0 );
834 const qint32 iy = *( qint32 * )( ptr + i * recordSize + 4 );
835 const qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
836 double x = blockOffset.
x() + blockScale.
x() * ix;
837 double y = blockOffset.
y() + blockScale.
y() * iy;
838 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
845 if ( !alreadyPrintedDebug )
847 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
848 alreadyPrintedDebug =
true;
852 const QgsVector3D p = context.map().mapToWorldCoordinates( point );
854 QVector3D color( 0.0f, 0.0f, 0.0f );
856 context.
getAttribute( ptr, i * recordSize + redOffset, redType, ir );
857 context.
getAttribute( ptr, i * recordSize + greenOffset, greenType, ig );
858 context.
getAttribute( ptr, i * recordSize + blueOffset, blueType, ib );
869 if ( useRedContrastEnhancement )
873 if ( useGreenContrastEnhancement )
877 if ( useBlueContrastEnhancement )
882 color.setX( ir / 255.0f );
883 color.setY( ig / 255.0f );
884 color.setZ( ib / 255.0f );
886 outNormal.positions.push_back( QVector3D( p.
x(), p.
y(), p.
z() ) );
887 outNormal.colors.push_back( color );
893 makeEntity( parent, context, outNormal,
false );
896Qt3DQGeometry *QgsRGBPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
898 return new QgsRGBPointCloud3DGeometry( parent, data, byteStride );
901QgsClassificationPointCloud3DSymbolHandler::QgsClassificationPointCloud3DSymbolHandler()
902 : QgsPointCloud3DSymbolHandler()
916 const int xOffset = 0;
923 QString attributeName;
924 bool attrIsX =
false;
925 bool attrIsY =
false;
926 bool attrIsZ =
false;
928 int attributeOffset = 0;
935 if ( symbol->
attribute() == QLatin1String(
"X" ) )
939 else if ( symbol->
attribute() == QLatin1String(
"Y" ) )
943 else if ( symbol->
attribute() == QLatin1String(
"Z" ) )
952 attributeType = attr->
type();
953 attributeName = attr->
name();
960 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
966 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
970 const char *ptr = block->data();
971 const int count = block->pointCount();
972 const std::size_t recordSize = block->attributes().pointRecordSize();
979 bool alreadyPrintedDebug =
false;
981 QList<QgsPointCloudCategory> categoriesList = symbol->
categoriesList();
982 QVector<int> categoriesValues;
983 QHash<int, double> categoriesPointSizes;
986 categoriesValues.push_back(
c.value() );
987 categoriesPointSizes.insert(
c.value(),
c.pointSize() > 0 ?
c.pointSize() :
988 context.symbol() ? context.symbol()->pointSize() : 1.0 );
992 for (
int i = 0; i < count; ++i )
997 const qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
998 const qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
999 const qint32 iz = *( qint32 * )( ptr + i * recordSize + zOffset );
1001 double x = blockOffset.
x() + blockScale.
x() * ix;
1002 double y = blockOffset.
y() + blockScale.
y() * iy;
1003 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
1010 if ( !alreadyPrintedDebug )
1012 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
1013 alreadyPrintedDebug =
true;
1017 const QgsVector3D p = context.map().mapToWorldCoordinates( point );
1018 float iParam = 0.0f;
1026 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
1028 if ( filteredOutValues.contains( (
int ) iParam ) ||
1029 ! categoriesValues.contains( (
int ) iParam ) )
1031 outNormal.positions.push_back( QVector3D( p.
x(), p.
y(), p.
z() ) );
1034 float iParam2 = categoriesValues.indexOf( (
int )iParam ) + 1;
1035 outNormal.parameter.push_back( iParam2 );
1036 outNormal.pointSizes.push_back( categoriesPointSizes.value( (
int ) iParam ) );
1042 makeEntity( parent, context, outNormal,
false );
1045Qt3DQGeometry *QgsClassificationPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
1047 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)