28#include <Qt3DCore/QEntity>
29#include <Qt3DRender/QGeometryRenderer>
30#include <Qt3DRender/QParameter>
31#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
32#include <Qt3DRender/QAttribute>
33#include <Qt3DRender/QBuffer>
34#include <Qt3DRender/QGeometry>
40#include <Qt3DCore/QAttribute>
41#include <Qt3DCore/QBuffer>
42#include <Qt3DCore/QGeometry>
48#include <Qt3DRender/QTechnique>
49#include <Qt3DRender/QShaderProgram>
50#include <Qt3DRender/QGraphicsApiFilter>
51#include <Qt3DRender/QEffect>
55#include <delaunator.hpp>
64 double nodeOriginX = bounds.
xMin() * blockScale.
x() + blockOffset.
x();
65 double nodeOriginY = bounds.
yMin() * blockScale.
y() + blockOffset.
y();
73 QgsDebugError( QStringLiteral(
"Error transforming node origin point" ) );
75 return QgsVector3D( nodeOriginX, nodeOriginY, nodeOriginZ );
79QgsPointCloud3DGeometry::QgsPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
88 , mByteStride( byteStride )
90 if ( !data.triangles.isEmpty() )
93 mTriangleIndexAttribute->setAttributeType( Qt3DQAttribute::IndexAttribute );
94 mTriangleIndexAttribute->setBuffer( mTriangleBuffer );
95 mTriangleIndexAttribute->setVertexBaseType( Qt3DQAttribute::UnsignedInt );
96 mTriangleBuffer->setData( data.triangles );
97 mTriangleIndexAttribute->setCount( data.triangles.size() /
sizeof( quint32 ) );
98 addAttribute( mTriangleIndexAttribute );
101 if ( !data.normals.isEmpty() )
104 mNormalsAttribute->setName( Qt3DQAttribute::defaultNormalAttributeName() );
105 mNormalsAttribute->setVertexBaseType( Qt3DQAttribute::Float );
106 mNormalsAttribute->setVertexSize( 3 );
107 mNormalsAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
108 mNormalsAttribute->setBuffer( mNormalsBuffer );
109 mNormalsBuffer->setData( data.normals );
110 mNormalsAttribute->setCount( data.normals.size() / ( 3 *
sizeof(
float ) ) );
111 addAttribute( mNormalsAttribute );
115QgsSingleColorPointCloud3DGeometry::QgsSingleColorPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
116 : QgsPointCloud3DGeometry( parent, data, byteStride )
118 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
119 mPositionAttribute->setBuffer( mVertexBuffer );
120 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
121 mPositionAttribute->setVertexSize( 3 );
122 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
123 mPositionAttribute->setByteOffset( 0 );
124 mPositionAttribute->setByteStride( mByteStride );
125 addAttribute( mPositionAttribute );
126 makeVertexBuffer( data );
129void QgsSingleColorPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
131 QByteArray vertexBufferData;
132 vertexBufferData.resize( data.positions.size() * mByteStride );
133 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
135 for (
int i = 0; i < data.positions.size(); ++i )
137 rawVertexArray[idx++] = data.positions.at( i ).x();
138 rawVertexArray[idx++] = data.positions.at( i ).y();
139 rawVertexArray[idx++] = data.positions.at( i ).z();
142 mVertexCount = data.positions.size();
143 mVertexBuffer->setData( vertexBufferData );
146QgsColorRampPointCloud3DGeometry::QgsColorRampPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
147 : QgsPointCloud3DGeometry( parent, data, byteStride )
149 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
150 mPositionAttribute->setBuffer( mVertexBuffer );
151 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
152 mPositionAttribute->setVertexSize( 3 );
153 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
154 mPositionAttribute->setByteOffset( 0 );
155 mPositionAttribute->setByteStride( mByteStride );
156 addAttribute( mPositionAttribute );
157 mParameterAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
158 mParameterAttribute->setBuffer( mVertexBuffer );
159 mParameterAttribute->setVertexBaseType( Qt3DQAttribute::Float );
160 mParameterAttribute->setVertexSize( 1 );
161 mParameterAttribute->setName(
"vertexParameter" );
162 mParameterAttribute->setByteOffset( 12 );
163 mParameterAttribute->setByteStride( mByteStride );
164 addAttribute( mParameterAttribute );
165 makeVertexBuffer( data );
168void QgsColorRampPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
170 QByteArray vertexBufferData;
171 vertexBufferData.resize( data.positions.size() * mByteStride );
172 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
174 Q_ASSERT( data.positions.size() == data.parameter.size() );
175 for (
int i = 0; i < data.positions.size(); ++i )
177 rawVertexArray[idx++] = data.positions.at( i ).x();
178 rawVertexArray[idx++] = data.positions.at( i ).y();
179 rawVertexArray[idx++] = data.positions.at( i ).z();
180 rawVertexArray[idx++] = data.parameter.at( i );
183 mVertexCount = data.positions.size();
184 mVertexBuffer->setData( vertexBufferData );
187QgsRGBPointCloud3DGeometry::QgsRGBPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
188 : QgsPointCloud3DGeometry( parent, data, byteStride )
190 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
191 mPositionAttribute->setBuffer( mVertexBuffer );
192 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
193 mPositionAttribute->setVertexSize( 3 );
194 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
195 mPositionAttribute->setByteOffset( 0 );
196 mPositionAttribute->setByteStride( mByteStride );
197 addAttribute( mPositionAttribute );
198 mColorAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
199 mColorAttribute->setBuffer( mVertexBuffer );
200 mColorAttribute->setVertexBaseType( Qt3DQAttribute::Float );
201 mColorAttribute->setVertexSize( 3 );
202 mColorAttribute->setName( QStringLiteral(
"vertexColor" ) );
203 mColorAttribute->setByteOffset( 12 );
204 mColorAttribute->setByteStride( mByteStride );
205 addAttribute( mColorAttribute );
206 makeVertexBuffer( data );
209void QgsRGBPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
211 QByteArray vertexBufferData;
212 vertexBufferData.resize( data.positions.size() * mByteStride );
213 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
215 Q_ASSERT( data.positions.size() == data.colors.size() );
216 for (
int i = 0; i < data.positions.size(); ++i )
218 rawVertexArray[idx++] = data.positions.at( i ).x();
219 rawVertexArray[idx++] = data.positions.at( i ).y();
220 rawVertexArray[idx++] = data.positions.at( i ).z();
221 rawVertexArray[idx++] = data.colors.at( i ).x();
222 rawVertexArray[idx++] = data.colors.at( i ).y();
223 rawVertexArray[idx++] = data.colors.at( i ).z();
225 mVertexCount = data.positions.size();
226 mVertexBuffer->setData( vertexBufferData );
229QgsClassificationPointCloud3DGeometry::QgsClassificationPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
230 : QgsPointCloud3DGeometry( parent, data, byteStride )
232 mPositionAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
233 mPositionAttribute->setBuffer( mVertexBuffer );
234 mPositionAttribute->setVertexBaseType( Qt3DQAttribute::Float );
235 mPositionAttribute->setVertexSize( 3 );
236 mPositionAttribute->setName( Qt3DQAttribute::defaultPositionAttributeName() );
237 mPositionAttribute->setByteOffset( 0 );
238 mPositionAttribute->setByteStride( mByteStride );
239 addAttribute( mPositionAttribute );
240 mParameterAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
241 mParameterAttribute->setBuffer( mVertexBuffer );
242 mParameterAttribute->setVertexBaseType( Qt3DQAttribute::Float );
243 mParameterAttribute->setVertexSize( 1 );
244 mParameterAttribute->setName(
"vertexParameter" );
245 mParameterAttribute->setByteOffset( 12 );
246 mParameterAttribute->setByteStride( mByteStride );
247 addAttribute( mParameterAttribute );
248 mPointSizeAttribute->setAttributeType( Qt3DQAttribute::VertexAttribute );
249 mPointSizeAttribute->setBuffer( mVertexBuffer );
250 mPointSizeAttribute->setVertexBaseType( Qt3DQAttribute::Float );
251 mPointSizeAttribute->setVertexSize( 1 );
252 mPointSizeAttribute->setName(
"vertexSize" );
253 mPointSizeAttribute->setByteOffset( 16 );
254 mPointSizeAttribute->setByteStride( mByteStride );
255 addAttribute( mPointSizeAttribute );
256 makeVertexBuffer( data );
259void QgsClassificationPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
261 QByteArray vertexBufferData;
262 vertexBufferData.resize( data.positions.size() * mByteStride );
263 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
265 Q_ASSERT( data.positions.size() == data.parameter.size() );
266 Q_ASSERT( data.positions.size() == data.pointSizes.size() );
267 for (
int i = 0; i < data.positions.size(); ++i )
269 rawVertexArray[idx++] = data.positions.at( i ).x();
270 rawVertexArray[idx++] = data.positions.at( i ).y();
271 rawVertexArray[idx++] = data.positions.at( i ).z();
272 rawVertexArray[idx++] = data.parameter.at( i );
273 rawVertexArray[idx++] = data.pointSizes.at( i );
276 mVertexCount = data.positions.size();
277 mVertexBuffer->setData( vertexBufferData );
280QgsPointCloud3DSymbolHandler::QgsPointCloud3DSymbolHandler()
285void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const QgsPointCloud3DRenderContext &context,
const QgsPointCloud3DSymbolHandler::PointData &out,
bool selected )
289 if ( out.positions.empty() )
294 Qt3DRender::QGeometryRenderer *gr =
new Qt3DRender::QGeometryRenderer;
297 gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
298 gr->setVertexCount( out.triangles.size() /
sizeof( quint32 ) );
302 gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
303 gr->setVertexCount( out.positions.count() );
305 gr->setGeometry( geom );
309 Qt3DCore::QTransform *tr =
new Qt3DCore::QTransform;
310 QVector3D nodeTranslation = ( out.positionsOrigin - context.
origin() ).toVector3D();
311 tr->setRotation( QQuaternion::fromAxisAndAngle( QVector3D( 1, 0, 0 ), -90 ) );
312 tr->setTranslation( QVector3D( nodeTranslation.x(), nodeTranslation.z(), -nodeTranslation.y() ) );
315 Qt3DRender::QMaterial *mat =
new Qt3DRender::QMaterial;
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;
385 double extraX = extraBoxFactor * bbox.
xExtent();
386 double extraY = extraBoxFactor * bbox.
yExtent();
389 const QgsAABB extendedBBox( bbox.
xMin - extraX, bbox.
yMin - extraY, -std::numeric_limits<float>::max(), bbox.
xMax + extraX, bbox.
yMax + extraY, std::numeric_limits<float>::max() );
391 PointData filteredExtraPointData;
392 while ( parentNode.
d() >= 0 )
394 PointData outputParent;
395 processNode( pc, parentNode, context, &outputParent );
398 QVector3D originDifference = ( outputParent.positionsOrigin - outNormal.positionsOrigin ).toVector3D();
400 for (
int i = 0; i < outputParent.positions.count(); ++i )
402 const QVector3D pos = outputParent.positions.at( i ) + originDifference;
403 if ( extendedBBox.intersects( pos.x(), pos.y(), pos.z() ) )
405 filteredExtraPointData.positions.append( pos );
406 vertices.push_back( pos.x() );
407 vertices.push_back( -pos.y() );
410 filteredExtraPointData.colors.append( outputParent.colors.at( i ) );
411 if ( hasParameterData )
412 filteredExtraPointData.parameter.append( outputParent.parameter.at( i ) );
413 if ( hasPointSizeData )
414 filteredExtraPointData.pointSizes.append( outputParent.pointSizes.at( i ) );
421 outNormal.positions.append( filteredExtraPointData.positions );
422 outNormal.colors.append( filteredExtraPointData.colors );
423 outNormal.parameter.append( filteredExtraPointData.parameter );
424 outNormal.pointSizes.append( filteredExtraPointData.pointSizes );
429void QgsPointCloud3DSymbolHandler::calculateNormals(
const std::vector<size_t> &triangles )
431 QVector<QVector3D> normals( outNormal.positions.count(), QVector3D( 0.0, 0.0, 0.0 ) );
432 for (
size_t i = 0; i < triangles.size(); i += 3 )
434 QVector<QVector3D> triangleVertices( 3 );
435 for (
size_t j = 0; j < 3; ++j )
437 size_t vertIndex = triangles.at( i + j );
438 triangleVertices[j] = outNormal.positions.at( vertIndex );
441 for (
size_t j = 0; j < 3; ++j )
442 normals[triangles.at( i + j )] += QVector3D::crossProduct(
443 triangleVertices.at( 1 ) - triangleVertices.at( 0 ),
444 triangleVertices.at( 2 ) - triangleVertices.at( 0 ) );
448 outNormal.normals.resize( ( outNormal.positions.count() ) *
sizeof(
float ) * 3 );
449 float *normPtr =
reinterpret_cast<float *
>( outNormal.normals.data() );
450 for (
int i = 0; i < normals.size(); ++i )
452 QVector3D normal = normals.at( i );
453 normal = normal.normalized();
455 *normPtr++ = normal.x();
456 *normPtr++ = normal.y();
457 *normPtr++ = normal.z();
463 outNormal.triangles.resize( triangleIndexes.size() *
sizeof( quint32 ) );
464 quint32 *indexPtr =
reinterpret_cast<quint32 *
>( outNormal.triangles.data() );
465 size_t effective = 0;
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 |= bbox.
intersects( 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 ) +
493 std::pow( pos.y() - pos2.y(), 2 ) ) > horizontalThreshold;
496 if ( horizontalSkip || verticalSkip )
500 if ( atLeastOneInBox && !horizontalSkip && !verticalSkip )
502 for (
size_t j = 0; j < 3; j++ )
504 size_t vertIndex = triangleIndexes.at( i + j );
505 *indexPtr++ = quint32( vertIndex );
511 if ( effective != 0 )
513 outNormal.triangles.resize( effective * 3 *
sizeof( quint32 ) );
517 outNormal.triangles.clear();
518 outNormal.normals.clear();
524 if ( outNormal.positions.isEmpty() )
531 bbox.
xMin + context.
origin().
x() - outNormal.positionsOrigin.x(),
532 -bbox.
zMax + context.
origin().
y() - outNormal.positionsOrigin.y(),
533 bbox.
yMin + context.
origin().
z() - outNormal.positionsOrigin.z(),
534 bbox.
xMax + context.
origin().
x() - outNormal.positionsOrigin.x(),
535 -bbox.
zMin + context.
origin().
y() - outNormal.positionsOrigin.y(),
536 bbox.
yMax + context.
origin().
z() - outNormal.positionsOrigin.z() );
537 QgsAABB aabbRelativeToChunkOrigin(
538 boxRelativeToChunkOrigin.xMinimum(), boxRelativeToChunkOrigin.yMinimum(), boxRelativeToChunkOrigin.zMinimum(),
539 boxRelativeToChunkOrigin.xMaximum(), boxRelativeToChunkOrigin.yMaximum(), boxRelativeToChunkOrigin.zMaximum() );
542 std::unique_ptr<delaunator::Delaunator> triangulation;
545 std::vector<double> vertices = getVertices( pc, n, context, aabbRelativeToChunkOrigin );
546 triangulation.reset(
new delaunator::Delaunator( vertices ) );
548 catch ( std::exception &e )
552 outNormal = PointData();
553 processNode( pc, n, context );
557 const std::vector<size_t> &triangleIndexes = triangulation->triangles;
559 calculateNormals( triangleIndexes );
560 filterTriangles( triangleIndexes, context, aabbRelativeToChunkOrigin );
565 std::unique_ptr<QgsPointCloudBlock> block;
575 bool loopAborted =
false;
594QgsSingleColorPointCloud3DSymbolHandler::QgsSingleColorPointCloud3DSymbolHandler()
595 : QgsPointCloud3DSymbolHandler()
616 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
620 const char *ptr = block->data();
621 const int count = block->pointCount();
622 const std::size_t recordSize = block->attributes().pointRecordSize();
628 bool alreadyPrintedDebug =
false;
633 output->positionsOrigin = originFromNodeBounds( pc, n, context, block.get() );
635 for (
int i = 0; i < count; ++i )
640 const qint32 ix = *( qint32 * )( ptr + i * recordSize + 0 );
641 const qint32 iy = *( qint32 * )( ptr + i * recordSize + 4 );
642 const qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
644 double x = blockOffset.
x() + blockScale.
x() * ix;
645 double y = blockOffset.
y() + blockScale.
y() * iy;
646 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
653 if ( !alreadyPrintedDebug )
655 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
656 alreadyPrintedDebug =
true;
660 output->positions.push_back( point.
toVector3D() );
666 makeEntity( parent, context, outNormal,
false );
669Qt3DQGeometry *QgsSingleColorPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
671 return new QgsSingleColorPointCloud3DGeometry( parent, data, byteStride );
674QgsColorRampPointCloud3DSymbolHandler::QgsColorRampPointCloud3DSymbolHandler()
675 : QgsPointCloud3DSymbolHandler()
689 const int xOffset = 0;
696 QString attributeName;
697 bool attrIsX =
false;
698 bool attrIsY =
false;
699 bool attrIsZ =
false;
701 int attributeOffset = 0;
705 bool alreadyPrintedDebug =
false;
713 if ( symbol->
attribute() == QLatin1String(
"X" ) )
717 else if ( symbol->
attribute() == QLatin1String(
"Y" ) )
721 else if ( symbol->
attribute() == QLatin1String(
"Z" ) )
730 attributeType = attr->
type();
731 attributeName = attr->
name();
738 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
744 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
748 const char *ptr = block->data();
749 const int count = block->pointCount();
750 const std::size_t recordSize = block->attributes().pointRecordSize();
758 output->positionsOrigin = originFromNodeBounds( pc, n, context, block.get() );
760 for (
int i = 0; i < count; ++i )
765 const qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
766 const qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
767 const qint32 iz = *( qint32 * )( ptr + i * recordSize + zOffset );
769 double x = blockOffset.
x() + blockScale.
x() * ix;
770 double y = blockOffset.
y() + blockScale.
y() * iy;
771 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
778 if ( !alreadyPrintedDebug )
780 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
781 alreadyPrintedDebug =
true;
785 output->positions.push_back( point.
toVector3D() );
788 output->parameter.push_back( x );
790 output->parameter.push_back( y );
792 output->parameter.push_back( z );
796 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
797 output->parameter.push_back( iParam );
804 makeEntity( parent, context, outNormal,
false );
807Qt3DQGeometry *QgsColorRampPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
809 return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );
812QgsRGBPointCloud3DSymbolHandler::QgsRGBPointCloud3DSymbolHandler()
813 : QgsPointCloud3DSymbolHandler()
854 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
858 const char *ptr = block->data();
859 const int count = block->pointCount();
860 const std::size_t recordSize = block->attributes().pointRecordSize();
867 bool alreadyPrintedDebug =
false;
880 output->positionsOrigin = originFromNodeBounds( pc, n, context, block.get() );
885 for (
int i = 0; i < count; ++i )
890 const qint32 ix = *( qint32 * )( ptr + i * recordSize + 0 );
891 const qint32 iy = *( qint32 * )( ptr + i * recordSize + 4 );
892 const qint32 iz = *( qint32 * )( ptr + i * recordSize + 8 );
893 double x = blockOffset.
x() + blockScale.
x() * ix;
894 double y = blockOffset.
y() + blockScale.
y() * iy;
895 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
902 if ( !alreadyPrintedDebug )
904 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
905 alreadyPrintedDebug =
true;
910 QVector3D color( 0.0f, 0.0f, 0.0f );
912 context.
getAttribute( ptr, i * recordSize + redOffset, redType, ir );
913 context.
getAttribute( ptr, i * recordSize + greenOffset, greenType, ig );
914 context.
getAttribute( ptr, i * recordSize + blueOffset, blueType, ib );
925 if ( useRedContrastEnhancement )
929 if ( useGreenContrastEnhancement )
933 if ( useBlueContrastEnhancement )
938 color.setX( ir / 255.0f );
939 color.setY( ig / 255.0f );
940 color.setZ( ib / 255.0f );
942 output->positions.push_back( point.
toVector3D() );
943 output->colors.push_back( color );
949 makeEntity( parent, context, outNormal,
false );
952Qt3DQGeometry *QgsRGBPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
954 return new QgsRGBPointCloud3DGeometry( parent, data, byteStride );
957QgsClassificationPointCloud3DSymbolHandler::QgsClassificationPointCloud3DSymbolHandler()
958 : QgsPointCloud3DSymbolHandler()
972 const int xOffset = 0;
979 QString attributeName;
980 bool attrIsX =
false;
981 bool attrIsY =
false;
982 bool attrIsZ =
false;
984 int attributeOffset = 0;
991 if ( symbol->
attribute() == QLatin1String(
"X" ) )
995 else if ( symbol->
attribute() == QLatin1String(
"Y" ) )
999 else if ( symbol->
attribute() == QLatin1String(
"Z" ) )
1008 attributeType = attr->
type();
1009 attributeName = attr->
name();
1016 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
1022 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
1026 const char *ptr = block->data();
1027 const int count = block->pointCount();
1028 const std::size_t recordSize = block->attributes().pointRecordSize();
1035 bool alreadyPrintedDebug =
false;
1037 QList<QgsPointCloudCategory> categoriesList = symbol->
categoriesList();
1038 QVector<int> categoriesValues;
1039 QHash<int, double> categoriesPointSizes;
1042 categoriesValues.push_back(
c.value() );
1043 categoriesPointSizes.insert(
c.value(),
c.pointSize() > 0 ?
c.pointSize() :
1044 context.symbol() ? context.symbol()->pointSize() : 1.0 );
1048 output = &outNormal;
1050 output->positionsOrigin = originFromNodeBounds( pc, n, context, block.get() );
1053 for (
int i = 0; i < count; ++i )
1058 const qint32 ix = *( qint32 * )( ptr + i * recordSize + xOffset );
1059 const qint32 iy = *( qint32 * )( ptr + i * recordSize + yOffset );
1060 const qint32 iz = *( qint32 * )( ptr + i * recordSize + zOffset );
1062 double x = blockOffset.
x() + blockScale.
x() * ix;
1063 double y = blockOffset.
y() + blockScale.
y() * iy;
1064 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
1071 if ( !alreadyPrintedDebug )
1073 QgsDebugError( QStringLiteral(
"Error transforming point coordinate" ) );
1074 alreadyPrintedDebug =
true;
1078 float iParam = 0.0f;
1086 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
1088 if ( filteredOutValues.contains( (
int ) iParam ) ||
1089 ! categoriesValues.contains( (
int ) iParam ) )
1091 output->positions.push_back( point.
toVector3D() );
1094 float iParam2 = categoriesValues.indexOf( (
int )iParam ) + 1;
1095 output->parameter.push_back( iParam2 );
1096 output->pointSizes.push_back( categoriesPointSizes.value( (
int ) iParam ) );
1102 makeEntity( parent, context, outNormal,
false );
1105Qt3DQGeometry *QgsClassificationPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
1107 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)
float yExtent() const
Returns box width in Y axis.
float xExtent() const
Returns box width in X axis.
bool intersects(const QgsAABB &other) const
Determines whether the box intersects some other axis aligned box.
A 3-dimensional box composed of x, y, z coordinates.
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 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.
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.
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)