31 #include <Qt3DRender/QGeometryRenderer>
32 #include <Qt3DRender/QAttribute>
33 #include <Qt3DRender/QTechnique>
34 #include <Qt3DRender/QShaderProgram>
35 #include <Qt3DRender/QGraphicsApiFilter>
36 #include <Qt3DRender/QEffect>
40 #include <delaunator.hpp>
42 QgsPointCloud3DGeometry::QgsPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
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 )
52 if ( !data.triangles.isEmpty() )
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 );
63 if ( !data.normals.isEmpty() )
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 );
77 QgsSingleColorPointCloud3DGeometry::QgsSingleColorPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
78 : QgsPointCloud3DGeometry( parent, data, byteStride )
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 );
91 void QgsSingleColorPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
93 QByteArray vertexBufferData;
94 vertexBufferData.resize( data.positions.size() * mByteStride );
95 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
97 for (
int i = 0; i < data.positions.size(); ++i )
99 rawVertexArray[idx++] = data.positions.at( i ).x();
100 rawVertexArray[idx++] = data.positions.at( i ).y();
101 rawVertexArray[idx++] = data.positions.at( i ).z();
104 mVertexCount = data.positions.size();
105 mVertexBuffer->setData( vertexBufferData );
108 QgsColorRampPointCloud3DGeometry::QgsColorRampPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
109 : QgsPointCloud3DGeometry( parent, data, byteStride )
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 );
130 void QgsColorRampPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
132 QByteArray vertexBufferData;
133 vertexBufferData.resize( data.positions.size() * mByteStride );
134 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
136 Q_ASSERT( data.positions.size() == data.parameter.size() );
137 for (
int i = 0; i < data.positions.size(); ++i )
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 );
145 mVertexCount = data.positions.size();
146 mVertexBuffer->setData( vertexBufferData );
149 QgsRGBPointCloud3DGeometry::QgsRGBPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
150 : QgsPointCloud3DGeometry( parent, data, byteStride )
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 );
171 void QgsRGBPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
173 QByteArray vertexBufferData;
174 vertexBufferData.resize( data.positions.size() * mByteStride );
175 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
177 Q_ASSERT( data.positions.size() == data.colors.size() );
178 for (
int i = 0; i < data.positions.size(); ++i )
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();
187 mVertexCount = data.positions.size();
188 mVertexBuffer->setData( vertexBufferData );
191 QgsPointCloud3DSymbolHandler::QgsPointCloud3DSymbolHandler()
196 void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const QgsPointCloud3DRenderContext &context,
const QgsPointCloud3DSymbolHandler::PointData &out,
bool selected )
200 if ( out.positions.empty() )
204 Qt3DRender::QGeometry *geom = makeGeometry( parent, out, context.
symbol()->
byteStride() );
205 Qt3DRender::QGeometryRenderer *gr =
new Qt3DRender::QGeometryRenderer;
208 gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
209 gr->setVertexCount( out.triangles.size() /
sizeof( quint32 ) );
213 gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
214 gr->setVertexCount( out.positions.count() );
216 gr->setGeometry( geom );
219 Qt3DCore::QTransform *tr =
new Qt3DCore::QTransform;
222 Qt3DRender::QMaterial *mat =
new Qt3DRender::QMaterial;
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" ) ) ) );
230 Qt3DRender::QRenderPass *renderPass =
new Qt3DRender::QRenderPass( mat );
231 renderPass->setShaderProgram( shaderProgram );
233 if ( out.triangles.isEmpty() )
235 Qt3DRender::QPointSize *pointSize =
new Qt3DRender::QPointSize( renderPass );
236 pointSize->setSizeMode( Qt3DRender::QPointSize::Programmable );
238 renderPass->addRenderState( pointSize );
242 Qt3DRender::QFilterKey *filterKey =
new Qt3DRender::QFilterKey;
243 filterKey->setName( QStringLiteral(
"renderingStyle" ) );
244 filterKey->setValue(
"forward" );
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() ) );
255 Qt3DRender::QEffect *eff =
new Qt3DRender::QEffect;
256 eff->addTechnique( technique );
257 mat->setEffect( eff );
260 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
261 entity->addComponent( gr );
262 entity->addComponent( tr );
263 entity->addComponent( mat );
264 entity->setParent( parent );
273 bool hasColorData = !outNormal.colors.empty();
274 bool hasParameterData = !outNormal.parameter.empty();
277 std::vector<double> vertices( outNormal.positions.size() * 2 );
279 for (
int i = 0; i < outNormal.positions.size(); ++i )
281 vertices[idx++] = outNormal.positions.at( i ).x();
282 vertices[idx++] = outNormal.positions.at( i ).z();
288 int properPointsCount = outNormal.positions.count();
289 while ( parentNode.
d() >= 0 )
291 processNode( pc, parentNode, context );
295 PointData filteredExtraPointData;
297 double span = pc->
span();
300 double extraBoxFactor = 16 / span;
301 double extraX = extraBoxFactor * bbox.
xExtent();
302 double extraZ = extraBoxFactor * bbox.
zExtent();
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 );
307 for (
int i = properPointsCount; i < outNormal.positions.count(); ++i )
309 const QVector3D pos = outNormal.positions.at( i );
310 if ( extendedBBox.intersects( pos.x(), pos.y(), pos.z() ) )
312 filteredExtraPointData.positions.append( pos );
313 vertices.push_back( pos.x() );
314 vertices.push_back( pos.z() );
317 filteredExtraPointData.colors.append( outNormal.colors.at( i ) );
318 if ( hasParameterData )
319 filteredExtraPointData.parameter.append( outNormal.parameter.at( i ) );
323 outNormal.positions.resize( properPointsCount );
325 outNormal.colors.resize( properPointsCount );
326 if ( hasParameterData )
327 outNormal.parameter.resize( properPointsCount );
329 outNormal.positions.append( filteredExtraPointData.positions );
330 outNormal.colors.append( filteredExtraPointData.colors );
331 outNormal.parameter.append( filteredExtraPointData.parameter );
336 void QgsPointCloud3DSymbolHandler::calculateNormals(
const std::vector<size_t> &triangles )
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 )
341 QVector<QVector3D> triangleVertices( 3 );
342 for (
size_t j = 0; j < 3; ++j )
344 size_t vertIndex = triangles.at( i + j );
345 triangleVertices[j] = outNormal.positions.at( vertIndex );
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 ) );
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 )
359 QVector3D normal = normals.at( i );
360 normal = normal.normalized();
362 *normPtr++ = normal.x();
363 *normPtr++ = normal.y();
364 *normPtr++ = normal.z();
370 outNormal.triangles.resize( triangleIndexes.size() *
sizeof( quint32 ) );
371 quint32 *indexPtr =
reinterpret_cast<quint32 *
>( outNormal.triangles.data() );
372 size_t effective = 0;
379 for (
size_t i = 0; i < triangleIndexes.size(); i += 3 )
381 bool atLeastOneInBox =
false;
382 bool horizontalSkip =
false;
383 bool verticalSkip =
false;
384 for (
size_t j = 0; j < 3; j++ )
386 QVector3D pos = outNormal.positions.at( triangleIndexes.at( i + j ) );
387 atLeastOneInBox |= bbox.
intersects( pos.x(), pos.y(), pos.z() );
389 if ( verticalFilter || horizontalFilter )
391 const QVector3D pos2 = outNormal.positions.at( triangleIndexes.at( i + ( j + 1 ) % 3 ) );
393 if ( verticalFilter )
394 verticalSkip |= std::fabs( pos.y() - pos2.y() ) > verticalThreshold;
396 if ( horizontalFilter && ! verticalSkip )
399 horizontalSkip |= sqrt( std::pow( pos.x() - pos2.x(), 2 ) +
400 std::pow( pos.z() - pos2.z(), 2 ) ) > horizontalThreshold;
403 if ( horizontalSkip || verticalSkip )
407 if ( atLeastOneInBox && !horizontalSkip && !verticalSkip )
409 for (
size_t j = 0; j < 3; j++ )
411 size_t vertIndex = triangleIndexes.at( i + j );
412 *indexPtr++ = quint32( vertIndex );
418 if ( effective != 0 )
420 outNormal.triangles.resize( effective * 3 *
sizeof( quint32 ) );
424 outNormal.triangles.clear();
425 outNormal.normals.clear();
431 if ( outNormal.positions.isEmpty() )
435 std::unique_ptr<delaunator::Delaunator> triangulation;
438 std::vector<double> vertices = getVertices( pc, n, context, bbox );
439 triangulation.reset(
new delaunator::Delaunator( vertices ) );
441 catch ( std::exception &e )
445 outNormal = PointData();
446 processNode( pc, n, context );
450 const std::vector<size_t> &triangleIndexes = triangulation->triangles;
452 calculateNormals( triangleIndexes );
453 filterTriangles( triangleIndexes, context, bbox );
459 if ( pc->
accessType() == QgsPointCloudIndex::AccessType::Local )
463 else if ( pc->
accessType() == QgsPointCloudIndex::AccessType::Remote )
465 bool loopAborted =
false;
477 block = req->
block();
484 QgsSingleColorPointCloud3DSymbolHandler::QgsSingleColorPointCloud3DSymbolHandler()
485 : QgsPointCloud3DSymbolHandler()
505 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
509 const char *ptr = block->
data();
517 bool alreadyPrintedDebug =
false;
519 for (
int i = 0; i < count; ++i )
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 );
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;
537 if ( !alreadyPrintedDebug )
539 QgsDebugMsg( QStringLiteral(
"Error transforming point coordinate" ) );
540 alreadyPrintedDebug =
true;
545 outNormal.positions.push_back( QVector3D( p.
x(), p.
y(), p.
z() ) );
551 makeEntity( parent, context, outNormal,
false );
554 Qt3DRender::QGeometry *QgsSingleColorPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
556 return new QgsSingleColorPointCloud3DGeometry( parent, data, byteStride );
559 QgsColorRampPointCloud3DSymbolHandler::QgsColorRampPointCloud3DSymbolHandler()
560 : QgsPointCloud3DSymbolHandler()
574 const int xOffset = 0;
581 QString attributeName;
582 bool attrIsX =
false;
583 bool attrIsY =
false;
584 bool attrIsZ =
false;
586 int attributeOffset = 0;
590 bool alreadyPrintedDebug =
false;
598 if ( symbol->
attribute() == QLatin1String(
"X" ) )
602 else if ( symbol->
attribute() == QLatin1String(
"Y" ) )
606 else if ( symbol->
attribute() == QLatin1String(
"Z" ) )
615 attributeType = attr->
type();
616 attributeName = attr->
name();
623 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
628 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
632 const char *ptr = block->
data();
639 for (
int i = 0; i < count; ++i )
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 );
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;
657 if ( !alreadyPrintedDebug )
659 QgsDebugMsg( QStringLiteral(
"Error transforming point coordinate" ) );
660 alreadyPrintedDebug =
true;
664 point = context.map().mapToWorldCoordinates( point );
665 outNormal.positions.push_back( QVector3D( point.x(), point.y(), point.z() ) );
668 outNormal.parameter.push_back( x );
670 outNormal.parameter.push_back( y );
672 outNormal.parameter.push_back( z );
676 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
677 outNormal.parameter.push_back( iParam );
684 makeEntity( parent, context, outNormal,
false );
687 Qt3DRender::QGeometry *QgsColorRampPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
689 return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );
692 QgsRGBPointCloud3DSymbolHandler::QgsRGBPointCloud3DSymbolHandler()
693 : QgsPointCloud3DSymbolHandler()
733 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
737 const char *ptr = block->
data();
746 bool alreadyPrintedDebug =
false;
759 for (
int i = 0; i < count; ++i )
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;
776 if ( !alreadyPrintedDebug )
778 QgsDebugMsg( QStringLiteral(
"Error transforming point coordinate" ) );
779 alreadyPrintedDebug =
true;
783 const QgsVector3D p = context.map().mapToWorldCoordinates( point );
785 QVector3D color( 0.0f, 0.0f, 0.0f );
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 );
800 if ( useRedContrastEnhancement )
804 if ( useGreenContrastEnhancement )
808 if ( useBlueContrastEnhancement )
813 color.setX( ir / 255.0f );
814 color.setY( ig / 255.0f );
815 color.setZ( ib / 255.0f );
817 outNormal.positions.push_back( QVector3D( p.
x(), p.
y(), p.
z() ) );
818 outNormal.colors.push_back( color );
824 makeEntity( parent, context, outNormal,
false );
827 Qt3DRender::QGeometry *QgsRGBPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
829 return new QgsRGBPointCloud3DGeometry( parent, data, byteStride );
832 QgsClassificationPointCloud3DSymbolHandler::QgsClassificationPointCloud3DSymbolHandler()
833 : QgsPointCloud3DSymbolHandler()
847 const int xOffset = 0;
854 QString attributeName;
855 bool attrIsX =
false;
856 bool attrIsY =
false;
857 bool attrIsZ =
false;
859 int attributeOffset = 0;
866 if ( symbol->
attribute() == QLatin1String(
"X" ) )
870 else if ( symbol->
attribute() == QLatin1String(
"Y" ) )
874 else if ( symbol->
attribute() == QLatin1String(
"Z" ) )
883 attributeType = attr->
type();
884 attributeName = attr->
name();
891 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
896 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
900 const char *ptr = block->
data();
909 bool alreadyPrintedDebug =
false;
911 QList<QgsPointCloudCategory> categoriesList = symbol->
categoriesList();
912 QVector<int> categoriesValues;
915 categoriesValues.push_back(
c.value() );
919 for (
int i = 0; i < count; ++i )
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 );
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;
937 if ( !alreadyPrintedDebug )
939 QgsDebugMsg( QStringLiteral(
"Error transforming point coordinate" ) );
940 alreadyPrintedDebug =
true;
944 const QgsVector3D p = context.map().mapToWorldCoordinates( point );
953 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
955 if ( filteredOutValues.contains( (
int ) iParam ) ||
956 ! categoriesValues.contains( (
int ) iParam ) )
958 outNormal.positions.push_back( QVector3D( p.
x(), p.
y(), p.
z() ) );
961 float iParam2 = categoriesValues.indexOf( (
int )iParam ) + 1;
962 outNormal.parameter.push_back( iParam2 );
968 makeEntity( parent, context, outNormal,
false );
971 Qt3DRender::QGeometry *QgsClassificationPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
973 return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );