20#include "delaunator.hpp"
35#include <Qt3DCore/QAttribute>
36#include <Qt3DCore/QBuffer>
37#include <Qt3DCore/QEntity>
38#include <Qt3DCore/QGeometry>
39#include <Qt3DRender/QEffect>
40#include <Qt3DRender/QGeometryRenderer>
41#include <Qt3DRender/QGraphicsApiFilter>
42#include <Qt3DRender/QParameter>
43#include <Qt3DRender/QShaderProgram>
44#include <Qt3DRender/QTechnique>
46#include "moc_qgspointcloud3dsymbol_p.cpp"
48using namespace Qt::StringLiterals;
56 double nodeOriginX = bounds.
xMinimum();
57 double nodeOriginY = bounds.
yMinimum();
67 return QgsVector3D( nodeOriginX, nodeOriginY, nodeOriginZ );
71QgsPointCloud3DGeometry::QgsPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
73 , mPositionAttribute( new
Qt3DCore::QAttribute( this ) )
74 , mParameterAttribute( new
Qt3DCore::QAttribute( this ) )
75 , mPointSizeAttribute( new
Qt3DCore::QAttribute( this ) )
76 , mColorAttribute( new
Qt3DCore::QAttribute( this ) )
77 , mTriangleIndexAttribute( new
Qt3DCore::QAttribute( this ) )
78 , mNormalsAttribute( new
Qt3DCore::QAttribute( this ) )
79 , mVertexBuffer( new
Qt3DCore::QBuffer( this ) )
80 , mByteStride( byteStride )
82 if ( !data.triangles.isEmpty() )
84 mTriangleBuffer = new Qt3DCore::QBuffer( this );
85 mTriangleIndexAttribute->setAttributeType( Qt3DCore::QAttribute::IndexAttribute );
86 mTriangleIndexAttribute->setBuffer( mTriangleBuffer );
87 mTriangleIndexAttribute->setVertexBaseType( Qt3DCore::QAttribute::UnsignedInt );
88 mTriangleBuffer->setData( data.triangles );
89 mTriangleIndexAttribute->setCount( data.triangles.size() / sizeof( quint32 ) );
90 addAttribute( mTriangleIndexAttribute );
93 if ( !data.normals.isEmpty() )
95 mNormalsBuffer = new Qt3DCore::QBuffer( this );
96 mNormalsAttribute->setName( Qt3DCore::QAttribute::defaultNormalAttributeName() );
97 mNormalsAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
98 mNormalsAttribute->setVertexSize( 3 );
99 mNormalsAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
100 mNormalsAttribute->setBuffer( mNormalsBuffer );
101 mNormalsBuffer->setData( data.normals );
102 mNormalsAttribute->setCount( data.normals.size() / ( 3 * sizeof( float ) ) );
103 addAttribute( mNormalsAttribute );
107QgsSingleColorPointCloud3DGeometry::QgsSingleColorPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
108 : QgsPointCloud3DGeometry( parent, data, byteStride )
110 mPositionAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
111 mPositionAttribute->setBuffer( mVertexBuffer );
112 mPositionAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
113 mPositionAttribute->setVertexSize( 3 );
114 mPositionAttribute->setName( Qt3DCore::QAttribute::defaultPositionAttributeName() );
115 mPositionAttribute->setByteOffset( 0 );
116 mPositionAttribute->setByteStride( mByteStride );
117 addAttribute( mPositionAttribute );
118 makeVertexBuffer( data );
121void QgsSingleColorPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
123 QByteArray vertexBufferData;
124 vertexBufferData.resize( data.positions.size() * mByteStride );
125 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
127 for (
int i = 0; i < data.positions.size(); ++i )
129 rawVertexArray[idx++] = data.positions.at( i ).x();
130 rawVertexArray[idx++] = data.positions.at( i ).y();
131 rawVertexArray[idx++] = data.positions.at( i ).z();
134 mVertexCount = data.positions.size();
135 mVertexBuffer->setData( vertexBufferData );
138QgsColorRampPointCloud3DGeometry::QgsColorRampPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
139 : QgsPointCloud3DGeometry( parent, data, byteStride )
141 mPositionAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
142 mPositionAttribute->setBuffer( mVertexBuffer );
143 mPositionAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
144 mPositionAttribute->setVertexSize( 3 );
145 mPositionAttribute->setName( Qt3DCore::QAttribute::defaultPositionAttributeName() );
146 mPositionAttribute->setByteOffset( 0 );
147 mPositionAttribute->setByteStride( mByteStride );
148 addAttribute( mPositionAttribute );
149 mParameterAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
150 mParameterAttribute->setBuffer( mVertexBuffer );
151 mParameterAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
152 mParameterAttribute->setVertexSize( 1 );
153 mParameterAttribute->setName(
"vertexParameter" );
154 mParameterAttribute->setByteOffset( 12 );
155 mParameterAttribute->setByteStride( mByteStride );
156 addAttribute( mParameterAttribute );
157 makeVertexBuffer( data );
160void QgsColorRampPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
162 QByteArray vertexBufferData;
163 vertexBufferData.resize( data.positions.size() * mByteStride );
164 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
166 Q_ASSERT( data.positions.size() == data.parameter.size() );
167 for (
int i = 0; i < data.positions.size(); ++i )
169 rawVertexArray[idx++] = data.positions.at( i ).x();
170 rawVertexArray[idx++] = data.positions.at( i ).y();
171 rawVertexArray[idx++] = data.positions.at( i ).z();
172 rawVertexArray[idx++] = data.parameter.at( i );
175 mVertexCount = data.positions.size();
176 mVertexBuffer->setData( vertexBufferData );
179QgsRGBPointCloud3DGeometry::QgsRGBPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
180 : QgsPointCloud3DGeometry( parent, data, byteStride )
182 mPositionAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
183 mPositionAttribute->setBuffer( mVertexBuffer );
184 mPositionAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
185 mPositionAttribute->setVertexSize( 3 );
186 mPositionAttribute->setName( Qt3DCore::QAttribute::defaultPositionAttributeName() );
187 mPositionAttribute->setByteOffset( 0 );
188 mPositionAttribute->setByteStride( mByteStride );
189 addAttribute( mPositionAttribute );
190 mColorAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
191 mColorAttribute->setBuffer( mVertexBuffer );
192 mColorAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
193 mColorAttribute->setVertexSize( 3 );
194 mColorAttribute->setName( u
"vertexColor"_s );
195 mColorAttribute->setByteOffset( 12 );
196 mColorAttribute->setByteStride( mByteStride );
197 addAttribute( mColorAttribute );
198 makeVertexBuffer( data );
201void QgsRGBPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
203 QByteArray vertexBufferData;
204 vertexBufferData.resize( data.positions.size() * mByteStride );
205 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
207 Q_ASSERT( data.positions.size() == data.colors.size() );
208 for (
int i = 0; i < data.positions.size(); ++i )
210 rawVertexArray[idx++] = data.positions.at( i ).x();
211 rawVertexArray[idx++] = data.positions.at( i ).y();
212 rawVertexArray[idx++] = data.positions.at( i ).z();
213 rawVertexArray[idx++] = data.colors.at( i ).x();
214 rawVertexArray[idx++] = data.colors.at( i ).y();
215 rawVertexArray[idx++] = data.colors.at( i ).z();
217 mVertexCount = data.positions.size();
218 mVertexBuffer->setData( vertexBufferData );
221QgsClassificationPointCloud3DGeometry::QgsClassificationPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
222 : QgsPointCloud3DGeometry( parent, data, byteStride )
224 mPositionAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
225 mPositionAttribute->setBuffer( mVertexBuffer );
226 mPositionAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
227 mPositionAttribute->setVertexSize( 3 );
228 mPositionAttribute->setName( Qt3DCore::QAttribute::defaultPositionAttributeName() );
229 mPositionAttribute->setByteOffset( 0 );
230 mPositionAttribute->setByteStride( mByteStride );
231 addAttribute( mPositionAttribute );
232 mParameterAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
233 mParameterAttribute->setBuffer( mVertexBuffer );
234 mParameterAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
235 mParameterAttribute->setVertexSize( 1 );
236 mParameterAttribute->setName(
"vertexParameter" );
237 mParameterAttribute->setByteOffset( 12 );
238 mParameterAttribute->setByteStride( mByteStride );
239 addAttribute( mParameterAttribute );
240 mPointSizeAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
241 mPointSizeAttribute->setBuffer( mVertexBuffer );
242 mPointSizeAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
243 mPointSizeAttribute->setVertexSize( 1 );
244 mPointSizeAttribute->setName(
"vertexSize" );
245 mPointSizeAttribute->setByteOffset( 16 );
246 mPointSizeAttribute->setByteStride( mByteStride );
247 addAttribute( mPointSizeAttribute );
248 makeVertexBuffer( data );
251void QgsClassificationPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
253 QByteArray vertexBufferData;
254 vertexBufferData.resize( data.positions.size() * mByteStride );
255 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
257 Q_ASSERT( data.positions.size() == data.parameter.size() );
258 Q_ASSERT( data.positions.size() == data.pointSizes.size() );
259 for (
int i = 0; i < data.positions.size(); ++i )
261 rawVertexArray[idx++] = data.positions.at( i ).x();
262 rawVertexArray[idx++] = data.positions.at( i ).y();
263 rawVertexArray[idx++] = data.positions.at( i ).z();
264 rawVertexArray[idx++] = data.parameter.at( i );
265 rawVertexArray[idx++] = data.pointSizes.at( i );
268 mVertexCount = data.positions.size();
269 mVertexBuffer->setData( vertexBufferData );
272QgsPointCloud3DSymbolHandler::QgsPointCloud3DSymbolHandler()
276void QgsPointCloud3DSymbolHandler::makeEntity(
277 Qt3DCore::QEntity *parent,
const QgsPointCloud3DRenderContext &context,
const QgsPointCloud3DSymbolHandler::PointData &out,
bool selected,
const QStringList &shaderDefines
282 if ( out.positions.empty() )
285 const bool isTriangulated = !out.triangles.isEmpty();
288 Qt3DCore::QGeometry *geom = makeGeometry( parent, out, context.
symbol()->
byteStride() );
289 Qt3DRender::QGeometryRenderer *gr =
new Qt3DRender::QGeometryRenderer;
292 gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
293 gr->setVertexCount( out.triangles.size() /
sizeof( quint32 ) );
297 gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
298 gr->setVertexCount( out.positions.count() );
300 gr->setGeometry( geom );
304 QgsGeoTransform *tr =
new QgsGeoTransform;
305 tr->setGeoTranslation( out.positionsOrigin );
312 Qt3DRender::QShaderProgram *shaderProgram =
new Qt3DRender::QShaderProgram( mat );
313 const QByteArray vertCode = Qt3DRender::QShaderProgram::loadSource( QUrl( u
"qrc:/shaders/pointcloud.vert"_s ) );
314 const QByteArray fragCode = Qt3DRender::QShaderProgram::loadSource( QUrl( u
"qrc:/shaders/pointcloud.frag"_s ) );
315 QStringList defines = shaderDefines;
316 if ( isTriangulated )
318 defines << u
"TRIANGULATE"_s;
323 Qt3DRender::QRenderPass *renderPass =
new Qt3DRender::QRenderPass( mat );
324 renderPass->setShaderProgram( shaderProgram );
326 if ( !isTriangulated )
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( u
"renderingStyle"_s );
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 );
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( triangleVertices.at( 1 ) - triangleVertices.at( 0 ), triangleVertices.at( 2 ) - triangleVertices.at( 0 ) );
443 outNormal.normals.resize( ( outNormal.positions.count() ) *
sizeof(
float ) * 3 );
444 float *normPtr =
reinterpret_cast<float *
>( outNormal.normals.data() );
445 for (
int i = 0; i < normals.size(); ++i )
447 QVector3D normal = normals.at( i );
448 normal = normal.normalized();
450 *normPtr++ = normal.x();
451 *normPtr++ = normal.y();
452 *normPtr++ = normal.z();
458 outNormal.triangles.resize( triangleIndexes.size() *
sizeof( quint32 ) );
459 quint32 *indexPtr =
reinterpret_cast<quint32 *
>( outNormal.triangles.data() );
460 size_t effective = 0;
467 QgsBox3D boxRelativeToChunkOrigin = box3D - outNormal.positionsOrigin;
469 for (
size_t i = 0; i < triangleIndexes.size(); i += 3 )
471 bool atLeastOneInBox =
false;
472 bool horizontalSkip =
false;
473 bool verticalSkip =
false;
474 for (
size_t j = 0; j < 3; j++ )
476 QVector3D pos = outNormal.positions.at( triangleIndexes.at( i + j ) );
477 atLeastOneInBox |= boxRelativeToChunkOrigin.
contains( pos.x(), pos.y(), pos.z() );
479 if ( verticalFilter || horizontalFilter )
481 const QVector3D pos2 = outNormal.positions.at( triangleIndexes.at( i + ( j + 1 ) % 3 ) );
483 if ( verticalFilter )
484 verticalSkip |= std::fabs( pos.z() - pos2.z() ) > verticalThreshold;
486 if ( horizontalFilter && !verticalSkip )
489 horizontalSkip |= sqrt( std::pow( pos.x() - pos2.x(), 2 ) + std::pow( pos.y() - pos2.y(), 2 ) ) > horizontalThreshold;
492 if ( horizontalSkip || verticalSkip )
496 if ( atLeastOneInBox && !horizontalSkip && !verticalSkip )
498 for (
size_t j = 0; j < 3; j++ )
500 size_t vertIndex = triangleIndexes.at( i + j );
501 *indexPtr++ = quint32( vertIndex );
507 if ( effective != 0 )
509 outNormal.triangles.resize( effective * 3 *
sizeof( quint32 ) );
513 outNormal.triangles.clear();
514 outNormal.normals.clear();
520 if ( outNormal.positions.isEmpty() )
524 std::unique_ptr<delaunator::Delaunator> triangulation;
527 std::vector<double> vertices = getVertices( pc, n, context, box3D );
528 triangulation = std::make_unique<delaunator::Delaunator>( vertices );
530 catch ( std::exception &e )
534 outNormal = PointData();
535 processNode( pc, n, context );
539 const std::vector<size_t> &triangleIndexes = triangulation->triangles;
541 calculateNormals( triangleIndexes );
542 filterTriangles( triangleIndexes, context, box3D );
545std::unique_ptr<QgsPointCloudBlock> QgsPointCloud3DSymbolHandler::pointCloudBlock(
549 std::unique_ptr<QgsPointCloudBlock> block;
560 bool loopAborted =
false;
578QgsSingleColorPointCloud3DSymbolHandler::QgsSingleColorPointCloud3DSymbolHandler()
579 : QgsPointCloud3DSymbolHandler()
598 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
602 const char *ptr = block->data();
603 const int count = block->pointCount();
604 const std::size_t recordSize = block->attributes().pointRecordSize();
610 bool alreadyPrintedDebug =
false;
615 output->positionsOrigin = originFromNodeBounds( pc, n, context );
617 for (
int i = 0; i < count; ++i )
622 const qint32 ix = *( qint32 * ) ( ptr + i * recordSize + 0 );
623 const qint32 iy = *( qint32 * ) ( ptr + i * recordSize + 4 );
624 const qint32 iz = *( qint32 * ) ( ptr + i * recordSize + 8 );
626 double x = blockOffset.
x() + blockScale.
x() * ix;
627 double y = blockOffset.
y() + blockScale.
y() * iy;
628 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
635 if ( !alreadyPrintedDebug )
638 alreadyPrintedDebug =
true;
642 output->positions.push_back( point.
toVector3D() );
648 makeEntity( parent, context, outNormal,
false, { u
"STYLE_SINGLE_COLOR"_s } );
651Qt3DCore::QGeometry *QgsSingleColorPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
653 return new QgsSingleColorPointCloud3DGeometry( parent, data, byteStride );
656QgsColorRampPointCloud3DSymbolHandler::QgsColorRampPointCloud3DSymbolHandler()
657 : QgsPointCloud3DSymbolHandler()
669 const int xOffset = 0;
676 QString attributeName;
677 bool attrIsX =
false;
678 bool attrIsY =
false;
679 bool attrIsZ =
false;
681 int attributeOffset = 0;
685 bool alreadyPrintedDebug =
false;
697 else if ( symbol->
attribute() ==
"Y"_L1 )
701 else if ( symbol->
attribute() ==
"Z"_L1 )
710 attributeType = attr->
type();
711 attributeName = attr->
name();
718 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
724 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
728 const char *ptr = block->data();
729 const int count = block->pointCount();
730 const std::size_t recordSize = block->attributes().pointRecordSize();
738 output->positionsOrigin = originFromNodeBounds( pc, n, context );
740 for (
int i = 0; i < count; ++i )
745 const qint32 ix = *( qint32 * ) ( ptr + i * recordSize + xOffset );
746 const qint32 iy = *( qint32 * ) ( ptr + i * recordSize + yOffset );
747 const qint32 iz = *( qint32 * ) ( ptr + i * recordSize + zOffset );
749 double x = blockOffset.
x() + blockScale.
x() * ix;
750 double y = blockOffset.
y() + blockScale.
y() * iy;
751 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
758 if ( !alreadyPrintedDebug )
761 alreadyPrintedDebug =
true;
765 output->positions.push_back( point.
toVector3D() );
768 output->parameter.push_back( x );
770 output->parameter.push_back( y );
772 output->parameter.push_back( z );
776 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
777 output->parameter.push_back( iParam );
784 makeEntity( parent, context, outNormal,
false, { u
"STYLE_COLOR_RAMP"_s } );
787Qt3DCore::QGeometry *QgsColorRampPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
789 return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );
792QgsRGBPointCloud3DSymbolHandler::QgsRGBPointCloud3DSymbolHandler()
793 : QgsPointCloud3DSymbolHandler()
832 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
836 const char *ptr = block->data();
837 const int count = block->pointCount();
838 const std::size_t recordSize = block->attributes().pointRecordSize();
845 bool alreadyPrintedDebug =
false;
858 output->positionsOrigin = originFromNodeBounds( pc, n, context );
863 for (
int i = 0; i < count; ++i )
868 const qint32 ix = *( qint32 * ) ( ptr + i * recordSize + 0 );
869 const qint32 iy = *( qint32 * ) ( ptr + i * recordSize + 4 );
870 const qint32 iz = *( qint32 * ) ( ptr + i * recordSize + 8 );
871 double x = blockOffset.
x() + blockScale.
x() * ix;
872 double y = blockOffset.
y() + blockScale.
y() * iy;
873 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
880 if ( !alreadyPrintedDebug )
883 alreadyPrintedDebug =
true;
888 QVector3D color( 0.0f, 0.0f, 0.0f );
890 context.
getAttribute( ptr, i * recordSize + redOffset, redType, ir );
891 context.
getAttribute( ptr, i * recordSize + greenOffset, greenType, ig );
892 context.
getAttribute( ptr, i * recordSize + blueOffset, blueType, ib );
903 if ( useRedContrastEnhancement )
907 if ( useGreenContrastEnhancement )
911 if ( useBlueContrastEnhancement )
917 color.setX( linear.redF() );
918 color.setY( linear.greenF() );
919 color.setZ( linear.blueF() );
921 output->positions.push_back( point.
toVector3D() );
922 output->colors.push_back( color );
928 makeEntity( parent, context, outNormal,
false, { u
"STYLE_RGB"_s } );
931Qt3DCore::QGeometry *QgsRGBPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
933 return new QgsRGBPointCloud3DGeometry( parent, data, byteStride );
936QgsClassificationPointCloud3DSymbolHandler::QgsClassificationPointCloud3DSymbolHandler()
937 : QgsPointCloud3DSymbolHandler()
949 const int xOffset = 0;
956 QString attributeName;
957 bool attrIsX =
false;
958 bool attrIsY =
false;
959 bool attrIsZ =
false;
961 int attributeOffset = 0;
973 else if ( symbol->
attribute() ==
"Y"_L1 )
977 else if ( symbol->
attribute() ==
"Z"_L1 )
986 attributeType = attr->
type();
987 attributeName = attr->
name();
993 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
999 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
1003 const char *ptr = block->data();
1004 const int count = block->pointCount();
1005 const std::size_t recordSize = block->attributes().pointRecordSize();
1012 bool alreadyPrintedDebug =
false;
1014 QList<QgsPointCloudCategory> categoriesList = symbol->
categoriesList();
1015 QVector<int> categoriesValues;
1016 QHash<int, double> categoriesPointSizes;
1019 categoriesValues.push_back(
c.value() );
1020 categoriesPointSizes.insert(
c.value(),
c.pointSize() > 0 ?
c.pointSize() : context.
symbol() ? context.
symbol()->
pointSize() : 1.0 );
1024 output = &outNormal;
1026 output->positionsOrigin = originFromNodeBounds( pc, n, context );
1029 for (
int i = 0; i < count; ++i )
1034 const qint32 ix = *( qint32 * ) ( ptr + i * recordSize + xOffset );
1035 const qint32 iy = *( qint32 * ) ( ptr + i * recordSize + yOffset );
1036 const qint32 iz = *( qint32 * ) ( ptr + i * recordSize + zOffset );
1038 double x = blockOffset.
x() + blockScale.
x() * ix;
1039 double y = blockOffset.
y() + blockScale.
y() * iy;
1040 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
1047 if ( !alreadyPrintedDebug )
1050 alreadyPrintedDebug =
true;
1054 float iParam = 0.0f;
1062 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
1064 if ( filteredOutValues.contains( (
int ) iParam ) || !categoriesValues.contains( (
int ) iParam ) )
1066 output->positions.push_back( point.
toVector3D() );
1069 float iParam2 = categoriesValues.indexOf( (
int ) iParam ) + 1;
1070 output->parameter.push_back( iParam2 );
1071 output->pointSizes.push_back( categoriesPointSizes.value( (
int ) iParam ) );
1077 makeEntity( parent, context, outNormal,
false, { u
"STYLE_CLASSIFICATION"_s } );
1080Qt3DCore::QGeometry *QgsClassificationPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
1082 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.
static QByteArray addDefinesToShaderCode(const QByteArray &shaderCode, const QStringList &defines)
Inserts some define macros into a shader source code.
static QColor srgbToLinear(const QColor &color)
Converts a SRGB color to a linear color.
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.
virtual void fillMaterial(QgsMaterial *material) SIP_SKIP=0
Used to fill material object with necessary QParameters (and consequently opengl uniforms).
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.
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.
std::unique_ptr< QgsPointCloudBlock > nodeData(QgsPointCloudNodeId n, const QgsPointCloudRequest &request)
Returns node data block.
QgsPointCloudNode getNode(QgsPointCloudNodeId id) const
Returns object for a given node.
QgsPointCloudBlockRequest * asyncNodeData(QgsPointCloudNodeId n, const QgsPointCloudRequest &request)
Returns a handle responsible for loading a node data block.
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
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)