17#include "moc_qgspointcloud3dsymbol_p.cpp"
29#include <Qt3DCore/QEntity>
30#include <Qt3DRender/QGeometryRenderer>
31#include <Qt3DRender/QParameter>
32#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
33#include <Qt3DRender/QAttribute>
34#include <Qt3DRender/QBuffer>
35#include <Qt3DRender/QGeometry>
41#include <Qt3DCore/QAttribute>
42#include <Qt3DCore/QBuffer>
43#include <Qt3DCore/QGeometry>
49#include <Qt3DRender/QTechnique>
50#include <Qt3DRender/QShaderProgram>
51#include <Qt3DRender/QGraphicsApiFilter>
52#include <Qt3DRender/QEffect>
56#include <delaunator.hpp>
65 double nodeOriginX = bounds.
xMin() * blockScale.
x() + blockOffset.
x();
66 double nodeOriginY = bounds.
yMin() * blockScale.
y() + blockOffset.
y();
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() )
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() )
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 Qt3DCore::QTransform *tr =
new Qt3DCore::QTransform;
311 QVector3D nodeTranslation = ( out.positionsOrigin - context.
origin() ).toVector3D();
312 tr->setTranslation( nodeTranslation );
319 Qt3DRender::QShaderProgram *shaderProgram =
new Qt3DRender::QShaderProgram( mat );
320 shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/pointcloud.vert" ) ) ) );
321 shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( QStringLiteral(
"qrc:/shaders/pointcloud.frag" ) ) ) );
323 Qt3DRender::QRenderPass *renderPass =
new Qt3DRender::QRenderPass( mat );
324 renderPass->setShaderProgram( shaderProgram );
326 if ( out.triangles.isEmpty() )
328 Qt3DRender::QPointSize *pointSize =
new Qt3DRender::QPointSize( renderPass );
329 pointSize->setSizeMode( Qt3DRender::QPointSize::Programmable );
330 renderPass->addRenderState( pointSize );
334 Qt3DRender::QFilterKey *filterKey =
new Qt3DRender::QFilterKey;
335 filterKey->setName( QStringLiteral(
"renderingStyle" ) );
336 filterKey->setValue(
"forward" );
338 Qt3DRender::QTechnique *technique =
new Qt3DRender::QTechnique;
339 technique->addRenderPass( renderPass );
340 technique->addFilterKey( filterKey );
341 technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
342 technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
343 technique->graphicsApiFilter()->setMajorVersion( 3 );
344 technique->graphicsApiFilter()->setMinorVersion( 1 );
345 technique->addParameter(
new Qt3DRender::QParameter(
"triangulate", !out.triangles.isEmpty() ) );
347 Qt3DRender::QEffect *eff =
new Qt3DRender::QEffect;
348 eff->addTechnique( technique );
349 mat->setEffect( eff );
352 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
353 entity->addComponent( gr );
354 entity->addComponent( tr );
355 entity->addComponent( mat );
356 entity->setParent( parent );
365 bool hasColorData = !outNormal.colors.empty();
366 bool hasParameterData = !outNormal.parameter.empty();
367 bool hasPointSizeData = !outNormal.pointSizes.empty();
370 std::vector<double> vertices( outNormal.positions.size() * 2 );
372 for (
int i = 0; i < outNormal.positions.size(); ++i )
374 vertices[idx++] = outNormal.positions.at( i ).x();
375 vertices[idx++] = -outNormal.positions.at( i ).y();
381 double span = pc->
span();
384 double extraBoxFactor = 16 / span;
387 QgsRectangle rectRelativeToChunkOrigin = ( box3D - outNormal.positionsOrigin ).toRectangle();
388 rectRelativeToChunkOrigin.
grow( extraBoxFactor * std::max( box3D.
width(), box3D.
height() ) );
390 PointData filteredExtraPointData;
391 while ( parentNode.
d() >= 0 )
393 PointData outputParent;
394 processNode( pc, parentNode, context, &outputParent );
397 QVector3D originDifference = ( outputParent.positionsOrigin - outNormal.positionsOrigin ).toVector3D();
399 for (
int i = 0; i < outputParent.positions.count(); ++i )
401 const QVector3D pos = outputParent.positions.at( i ) + originDifference;
402 if ( rectRelativeToChunkOrigin.
contains( pos.x(), pos.y() ) )
404 filteredExtraPointData.positions.append( pos );
405 vertices.push_back( pos.x() );
406 vertices.push_back( -pos.y() );
409 filteredExtraPointData.colors.append( outputParent.colors.at( i ) );
410 if ( hasParameterData )
411 filteredExtraPointData.parameter.append( outputParent.parameter.at( i ) );
412 if ( hasPointSizeData )
413 filteredExtraPointData.pointSizes.append( outputParent.pointSizes.at( i ) );
420 outNormal.positions.append( filteredExtraPointData.positions );
421 outNormal.colors.append( filteredExtraPointData.colors );
422 outNormal.parameter.append( filteredExtraPointData.parameter );
423 outNormal.pointSizes.append( filteredExtraPointData.pointSizes );
428void QgsPointCloud3DSymbolHandler::calculateNormals(
const std::vector<size_t> &triangles )
430 QVector<QVector3D> normals( outNormal.positions.count(), QVector3D( 0.0, 0.0, 0.0 ) );
431 for (
size_t i = 0; i < triangles.size(); i += 3 )
433 QVector<QVector3D> triangleVertices( 3 );
434 for (
size_t j = 0; j < 3; ++j )
436 size_t vertIndex = triangles.at( i + j );
437 triangleVertices[j] = outNormal.positions.at( vertIndex );
440 for (
size_t j = 0; j < 3; ++j )
441 normals[triangles.at( i + j )] += QVector3D::crossProduct(
442 triangleVertices.at( 1 ) - triangleVertices.at( 0 ),
443 triangleVertices.at( 2 ) - triangleVertices.at( 0 ) );
447 outNormal.normals.resize( ( outNormal.positions.count() ) *
sizeof(
float ) * 3 );
448 float *normPtr =
reinterpret_cast<float *
>( outNormal.normals.data() );
449 for (
int i = 0; i < normals.size(); ++i )
451 QVector3D normal = normals.at( i );
452 normal = normal.normalized();
454 *normPtr++ = normal.x();
455 *normPtr++ = normal.y();
456 *normPtr++ = normal.z();
462 outNormal.triangles.resize( triangleIndexes.size() *
sizeof( quint32 ) );
463 quint32 *indexPtr =
reinterpret_cast<quint32 *
>( outNormal.triangles.data() );
464 size_t effective = 0;
471 QgsBox3D boxRelativeToChunkOrigin = box3D - outNormal.positionsOrigin;
473 for (
size_t i = 0; i < triangleIndexes.size(); i += 3 )
475 bool atLeastOneInBox =
false;
476 bool horizontalSkip =
false;
477 bool verticalSkip =
false;
478 for (
size_t j = 0; j < 3; j++ )
480 QVector3D pos = outNormal.positions.at( triangleIndexes.at( i + j ) );
481 atLeastOneInBox |= boxRelativeToChunkOrigin.
contains( pos.x(), pos.y(), pos.z() );
483 if ( verticalFilter || horizontalFilter )
485 const QVector3D pos2 = outNormal.positions.at( triangleIndexes.at( i + ( j + 1 ) % 3 ) );
487 if ( verticalFilter )
488 verticalSkip |= std::fabs( pos.z() - pos2.z() ) > verticalThreshold;
490 if ( horizontalFilter && ! verticalSkip )
493 horizontalSkip |= sqrt( std::pow( pos.x() - pos2.x(), 2 ) +
494 std::pow( pos.y() - pos2.y(), 2 ) ) > horizontalThreshold;
497 if ( horizontalSkip || verticalSkip )
501 if ( atLeastOneInBox && !horizontalSkip && !verticalSkip )
503 for (
size_t j = 0; j < 3; j++ )
505 size_t vertIndex = triangleIndexes.at( i + j );
506 *indexPtr++ = quint32( vertIndex );
512 if ( effective != 0 )
514 outNormal.triangles.resize( effective * 3 *
sizeof( quint32 ) );
518 outNormal.triangles.clear();
519 outNormal.normals.clear();
525 if ( outNormal.positions.isEmpty() )
529 std::unique_ptr<delaunator::Delaunator> triangulation;
532 std::vector<double> vertices = getVertices( pc, n, context, box3D );
533 triangulation.reset(
new delaunator::Delaunator( vertices ) );
535 catch ( std::exception &e )
539 outNormal = PointData();
540 processNode( pc, n, context );
544 const std::vector<size_t> &triangleIndexes = triangulation->triangles;
546 calculateNormals( triangleIndexes );
547 filterTriangles( triangleIndexes, context, box3D );
552 std::unique_ptr<QgsPointCloudBlock> block;
562 bool loopAborted =
false;
581QgsSingleColorPointCloud3DSymbolHandler::QgsSingleColorPointCloud3DSymbolHandler()
582 : QgsPointCloud3DSymbolHandler()
603 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
607 const char *ptr = block->data();
608 const int count = block->pointCount();
609 const std::size_t recordSize = block->attributes().pointRecordSize();
615 bool alreadyPrintedDebug =
false;
620 output->positionsOrigin = originFromNodeBounds( pc, n, context, block.get() );
622 for (
int i = 0; i < count; ++i )
627 const qint32 ix = *( qint32 * )( ptr + i * recordSize + 0 );
628 const qint32 iy = *( qint32 * )( ptr + i * recordSize + 4 );
629 const qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
631 double x = blockOffset.
x() + blockScale.
x() * ix;
632 double y = blockOffset.
y() + blockScale.
y() * iy;
633 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
640 if ( !alreadyPrintedDebug )
642 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
643 alreadyPrintedDebug =
true;
647 output->positions.push_back( point.
toVector3D() );
653 makeEntity( parent, context, outNormal,
false );
656Qt3DQGeometry *QgsSingleColorPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
658 return new QgsSingleColorPointCloud3DGeometry( parent, data, byteStride );
661QgsColorRampPointCloud3DSymbolHandler::QgsColorRampPointCloud3DSymbolHandler()
662 : QgsPointCloud3DSymbolHandler()
676 const int xOffset = 0;
683 QString attributeName;
684 bool attrIsX =
false;
685 bool attrIsY =
false;
686 bool attrIsZ =
false;
688 int attributeOffset = 0;
692 bool alreadyPrintedDebug =
false;
700 if ( symbol->
attribute() == QLatin1String(
"X" ) )
704 else if ( symbol->
attribute() == QLatin1String(
"Y" ) )
708 else if ( symbol->
attribute() == QLatin1String(
"Z" ) )
717 attributeType = attr->
type();
718 attributeName = attr->
name();
725 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
731 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
735 const char *ptr = block->data();
736 const int count = block->pointCount();
737 const std::size_t recordSize = block->attributes().pointRecordSize();
745 output->positionsOrigin = originFromNodeBounds( pc, n, context, block.get() );
747 for (
int i = 0; i < count; ++i )
752 const qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
753 const qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
754 const qint32 iz = *( qint32 * )( ptr + i * recordSize + zOffset );
756 double x = blockOffset.
x() + blockScale.
x() * ix;
757 double y = blockOffset.
y() + blockScale.
y() * iy;
758 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
765 if ( !alreadyPrintedDebug )
767 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
768 alreadyPrintedDebug =
true;
772 output->positions.push_back( point.
toVector3D() );
775 output->parameter.push_back( x );
777 output->parameter.push_back( y );
779 output->parameter.push_back( z );
783 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
784 output->parameter.push_back( iParam );
791 makeEntity( parent, context, outNormal,
false );
794Qt3DQGeometry *QgsColorRampPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
796 return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );
799QgsRGBPointCloud3DSymbolHandler::QgsRGBPointCloud3DSymbolHandler()
800 : QgsPointCloud3DSymbolHandler()
841 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
845 const char *ptr = block->data();
846 const int count = block->pointCount();
847 const std::size_t recordSize = block->attributes().pointRecordSize();
854 bool alreadyPrintedDebug =
false;
867 output->positionsOrigin = originFromNodeBounds( pc, n, context, block.get() );
872 for (
int i = 0; i < count; ++i )
877 const qint32 ix = *( qint32 * )( ptr + i * recordSize + 0 );
878 const qint32 iy = *( qint32 * )( ptr + i * recordSize + 4 );
879 const qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
880 double x = blockOffset.
x() + blockScale.
x() * ix;
881 double y = blockOffset.
y() + blockScale.
y() * iy;
882 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
889 if ( !alreadyPrintedDebug )
891 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
892 alreadyPrintedDebug =
true;
897 QVector3D color( 0.0f, 0.0f, 0.0f );
899 context.
getAttribute( ptr, i * recordSize + redOffset, redType, ir );
900 context.
getAttribute( ptr, i * recordSize + greenOffset, greenType, ig );
901 context.
getAttribute( ptr, i * recordSize + blueOffset, blueType, ib );
912 if ( useRedContrastEnhancement )
916 if ( useGreenContrastEnhancement )
920 if ( useBlueContrastEnhancement )
925 color.setX( ir / 255.0f );
926 color.setY( ig / 255.0f );
927 color.setZ( ib / 255.0f );
929 output->positions.push_back( point.
toVector3D() );
930 output->colors.push_back( color );
936 makeEntity( parent, context, outNormal,
false );
939Qt3DQGeometry *QgsRGBPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
941 return new QgsRGBPointCloud3DGeometry( parent, data, byteStride );
944QgsClassificationPointCloud3DSymbolHandler::QgsClassificationPointCloud3DSymbolHandler()
945 : QgsPointCloud3DSymbolHandler()
959 const int xOffset = 0;
966 QString attributeName;
967 bool attrIsX =
false;
968 bool attrIsY =
false;
969 bool attrIsZ =
false;
971 int attributeOffset = 0;
978 if ( symbol->
attribute() == QLatin1String(
"X" ) )
982 else if ( symbol->
attribute() == QLatin1String(
"Y" ) )
986 else if ( symbol->
attribute() == QLatin1String(
"Z" ) )
995 attributeType = attr->
type();
996 attributeName = attr->
name();
1003 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
1009 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
1013 const char *ptr = block->data();
1014 const int count = block->pointCount();
1015 const std::size_t recordSize = block->attributes().pointRecordSize();
1022 bool alreadyPrintedDebug =
false;
1024 QList<QgsPointCloudCategory> categoriesList = symbol->
categoriesList();
1025 QVector<int> categoriesValues;
1026 QHash<int, double> categoriesPointSizes;
1029 categoriesValues.push_back(
c.value() );
1030 categoriesPointSizes.insert(
c.value(),
c.pointSize() > 0 ?
c.pointSize() :
1031 context.symbol() ? context.symbol()->pointSize() : 1.0 );
1035 output = &outNormal;
1037 output->positionsOrigin = originFromNodeBounds( pc, n, context, block.get() );
1040 for (
int i = 0; i < count; ++i )
1045 const qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
1046 const qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
1047 const qint32 iz = *( qint32 * )( ptr + i * recordSize + zOffset );
1049 double x = blockOffset.
x() + blockScale.
x() * ix;
1050 double y = blockOffset.
y() + blockScale.
y() * iy;
1051 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
1058 if ( !alreadyPrintedDebug )
1060 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
1061 alreadyPrintedDebug =
true;
1065 float iParam = 0.0f;
1073 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
1075 if ( filteredOutValues.contains( (
int ) iParam ) ||
1076 ! categoriesValues.contains( (
int ) iParam ) )
1078 output->positions.push_back( point.
toVector3D() );
1081 float iParam2 = categoriesValues.indexOf( (
int )iParam ) + 1;
1082 output->parameter.push_back( iParam2 );
1083 output->pointSizes.push_back( categoriesPointSizes.value( (
int ) iParam ) );
1089 makeEntity( parent, context, outNormal,
false );
1092Qt3DQGeometry *QgsClassificationPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
1094 return new QgsClassificationPointCloud3DGeometry( parent, data, byteStride );
Represents a indexed point cloud node in octree.
IndexedPointCloudNode parentNode() const
Returns the parent of the node.
QgsVector3D origin() const
Returns coordinates in map CRS at which 3D scene has origin (0,0,0)
A 3-dimensional box composed of x, y, z coordinates.
bool contains(const QgsBox3D &other) const
Returns true when box contains other box.
double width() const
Returns the width of the box.
double height() const
Returns the height of the 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.
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.
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.
Base class for storing raw data from point cloud nodes.
QgsVector3D scale() const
Returns the custom scale of the block.
QgsVector3D offset() const
Returns the custom offset of the block.
Represents an individual category (class) from a QgsPointCloudClassifiedRenderer.
Represents packaged data bounds.
qint64 xMin() const
Returns x min.
qint64 zMin() const
Returns z min.
qint64 yMin() const
Returns y min.
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...
QgsPointCloudDataBounds nodeBounds(const IndexedPointCloudNode &node) const
Returns bounds of particular node.
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.
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.
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.
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)