18#include "moc_qgspointcloud3dsymbol_p.cpp"
31#include <Qt3DCore/QEntity>
32#include <Qt3DRender/QGeometryRenderer>
33#include <Qt3DRender/QParameter>
34#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
35#include <Qt3DRender/QAttribute>
36#include <Qt3DRender/QBuffer>
37#include <Qt3DRender/QGeometry>
43#include <Qt3DCore/QAttribute>
44#include <Qt3DCore/QBuffer>
45#include <Qt3DCore/QGeometry>
51#include <Qt3DRender/QTechnique>
52#include <Qt3DRender/QShaderProgram>
53#include <Qt3DRender/QGraphicsApiFilter>
54#include <Qt3DRender/QEffect>
58#include <delaunator.hpp>
65 double nodeOriginX = bounds.
xMinimum();
66 double nodeOriginY = bounds.
yMinimum();
74 QgsDebugError( QStringLiteral(
"Error transforming node origin point" ) );
76 return QgsVector3D( nodeOriginX, nodeOriginY, nodeOriginZ );
80QgsPointCloud3DGeometry::QgsPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
89 , mByteStride( byteStride )
91 if ( !data.triangles.isEmpty() )
93 mTriangleBuffer = new Qt3DQBuffer( this );
94 mTriangleIndexAttribute->setAttributeType( Qt3DQAttribute::IndexAttribute );
95 mTriangleIndexAttribute->setBuffer( mTriangleBuffer );
96 mTriangleIndexAttribute->setVertexBaseType( Qt3DQAttribute::UnsignedInt );
97 mTriangleBuffer->setData( data.triangles );
98 mTriangleIndexAttribute->setCount( data.triangles.size() / sizeof( quint32 ) );
99 addAttribute( mTriangleIndexAttribute );
102 if ( !data.normals.isEmpty() )
104 mNormalsBuffer = new Qt3DQBuffer( this );
105 mNormalsAttribute->setName( Qt3DQAttribute::defaultNormalAttributeName() );
106 mNormalsAttribute->setVertexBaseType( Qt3DQAttribute::Float );
107 mNormalsAttribute->setVertexSize( 3 );
108 mNormalsAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
109 mNormalsAttribute->setBuffer( mNormalsBuffer );
110 mNormalsBuffer->setData( data.normals );
111 mNormalsAttribute->setCount( data.normals.size() / ( 3 * sizeof( float ) ) );
112 addAttribute( mNormalsAttribute );
116QgsSingleColorPointCloud3DGeometry::QgsSingleColorPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
117 : QgsPointCloud3DGeometry( parent, data, byteStride )
119 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
120 mPositionAttribute->setBuffer( mVertexBuffer );
121 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
122 mPositionAttribute->setVertexSize( 3 );
123 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
124 mPositionAttribute->setByteOffset( 0 );
125 mPositionAttribute->setByteStride( mByteStride );
126 addAttribute( mPositionAttribute );
127 makeVertexBuffer( data );
130void QgsSingleColorPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
132 QByteArray vertexBufferData;
133 vertexBufferData.resize( data.positions.size() * mByteStride );
134 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
136 for (
int i = 0; i < data.positions.size(); ++i )
138 rawVertexArray[idx++] = data.positions.at( i ).x();
139 rawVertexArray[idx++] = data.positions.at( i ).y();
140 rawVertexArray[idx++] = data.positions.at( i ).z();
143 mVertexCount = data.positions.size();
144 mVertexBuffer->setData( vertexBufferData );
147QgsColorRampPointCloud3DGeometry::QgsColorRampPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
148 : QgsPointCloud3DGeometry( parent, data, byteStride )
150 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
151 mPositionAttribute->setBuffer( mVertexBuffer );
152 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
153 mPositionAttribute->setVertexSize( 3 );
154 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
155 mPositionAttribute->setByteOffset( 0 );
156 mPositionAttribute->setByteStride( mByteStride );
157 addAttribute( mPositionAttribute );
158 mParameterAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
159 mParameterAttribute->setBuffer( mVertexBuffer );
160 mParameterAttribute->setVertexBaseType( Qt3DQAttribute::Float );
161 mParameterAttribute->setVertexSize( 1 );
162 mParameterAttribute->setName(
"vertexParameter" );
163 mParameterAttribute->setByteOffset( 12 );
164 mParameterAttribute->setByteStride( mByteStride );
165 addAttribute( mParameterAttribute );
166 makeVertexBuffer( data );
169void QgsColorRampPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
171 QByteArray vertexBufferData;
172 vertexBufferData.resize( data.positions.size() * mByteStride );
173 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
175 Q_ASSERT( data.positions.size() == data.parameter.size() );
176 for (
int i = 0; i < data.positions.size(); ++i )
178 rawVertexArray[idx++] = data.positions.at( i ).x();
179 rawVertexArray[idx++] = data.positions.at( i ).y();
180 rawVertexArray[idx++] = data.positions.at( i ).z();
181 rawVertexArray[idx++] = data.parameter.at( i );
184 mVertexCount = data.positions.size();
185 mVertexBuffer->setData( vertexBufferData );
188QgsRGBPointCloud3DGeometry::QgsRGBPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
189 : QgsPointCloud3DGeometry( parent, data, byteStride )
191 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
192 mPositionAttribute->setBuffer( mVertexBuffer );
193 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
194 mPositionAttribute->setVertexSize( 3 );
195 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
196 mPositionAttribute->setByteOffset( 0 );
197 mPositionAttribute->setByteStride( mByteStride );
198 addAttribute( mPositionAttribute );
199 mColorAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
200 mColorAttribute->setBuffer( mVertexBuffer );
201 mColorAttribute->setVertexBaseType( Qt3DQAttribute::Float );
202 mColorAttribute->setVertexSize( 3 );
203 mColorAttribute->setName( QStringLiteral(
"vertexColor" ) );
204 mColorAttribute->setByteOffset( 12 );
205 mColorAttribute->setByteStride( mByteStride );
206 addAttribute( mColorAttribute );
207 makeVertexBuffer( data );
210void QgsRGBPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
212 QByteArray vertexBufferData;
213 vertexBufferData.resize( data.positions.size() * mByteStride );
214 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
216 Q_ASSERT( data.positions.size() == data.colors.size() );
217 for (
int i = 0; i < data.positions.size(); ++i )
219 rawVertexArray[idx++] = data.positions.at( i ).x();
220 rawVertexArray[idx++] = data.positions.at( i ).y();
221 rawVertexArray[idx++] = data.positions.at( i ).z();
222 rawVertexArray[idx++] = data.colors.at( i ).x();
223 rawVertexArray[idx++] = data.colors.at( i ).y();
224 rawVertexArray[idx++] = data.colors.at( i ).z();
226 mVertexCount = data.positions.size();
227 mVertexBuffer->setData( vertexBufferData );
230QgsClassificationPointCloud3DGeometry::QgsClassificationPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
231 : QgsPointCloud3DGeometry( parent, data, byteStride )
233 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
234 mPositionAttribute->setBuffer( mVertexBuffer );
235 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
236 mPositionAttribute->setVertexSize( 3 );
237 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
238 mPositionAttribute->setByteOffset( 0 );
239 mPositionAttribute->setByteStride( mByteStride );
240 addAttribute( mPositionAttribute );
241 mParameterAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
242 mParameterAttribute->setBuffer( mVertexBuffer );
243 mParameterAttribute->setVertexBaseType( Qt3DQAttribute::Float );
244 mParameterAttribute->setVertexSize( 1 );
245 mParameterAttribute->setName(
"vertexParameter" );
246 mParameterAttribute->setByteOffset( 12 );
247 mParameterAttribute->setByteStride( mByteStride );
248 addAttribute( mParameterAttribute );
249 mPointSizeAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
250 mPointSizeAttribute->setBuffer( mVertexBuffer );
251 mPointSizeAttribute->setVertexBaseType( Qt3DQAttribute::Float );
252 mPointSizeAttribute->setVertexSize( 1 );
253 mPointSizeAttribute->setName(
"vertexSize" );
254 mPointSizeAttribute->setByteOffset( 16 );
255 mPointSizeAttribute->setByteStride( mByteStride );
256 addAttribute( mPointSizeAttribute );
257 makeVertexBuffer( data );
260void QgsClassificationPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
262 QByteArray vertexBufferData;
263 vertexBufferData.resize( data.positions.size() * mByteStride );
264 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
266 Q_ASSERT( data.positions.size() == data.parameter.size() );
267 Q_ASSERT( data.positions.size() == data.pointSizes.size() );
268 for (
int i = 0; i < data.positions.size(); ++i )
270 rawVertexArray[idx++] = data.positions.at( i ).x();
271 rawVertexArray[idx++] = data.positions.at( i ).y();
272 rawVertexArray[idx++] = data.positions.at( i ).z();
273 rawVertexArray[idx++] = data.parameter.at( i );
274 rawVertexArray[idx++] = data.pointSizes.at( i );
277 mVertexCount = data.positions.size();
278 mVertexBuffer->setData( vertexBufferData );
281QgsPointCloud3DSymbolHandler::QgsPointCloud3DSymbolHandler()
286void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const QgsPointCloud3DRenderContext &context,
const QgsPointCloud3DSymbolHandler::PointData &out,
bool selected )
290 if ( out.positions.empty() )
295 Qt3DRender::QGeometryRenderer *gr =
new Qt3DRender::QGeometryRenderer;
298 gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
299 gr->setVertexCount( out.triangles.size() /
sizeof( quint32 ) );
303 gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
304 gr->setVertexCount( out.positions.count() );
306 gr->setGeometry( geom );
310 QgsGeoTransform *tr =
new QgsGeoTransform;
311 tr->setGeoTranslation( out.positionsOrigin );
318 Qt3DRender::QShaderProgram *shaderProgram =
new Qt3DRender::QShaderProgram( mat );
319 shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/pointcloud.vert" ) ) ) );
320 shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/pointcloud.frag" ) ) ) );
322 Qt3DRender::QRenderPass *renderPass =
new Qt3DRender::QRenderPass( mat );
323 renderPass->setShaderProgram( shaderProgram );
325 if ( out.triangles.isEmpty() )
327 Qt3DRender::QPointSize *pointSize =
new Qt3DRender::QPointSize( renderPass );
328 pointSize->setSizeMode( Qt3DRender::QPointSize::Programmable );
329 renderPass->addRenderState( pointSize );
333 Qt3DRender::QFilterKey *filterKey =
new Qt3DRender::QFilterKey;
334 filterKey->setName( QStringLiteral(
"renderingStyle" ) );
335 filterKey->setValue(
"forward" );
337 Qt3DRender::QTechnique *technique =
new Qt3DRender::QTechnique;
338 technique->addRenderPass( renderPass );
339 technique->addFilterKey( filterKey );
340 technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
341 technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
342 technique->graphicsApiFilter()->setMajorVersion( 3 );
343 technique->graphicsApiFilter()->setMinorVersion( 1 );
344 technique->addParameter(
new Qt3DRender::QParameter(
"triangulate", !out.triangles.isEmpty() ) );
346 Qt3DRender::QEffect *eff =
new Qt3DRender::QEffect;
347 eff->addTechnique( technique );
348 mat->setEffect( eff );
351 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
352 entity->addComponent( gr );
353 entity->addComponent( tr );
354 entity->addComponent( mat );
355 entity->setParent( parent );
363 bool hasColorData = !outNormal.colors.empty();
364 bool hasParameterData = !outNormal.parameter.empty();
365 bool hasPointSizeData = !outNormal.pointSizes.empty();
368 std::vector<double> vertices( outNormal.positions.size() * 2 );
370 for (
int i = 0; i < outNormal.positions.size(); ++i )
372 vertices[idx++] = outNormal.positions.at( i ).x();
373 vertices[idx++] = -outNormal.positions.at( i ).y();
379 double span = pc.
span();
382 double extraBoxFactor = 16 / span;
385 QgsRectangle rectRelativeToChunkOrigin = ( box3D - outNormal.positionsOrigin ).toRectangle();
386 rectRelativeToChunkOrigin.
grow( extraBoxFactor * std::max( box3D.
width(), box3D.
height() ) );
388 PointData filteredExtraPointData;
389 while ( parentNode.
d() >= 0 )
391 PointData outputParent;
392 processNode( pc, parentNode, context, &outputParent );
395 QVector3D originDifference = ( outputParent.positionsOrigin - outNormal.positionsOrigin ).toVector3D();
397 for (
int i = 0; i < outputParent.positions.count(); ++i )
399 const QVector3D pos = outputParent.positions.at( i ) + originDifference;
400 if ( rectRelativeToChunkOrigin.
contains( pos.x(), pos.y() ) )
402 filteredExtraPointData.positions.append( pos );
403 vertices.push_back( pos.x() );
404 vertices.push_back( -pos.y() );
407 filteredExtraPointData.colors.append( outputParent.colors.at( i ) );
408 if ( hasParameterData )
409 filteredExtraPointData.parameter.append( outputParent.parameter.at( i ) );
410 if ( hasPointSizeData )
411 filteredExtraPointData.pointSizes.append( outputParent.pointSizes.at( i ) );
418 outNormal.positions.append( filteredExtraPointData.positions );
419 outNormal.colors.append( filteredExtraPointData.colors );
420 outNormal.parameter.append( filteredExtraPointData.parameter );
421 outNormal.pointSizes.append( filteredExtraPointData.pointSizes );
426void QgsPointCloud3DSymbolHandler::calculateNormals(
const std::vector<size_t> &triangles )
428 QVector<QVector3D> normals( outNormal.positions.count(), QVector3D( 0.0, 0.0, 0.0 ) );
429 for (
size_t i = 0; i < triangles.size(); i += 3 )
431 QVector<QVector3D> triangleVertices( 3 );
432 for (
size_t j = 0; j < 3; ++j )
434 size_t vertIndex = triangles.at( i + j );
435 triangleVertices[j] = outNormal.positions.at( vertIndex );
438 for (
size_t j = 0; j < 3; ++j )
439 normals[triangles.at( i + j )] += QVector3D::crossProduct(
440 triangleVertices.at( 1 ) - triangleVertices.at( 0 ),
441 triangleVertices.at( 2 ) - triangleVertices.at( 0 )
446 outNormal.normals.resize( ( outNormal.positions.count() ) *
sizeof(
float ) * 3 );
447 float *normPtr =
reinterpret_cast<float *
>( outNormal.normals.data() );
448 for (
int i = 0; i < normals.size(); ++i )
450 QVector3D normal = normals.at( i );
451 normal = normal.normalized();
453 *normPtr++ = normal.x();
454 *normPtr++ = normal.y();
455 *normPtr++ = normal.z();
461 outNormal.triangles.resize( triangleIndexes.size() *
sizeof( quint32 ) );
462 quint32 *indexPtr =
reinterpret_cast<quint32 *
>( outNormal.triangles.data() );
463 size_t effective = 0;
470 QgsBox3D boxRelativeToChunkOrigin = box3D - outNormal.positionsOrigin;
472 for (
size_t i = 0; i < triangleIndexes.size(); i += 3 )
474 bool atLeastOneInBox =
false;
475 bool horizontalSkip =
false;
476 bool verticalSkip =
false;
477 for (
size_t j = 0; j < 3; j++ )
479 QVector3D pos = outNormal.positions.at( triangleIndexes.at( i + j ) );
480 atLeastOneInBox |= boxRelativeToChunkOrigin.
contains( pos.x(), pos.y(), pos.z() );
482 if ( verticalFilter || horizontalFilter )
484 const QVector3D pos2 = outNormal.positions.at( triangleIndexes.at( i + ( j + 1 ) % 3 ) );
486 if ( verticalFilter )
487 verticalSkip |= std::fabs( pos.z() - pos2.z() ) > verticalThreshold;
489 if ( horizontalFilter && !verticalSkip )
492 horizontalSkip |= sqrt( std::pow( pos.x() - pos2.x(), 2 ) + std::pow( pos.y() - pos2.y(), 2 ) ) > horizontalThreshold;
495 if ( horizontalSkip || verticalSkip )
499 if ( atLeastOneInBox && !horizontalSkip && !verticalSkip )
501 for (
size_t j = 0; j < 3; j++ )
503 size_t vertIndex = triangleIndexes.at( i + j );
504 *indexPtr++ = quint32( vertIndex );
510 if ( effective != 0 )
512 outNormal.triangles.resize( effective * 3 *
sizeof( quint32 ) );
516 outNormal.triangles.clear();
517 outNormal.normals.clear();
523 if ( outNormal.positions.isEmpty() )
527 std::unique_ptr<delaunator::Delaunator> triangulation;
530 std::vector<double> vertices = getVertices( pc, n, context, box3D );
531 triangulation = std::make_unique<delaunator::Delaunator>( vertices );
533 catch ( std::exception &e )
537 outNormal = PointData();
538 processNode( pc, n, context );
542 const std::vector<size_t> &triangleIndexes = triangulation->triangles;
544 calculateNormals( triangleIndexes );
545 filterTriangles( triangleIndexes, context, box3D );
550 std::unique_ptr<QgsPointCloudBlock> block;
561 bool loopAborted =
false;
579QgsSingleColorPointCloud3DSymbolHandler::QgsSingleColorPointCloud3DSymbolHandler()
580 : QgsPointCloud3DSymbolHandler()
600 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
604 const char *ptr = block->data();
605 const int count = block->pointCount();
606 const std::size_t recordSize = block->attributes().pointRecordSize();
612 bool alreadyPrintedDebug =
false;
617 output->positionsOrigin = originFromNodeBounds( pc, n, context );
619 for (
int i = 0; i < count; ++i )
624 const qint32 ix = *( qint32 * ) ( ptr + i * recordSize + 0 );
625 const qint32 iy = *( qint32 * ) ( ptr + i * recordSize + 4 );
626 const qint32 iz = *( qint32 * ) ( ptr + i * recordSize + 8 );
628 double x = blockOffset.
x() + blockScale.
x() * ix;
629 double y = blockOffset.
y() + blockScale.
y() * iy;
630 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
637 if ( !alreadyPrintedDebug )
639 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
640 alreadyPrintedDebug =
true;
644 output->positions.push_back( point.
toVector3D() );
650 makeEntity( parent, context, outNormal,
false );
653Qt3DQGeometry *QgsSingleColorPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
655 return new QgsSingleColorPointCloud3DGeometry( parent, data, byteStride );
658QgsColorRampPointCloud3DSymbolHandler::QgsColorRampPointCloud3DSymbolHandler()
659 : QgsPointCloud3DSymbolHandler()
672 const int xOffset = 0;
679 QString attributeName;
680 bool attrIsX =
false;
681 bool attrIsY =
false;
682 bool attrIsZ =
false;
684 int attributeOffset = 0;
688 bool alreadyPrintedDebug =
false;
696 if ( symbol->
attribute() == QLatin1String(
"X" ) )
700 else if ( symbol->
attribute() == QLatin1String(
"Y" ) )
704 else if ( symbol->
attribute() == QLatin1String(
"Z" ) )
713 attributeType = attr->
type();
714 attributeName = attr->
name();
721 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
727 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
731 const char *ptr = block->data();
732 const int count = block->pointCount();
733 const std::size_t recordSize = block->attributes().pointRecordSize();
741 output->positionsOrigin = originFromNodeBounds( pc, n, context );
743 for (
int i = 0; i < count; ++i )
748 const qint32 ix = *( qint32 * ) ( ptr + i * recordSize + xOffset );
749 const qint32 iy = *( qint32 * ) ( ptr + i * recordSize + yOffset );
750 const qint32 iz = *( qint32 * ) ( ptr + i * recordSize + zOffset );
752 double x = blockOffset.
x() + blockScale.
x() * ix;
753 double y = blockOffset.
y() + blockScale.
y() * iy;
754 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
761 if ( !alreadyPrintedDebug )
763 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
764 alreadyPrintedDebug =
true;
768 output->positions.push_back( point.
toVector3D() );
771 output->parameter.push_back( x );
773 output->parameter.push_back( y );
775 output->parameter.push_back( z );
779 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
780 output->parameter.push_back( iParam );
787 makeEntity( parent, context, outNormal,
false );
790Qt3DQGeometry *QgsColorRampPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
792 return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );
795QgsRGBPointCloud3DSymbolHandler::QgsRGBPointCloud3DSymbolHandler()
796 : QgsPointCloud3DSymbolHandler()
836 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
840 const char *ptr = block->data();
841 const int count = block->pointCount();
842 const std::size_t recordSize = block->attributes().pointRecordSize();
849 bool alreadyPrintedDebug =
false;
862 output->positionsOrigin = originFromNodeBounds( pc, n, context );
867 for (
int i = 0; i < count; ++i )
872 const qint32 ix = *( qint32 * ) ( ptr + i * recordSize + 0 );
873 const qint32 iy = *( qint32 * ) ( ptr + i * recordSize + 4 );
874 const qint32 iz = *( qint32 * ) ( ptr + i * recordSize + 8 );
875 double x = blockOffset.
x() + blockScale.
x() * ix;
876 double y = blockOffset.
y() + blockScale.
y() * iy;
877 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
884 if ( !alreadyPrintedDebug )
886 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
887 alreadyPrintedDebug =
true;
892 QVector3D color( 0.0f, 0.0f, 0.0f );
894 context.
getAttribute( ptr, i * recordSize + redOffset, redType, ir );
895 context.
getAttribute( ptr, i * recordSize + greenOffset, greenType, ig );
896 context.
getAttribute( ptr, i * recordSize + blueOffset, blueType, ib );
907 if ( useRedContrastEnhancement )
911 if ( useGreenContrastEnhancement )
915 if ( useBlueContrastEnhancement )
920 color.setX( ir / 255.0f );
921 color.setY( ig / 255.0f );
922 color.setZ( ib / 255.0f );
924 output->positions.push_back( point.
toVector3D() );
925 output->colors.push_back( color );
931 makeEntity( parent, context, outNormal,
false );
934Qt3DQGeometry *QgsRGBPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
936 return new QgsRGBPointCloud3DGeometry( parent, data, byteStride );
939QgsClassificationPointCloud3DSymbolHandler::QgsClassificationPointCloud3DSymbolHandler()
940 : QgsPointCloud3DSymbolHandler()
953 const int xOffset = 0;
960 QString attributeName;
961 bool attrIsX =
false;
962 bool attrIsY =
false;
963 bool attrIsZ =
false;
965 int attributeOffset = 0;
973 if ( symbol->
attribute() == QLatin1String(
"X" ) )
977 else if ( symbol->
attribute() == QLatin1String(
"Y" ) )
981 else if ( symbol->
attribute() == QLatin1String(
"Z" ) )
990 attributeType = attr->
type();
991 attributeName = attr->
name();
997 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
1003 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
1007 const char *ptr = block->data();
1008 const int count = block->pointCount();
1009 const std::size_t recordSize = block->attributes().pointRecordSize();
1016 bool alreadyPrintedDebug =
false;
1018 QList<QgsPointCloudCategory> categoriesList = symbol->
categoriesList();
1019 QVector<int> categoriesValues;
1020 QHash<int, double> categoriesPointSizes;
1023 categoriesValues.push_back(
c.value() );
1024 categoriesPointSizes.insert(
c.value(),
c.pointSize() > 0 ?
c.pointSize() : context.
symbol() ? context.
symbol()->
pointSize()
1029 output = &outNormal;
1031 output->positionsOrigin = originFromNodeBounds( pc, n, context );
1034 for (
int i = 0; i < count; ++i )
1039 const qint32 ix = *( qint32 * ) ( ptr + i * recordSize + xOffset );
1040 const qint32 iy = *( qint32 * ) ( ptr + i * recordSize + yOffset );
1041 const qint32 iz = *( qint32 * ) ( ptr + i * recordSize + zOffset );
1043 double x = blockOffset.
x() + blockScale.
x() * ix;
1044 double y = blockOffset.
y() + blockScale.
y() * iy;
1045 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
1052 if ( !alreadyPrintedDebug )
1054 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
1055 alreadyPrintedDebug =
true;
1059 float iParam = 0.0f;
1067 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
1069 if ( filteredOutValues.contains( (
int ) iParam ) || !categoriesValues.contains( (
int ) iParam ) )
1071 output->positions.push_back( point.
toVector3D() );
1074 float iParam2 = categoriesValues.indexOf( (
int ) iParam ) + 1;
1075 output->parameter.push_back( iParam2 );
1076 output->pointSizes.push_back( categoriesPointSizes.value( (
int ) iParam ) );
1082 makeEntity( parent, context, outNormal,
false );
1085Qt3DQGeometry *QgsClassificationPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
1087 return new QgsClassificationPointCloud3DGeometry( parent, data, byteStride );
@ Local
Local means the source is a local file on the machine.
@ Remote
Remote means it's loaded through a protocol like HTTP.
A 3-dimensional box composed of x, y, z coordinates.
double xMinimum() const
Returns the minimum x value.
bool contains(const QgsBox3D &other) const
Returns true when box contains other box.
double width() const
Returns the width of the box.
double zMinimum() const
Returns the minimum z value.
double yMinimum() const
Returns the minimum y value.
double height() const
Returns the height of the box.
3D symbol that draws point cloud geometries as 3D objects using classification of the dataset.
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.
3D symbol that draws point cloud geometries as 3D objects using color ramp shader.
QString attribute() const
Returns the attribute used to select the color of the point cloud.
Handles contrast enhancement and clipping.
@ 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.
Base class for all materials used within QGIS 3D views.
Encapsulates the render context for a 3D point cloud rendering operation.
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.
QgsRectangle layerExtent() const
Returns the 3D scene's extent in layer 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 void fillMaterial(QgsMaterial *material)=0SIP_SKIP
Used to fill material object with necessary QParameters (and consequently opengl uniforms).
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.
bool renderAsTriangles() const
Returns whether points are triangulated to render solid surface.
float pointSize() const
Returns the point size of the point cloud.
bool horizontalTriangleFilter() const
Returns whether triangles are filtered by horizontal size for rendering.
A 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.
Smart pointer for QgsAbstractPointCloudIndex.
int span() const
Returns the number of points in one direction in a single node.
QgsPointCloudBlockRequest * asyncNodeData(const QgsPointCloudNodeId &n, const QgsPointCloudRequest &request)
Returns a handle responsible for loading a node data block.
std::unique_ptr< QgsPointCloudBlock > nodeData(const QgsPointCloudNodeId &n, const QgsPointCloudRequest &request)
Returns node data block.
QgsPointCloudNode getNode(const QgsPointCloudNodeId &id) const
Returns object for a given node.
Qgis::PointCloudAccessType accessType() const
Returns the access type of the data If the access type is Remote, data will be fetched from an HTTP s...
Represents an indexed point cloud node's position in octree.
QgsPointCloudNodeId parentNode() const
Returns the parent of the node.
Keeps metadata for an indexed point cloud node.
qint64 pointCount() const
Returns number of points contained in node data.
QgsBox3D bounds() const
Returns node's bounding cube in CRS coords.
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.
A rectangle specified with double values.
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
void grow(double delta)
Grows the rectangle in place by the specified amount.
3D symbol that draws point cloud geometries as 3D objects using RGB colors in the dataset.
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.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
double y() const
Returns Y coordinate.
double z() const
Returns Z coordinate.
QVector3D toVector3D() const
Converts the current object to QVector3D.
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)