20#include "delaunator.hpp"
34#include <Qt3DCore/QAttribute>
35#include <Qt3DCore/QBuffer>
36#include <Qt3DCore/QEntity>
37#include <Qt3DCore/QGeometry>
38#include <Qt3DRender/QEffect>
39#include <Qt3DRender/QGeometryRenderer>
40#include <Qt3DRender/QGraphicsApiFilter>
41#include <Qt3DRender/QParameter>
42#include <Qt3DRender/QShaderProgram>
43#include <Qt3DRender/QTechnique>
45#include "moc_qgspointcloud3dsymbol_p.cpp"
47using namespace Qt::StringLiterals;
55 double nodeOriginX = bounds.
xMinimum();
56 double nodeOriginY = bounds.
yMinimum();
66 return QgsVector3D( nodeOriginX, nodeOriginY, nodeOriginZ );
70QgsPointCloud3DGeometry::QgsPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
72 , mPositionAttribute( new
Qt3DCore::QAttribute( this ) )
73 , mParameterAttribute( new
Qt3DCore::QAttribute( this ) )
74 , mPointSizeAttribute( new
Qt3DCore::QAttribute( this ) )
75 , mColorAttribute( new
Qt3DCore::QAttribute( this ) )
76 , mTriangleIndexAttribute( new
Qt3DCore::QAttribute( this ) )
77 , mNormalsAttribute( new
Qt3DCore::QAttribute( this ) )
78 , mVertexBuffer( new
Qt3DCore::QBuffer( this ) )
79 , mByteStride( byteStride )
81 if ( !data.triangles.isEmpty() )
83 mTriangleBuffer = new Qt3DCore::QBuffer( this );
84 mTriangleIndexAttribute->setAttributeType( Qt3DCore::QAttribute::IndexAttribute );
85 mTriangleIndexAttribute->setBuffer( mTriangleBuffer );
86 mTriangleIndexAttribute->setVertexBaseType( Qt3DCore::QAttribute::UnsignedInt );
87 mTriangleBuffer->setData( data.triangles );
88 mTriangleIndexAttribute->setCount( data.triangles.size() / sizeof( quint32 ) );
89 addAttribute( mTriangleIndexAttribute );
92 if ( !data.normals.isEmpty() )
94 mNormalsBuffer = new Qt3DCore::QBuffer( this );
95 mNormalsAttribute->setName( Qt3DCore::QAttribute::defaultNormalAttributeName() );
96 mNormalsAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
97 mNormalsAttribute->setVertexSize( 3 );
98 mNormalsAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
99 mNormalsAttribute->setBuffer( mNormalsBuffer );
100 mNormalsBuffer->setData( data.normals );
101 mNormalsAttribute->setCount( data.normals.size() / ( 3 * sizeof( float ) ) );
102 addAttribute( mNormalsAttribute );
106QgsSingleColorPointCloud3DGeometry::QgsSingleColorPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
107 : QgsPointCloud3DGeometry( parent, data, byteStride )
109 mPositionAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
110 mPositionAttribute->setBuffer( mVertexBuffer );
111 mPositionAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
112 mPositionAttribute->setVertexSize( 3 );
113 mPositionAttribute->setName( Qt3DCore::QAttribute::defaultPositionAttributeName() );
114 mPositionAttribute->setByteOffset( 0 );
115 mPositionAttribute->setByteStride( mByteStride );
116 addAttribute( mPositionAttribute );
117 makeVertexBuffer( data );
120void QgsSingleColorPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
122 QByteArray vertexBufferData;
123 vertexBufferData.resize( data.positions.size() * mByteStride );
124 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
126 for (
int i = 0; i < data.positions.size(); ++i )
128 rawVertexArray[idx++] = data.positions.at( i ).x();
129 rawVertexArray[idx++] = data.positions.at( i ).y();
130 rawVertexArray[idx++] = data.positions.at( i ).z();
133 mVertexCount = data.positions.size();
134 mVertexBuffer->setData( vertexBufferData );
137QgsColorRampPointCloud3DGeometry::QgsColorRampPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
138 : QgsPointCloud3DGeometry( parent, data, byteStride )
140 mPositionAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
141 mPositionAttribute->setBuffer( mVertexBuffer );
142 mPositionAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
143 mPositionAttribute->setVertexSize( 3 );
144 mPositionAttribute->setName( Qt3DCore::QAttribute::defaultPositionAttributeName() );
145 mPositionAttribute->setByteOffset( 0 );
146 mPositionAttribute->setByteStride( mByteStride );
147 addAttribute( mPositionAttribute );
148 mParameterAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
149 mParameterAttribute->setBuffer( mVertexBuffer );
150 mParameterAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
151 mParameterAttribute->setVertexSize( 1 );
152 mParameterAttribute->setName(
"vertexParameter" );
153 mParameterAttribute->setByteOffset( 12 );
154 mParameterAttribute->setByteStride( mByteStride );
155 addAttribute( mParameterAttribute );
156 makeVertexBuffer( data );
159void QgsColorRampPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
161 QByteArray vertexBufferData;
162 vertexBufferData.resize( data.positions.size() * mByteStride );
163 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
165 Q_ASSERT( data.positions.size() == data.parameter.size() );
166 for (
int i = 0; i < data.positions.size(); ++i )
168 rawVertexArray[idx++] = data.positions.at( i ).x();
169 rawVertexArray[idx++] = data.positions.at( i ).y();
170 rawVertexArray[idx++] = data.positions.at( i ).z();
171 rawVertexArray[idx++] = data.parameter.at( i );
174 mVertexCount = data.positions.size();
175 mVertexBuffer->setData( vertexBufferData );
178QgsRGBPointCloud3DGeometry::QgsRGBPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
179 : QgsPointCloud3DGeometry( parent, data, byteStride )
181 mPositionAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
182 mPositionAttribute->setBuffer( mVertexBuffer );
183 mPositionAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
184 mPositionAttribute->setVertexSize( 3 );
185 mPositionAttribute->setName( Qt3DCore::QAttribute::defaultPositionAttributeName() );
186 mPositionAttribute->setByteOffset( 0 );
187 mPositionAttribute->setByteStride( mByteStride );
188 addAttribute( mPositionAttribute );
189 mColorAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
190 mColorAttribute->setBuffer( mVertexBuffer );
191 mColorAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
192 mColorAttribute->setVertexSize( 3 );
193 mColorAttribute->setName( u
"vertexColor"_s );
194 mColorAttribute->setByteOffset( 12 );
195 mColorAttribute->setByteStride( mByteStride );
196 addAttribute( mColorAttribute );
197 makeVertexBuffer( data );
200void QgsRGBPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
202 QByteArray vertexBufferData;
203 vertexBufferData.resize( data.positions.size() * mByteStride );
204 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
206 Q_ASSERT( data.positions.size() == data.colors.size() );
207 for (
int i = 0; i < data.positions.size(); ++i )
209 rawVertexArray[idx++] = data.positions.at( i ).x();
210 rawVertexArray[idx++] = data.positions.at( i ).y();
211 rawVertexArray[idx++] = data.positions.at( i ).z();
212 rawVertexArray[idx++] = data.colors.at( i ).x();
213 rawVertexArray[idx++] = data.colors.at( i ).y();
214 rawVertexArray[idx++] = data.colors.at( i ).z();
216 mVertexCount = data.positions.size();
217 mVertexBuffer->setData( vertexBufferData );
220QgsClassificationPointCloud3DGeometry::QgsClassificationPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
221 : QgsPointCloud3DGeometry( parent, data, byteStride )
223 mPositionAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
224 mPositionAttribute->setBuffer( mVertexBuffer );
225 mPositionAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
226 mPositionAttribute->setVertexSize( 3 );
227 mPositionAttribute->setName( Qt3DCore::QAttribute::defaultPositionAttributeName() );
228 mPositionAttribute->setByteOffset( 0 );
229 mPositionAttribute->setByteStride( mByteStride );
230 addAttribute( mPositionAttribute );
231 mParameterAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
232 mParameterAttribute->setBuffer( mVertexBuffer );
233 mParameterAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
234 mParameterAttribute->setVertexSize( 1 );
235 mParameterAttribute->setName(
"vertexParameter" );
236 mParameterAttribute->setByteOffset( 12 );
237 mParameterAttribute->setByteStride( mByteStride );
238 addAttribute( mParameterAttribute );
239 mPointSizeAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
240 mPointSizeAttribute->setBuffer( mVertexBuffer );
241 mPointSizeAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
242 mPointSizeAttribute->setVertexSize( 1 );
243 mPointSizeAttribute->setName(
"vertexSize" );
244 mPointSizeAttribute->setByteOffset( 16 );
245 mPointSizeAttribute->setByteStride( mByteStride );
246 addAttribute( mPointSizeAttribute );
247 makeVertexBuffer( data );
250void QgsClassificationPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
252 QByteArray vertexBufferData;
253 vertexBufferData.resize( data.positions.size() * mByteStride );
254 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
256 Q_ASSERT( data.positions.size() == data.parameter.size() );
257 Q_ASSERT( data.positions.size() == data.pointSizes.size() );
258 for (
int i = 0; i < data.positions.size(); ++i )
260 rawVertexArray[idx++] = data.positions.at( i ).x();
261 rawVertexArray[idx++] = data.positions.at( i ).y();
262 rawVertexArray[idx++] = data.positions.at( i ).z();
263 rawVertexArray[idx++] = data.parameter.at( i );
264 rawVertexArray[idx++] = data.pointSizes.at( i );
267 mVertexCount = data.positions.size();
268 mVertexBuffer->setData( vertexBufferData );
271QgsPointCloud3DSymbolHandler::QgsPointCloud3DSymbolHandler()
275void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent,
const QgsPointCloud3DRenderContext &context,
const QgsPointCloud3DSymbolHandler::PointData &out,
bool selected )
279 if ( out.positions.empty() )
283 Qt3DCore::QGeometry *geom = makeGeometry( parent, out, context.
symbol()->
byteStride() );
284 Qt3DRender::QGeometryRenderer *gr =
new Qt3DRender::QGeometryRenderer;
287 gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Triangles );
288 gr->setVertexCount( out.triangles.size() /
sizeof( quint32 ) );
292 gr->setPrimitiveType( Qt3DRender::QGeometryRenderer::Points );
293 gr->setVertexCount( out.positions.count() );
295 gr->setGeometry( geom );
299 QgsGeoTransform *tr =
new QgsGeoTransform;
300 tr->setGeoTranslation( out.positionsOrigin );
307 Qt3DRender::QShaderProgram *shaderProgram =
new Qt3DRender::QShaderProgram( mat );
308 shaderProgram->setVertexShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( u
"qrc:/shaders/pointcloud.vert"_s ) ) );
309 shaderProgram->setFragmentShaderCode( Qt3DRender::QShaderProgram::loadSource( QUrl( u
"qrc:/shaders/pointcloud.frag"_s ) ) );
311 Qt3DRender::QRenderPass *renderPass =
new Qt3DRender::QRenderPass( mat );
312 renderPass->setShaderProgram( shaderProgram );
314 if ( out.triangles.isEmpty() )
316 Qt3DRender::QPointSize *pointSize =
new Qt3DRender::QPointSize( renderPass );
317 pointSize->setSizeMode( Qt3DRender::QPointSize::Programmable );
318 renderPass->addRenderState( pointSize );
322 Qt3DRender::QFilterKey *filterKey =
new Qt3DRender::QFilterKey;
323 filterKey->setName( u
"renderingStyle"_s );
324 filterKey->setValue(
"forward" );
326 Qt3DRender::QTechnique *technique =
new Qt3DRender::QTechnique;
327 technique->addRenderPass( renderPass );
328 technique->addFilterKey( filterKey );
329 technique->graphicsApiFilter()->setApi( Qt3DRender::QGraphicsApiFilter::OpenGL );
330 technique->graphicsApiFilter()->setProfile( Qt3DRender::QGraphicsApiFilter::CoreProfile );
331 technique->graphicsApiFilter()->setMajorVersion( 3 );
332 technique->graphicsApiFilter()->setMinorVersion( 1 );
333 technique->addParameter(
new Qt3DRender::QParameter(
"triangulate", !out.triangles.isEmpty() ) );
335 Qt3DRender::QEffect *eff =
new Qt3DRender::QEffect;
336 eff->addTechnique( technique );
337 mat->setEffect( eff );
340 Qt3DCore::QEntity *entity =
new Qt3DCore::QEntity;
341 entity->addComponent( gr );
342 entity->addComponent( tr );
343 entity->addComponent( mat );
344 entity->setParent( parent );
352 bool hasColorData = !outNormal.colors.empty();
353 bool hasParameterData = !outNormal.parameter.empty();
354 bool hasPointSizeData = !outNormal.pointSizes.empty();
357 std::vector<double> vertices( outNormal.positions.size() * 2 );
359 for (
int i = 0; i < outNormal.positions.size(); ++i )
361 vertices[idx++] = outNormal.positions.at( i ).x();
362 vertices[idx++] = -outNormal.positions.at( i ).y();
368 double span = pc.
span();
371 double extraBoxFactor = 16 / span;
374 QgsRectangle rectRelativeToChunkOrigin = ( box3D - outNormal.positionsOrigin ).toRectangle();
375 rectRelativeToChunkOrigin.
grow( extraBoxFactor * std::max( box3D.
width(), box3D.
height() ) );
377 PointData filteredExtraPointData;
378 while ( parentNode.
d() >= 0 )
380 PointData outputParent;
381 processNode( pc, parentNode, context, &outputParent );
384 QVector3D originDifference = ( outputParent.positionsOrigin - outNormal.positionsOrigin ).toVector3D();
386 for (
int i = 0; i < outputParent.positions.count(); ++i )
388 const QVector3D pos = outputParent.positions.at( i ) + originDifference;
389 if ( rectRelativeToChunkOrigin.
contains( pos.x(), pos.y() ) )
391 filteredExtraPointData.positions.append( pos );
392 vertices.push_back( pos.x() );
393 vertices.push_back( -pos.y() );
396 filteredExtraPointData.colors.append( outputParent.colors.at( i ) );
397 if ( hasParameterData )
398 filteredExtraPointData.parameter.append( outputParent.parameter.at( i ) );
399 if ( hasPointSizeData )
400 filteredExtraPointData.pointSizes.append( outputParent.pointSizes.at( i ) );
407 outNormal.positions.append( filteredExtraPointData.positions );
408 outNormal.colors.append( filteredExtraPointData.colors );
409 outNormal.parameter.append( filteredExtraPointData.parameter );
410 outNormal.pointSizes.append( filteredExtraPointData.pointSizes );
415void QgsPointCloud3DSymbolHandler::calculateNormals(
const std::vector<size_t> &triangles )
417 QVector<QVector3D> normals( outNormal.positions.count(), QVector3D( 0.0, 0.0, 0.0 ) );
418 for (
size_t i = 0; i < triangles.size(); i += 3 )
420 QVector<QVector3D> triangleVertices( 3 );
421 for (
size_t j = 0; j < 3; ++j )
423 size_t vertIndex = triangles.at( i + j );
424 triangleVertices[j] = outNormal.positions.at( vertIndex );
427 for (
size_t j = 0; j < 3; ++j )
428 normals[triangles.at( i + j )] += QVector3D::crossProduct( triangleVertices.at( 1 ) - triangleVertices.at( 0 ), triangleVertices.at( 2 ) - triangleVertices.at( 0 ) );
432 outNormal.normals.resize( ( outNormal.positions.count() ) *
sizeof(
float ) * 3 );
433 float *normPtr =
reinterpret_cast<float *
>( outNormal.normals.data() );
434 for (
int i = 0; i < normals.size(); ++i )
436 QVector3D normal = normals.at( i );
437 normal = normal.normalized();
439 *normPtr++ = normal.x();
440 *normPtr++ = normal.y();
441 *normPtr++ = normal.z();
447 outNormal.triangles.resize( triangleIndexes.size() *
sizeof( quint32 ) );
448 quint32 *indexPtr =
reinterpret_cast<quint32 *
>( outNormal.triangles.data() );
449 size_t effective = 0;
456 QgsBox3D boxRelativeToChunkOrigin = box3D - outNormal.positionsOrigin;
458 for (
size_t i = 0; i < triangleIndexes.size(); i += 3 )
460 bool atLeastOneInBox =
false;
461 bool horizontalSkip =
false;
462 bool verticalSkip =
false;
463 for (
size_t j = 0; j < 3; j++ )
465 QVector3D pos = outNormal.positions.at( triangleIndexes.at( i + j ) );
466 atLeastOneInBox |= boxRelativeToChunkOrigin.
contains( pos.x(), pos.y(), pos.z() );
468 if ( verticalFilter || horizontalFilter )
470 const QVector3D pos2 = outNormal.positions.at( triangleIndexes.at( i + ( j + 1 ) % 3 ) );
472 if ( verticalFilter )
473 verticalSkip |= std::fabs( pos.z() - pos2.z() ) > verticalThreshold;
475 if ( horizontalFilter && !verticalSkip )
478 horizontalSkip |= sqrt( std::pow( pos.x() - pos2.x(), 2 ) + std::pow( pos.y() - pos2.y(), 2 ) ) > horizontalThreshold;
481 if ( horizontalSkip || verticalSkip )
485 if ( atLeastOneInBox && !horizontalSkip && !verticalSkip )
487 for (
size_t j = 0; j < 3; j++ )
489 size_t vertIndex = triangleIndexes.at( i + j );
490 *indexPtr++ = quint32( vertIndex );
496 if ( effective != 0 )
498 outNormal.triangles.resize( effective * 3 *
sizeof( quint32 ) );
502 outNormal.triangles.clear();
503 outNormal.normals.clear();
509 if ( outNormal.positions.isEmpty() )
513 std::unique_ptr<delaunator::Delaunator> triangulation;
516 std::vector<double> vertices = getVertices( pc, n, context, box3D );
517 triangulation = std::make_unique<delaunator::Delaunator>( vertices );
519 catch ( std::exception &e )
523 outNormal = PointData();
524 processNode( pc, n, context );
528 const std::vector<size_t> &triangleIndexes = triangulation->triangles;
530 calculateNormals( triangleIndexes );
531 filterTriangles( triangleIndexes, context, box3D );
534std::unique_ptr<QgsPointCloudBlock> QgsPointCloud3DSymbolHandler::pointCloudBlock(
538 std::unique_ptr<QgsPointCloudBlock> block;
549 bool loopAborted =
false;
567QgsSingleColorPointCloud3DSymbolHandler::QgsSingleColorPointCloud3DSymbolHandler()
568 : QgsPointCloud3DSymbolHandler()
587 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
591 const char *ptr = block->data();
592 const int count = block->pointCount();
593 const std::size_t recordSize = block->attributes().pointRecordSize();
599 bool alreadyPrintedDebug =
false;
604 output->positionsOrigin = originFromNodeBounds( pc, n, context );
606 for (
int i = 0; i < count; ++i )
611 const qint32 ix = *( qint32 * ) ( ptr + i * recordSize + 0 );
612 const qint32 iy = *( qint32 * ) ( ptr + i * recordSize + 4 );
613 const qint32 iz = *( qint32 * ) ( ptr + i * recordSize + 8 );
615 double x = blockOffset.
x() + blockScale.
x() * ix;
616 double y = blockOffset.
y() + blockScale.
y() * iy;
617 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
624 if ( !alreadyPrintedDebug )
627 alreadyPrintedDebug =
true;
631 output->positions.push_back( point.
toVector3D() );
637 makeEntity( parent, context, outNormal,
false );
640Qt3DCore::QGeometry *QgsSingleColorPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
642 return new QgsSingleColorPointCloud3DGeometry( parent, data, byteStride );
645QgsColorRampPointCloud3DSymbolHandler::QgsColorRampPointCloud3DSymbolHandler()
646 : QgsPointCloud3DSymbolHandler()
658 const int xOffset = 0;
665 QString attributeName;
666 bool attrIsX =
false;
667 bool attrIsY =
false;
668 bool attrIsZ =
false;
670 int attributeOffset = 0;
674 bool alreadyPrintedDebug =
false;
686 else if ( symbol->
attribute() ==
"Y"_L1 )
690 else if ( symbol->
attribute() ==
"Z"_L1 )
699 attributeType = attr->
type();
700 attributeName = attr->
name();
707 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
713 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
717 const char *ptr = block->data();
718 const int count = block->pointCount();
719 const std::size_t recordSize = block->attributes().pointRecordSize();
727 output->positionsOrigin = originFromNodeBounds( pc, n, context );
729 for (
int i = 0; i < count; ++i )
734 const qint32 ix = *( qint32 * ) ( ptr + i * recordSize + xOffset );
735 const qint32 iy = *( qint32 * ) ( ptr + i * recordSize + yOffset );
736 const qint32 iz = *( qint32 * ) ( ptr + i * recordSize + zOffset );
738 double x = blockOffset.
x() + blockScale.
x() * ix;
739 double y = blockOffset.
y() + blockScale.
y() * iy;
740 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
747 if ( !alreadyPrintedDebug )
750 alreadyPrintedDebug =
true;
754 output->positions.push_back( point.
toVector3D() );
757 output->parameter.push_back( x );
759 output->parameter.push_back( y );
761 output->parameter.push_back( z );
765 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
766 output->parameter.push_back( iParam );
773 makeEntity( parent, context, outNormal,
false );
776Qt3DCore::QGeometry *QgsColorRampPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
778 return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );
781QgsRGBPointCloud3DSymbolHandler::QgsRGBPointCloud3DSymbolHandler()
782 : QgsPointCloud3DSymbolHandler()
821 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
825 const char *ptr = block->data();
826 const int count = block->pointCount();
827 const std::size_t recordSize = block->attributes().pointRecordSize();
834 bool alreadyPrintedDebug =
false;
847 output->positionsOrigin = originFromNodeBounds( pc, n, context );
852 for (
int i = 0; i < count; ++i )
857 const qint32 ix = *( qint32 * ) ( ptr + i * recordSize + 0 );
858 const qint32 iy = *( qint32 * ) ( ptr + i * recordSize + 4 );
859 const qint32 iz = *( qint32 * ) ( ptr + i * recordSize + 8 );
860 double x = blockOffset.
x() + blockScale.
x() * ix;
861 double y = blockOffset.
y() + blockScale.
y() * iy;
862 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
869 if ( !alreadyPrintedDebug )
872 alreadyPrintedDebug =
true;
877 QVector3D color( 0.0f, 0.0f, 0.0f );
879 context.
getAttribute( ptr, i * recordSize + redOffset, redType, ir );
880 context.
getAttribute( ptr, i * recordSize + greenOffset, greenType, ig );
881 context.
getAttribute( ptr, i * recordSize + blueOffset, blueType, ib );
892 if ( useRedContrastEnhancement )
896 if ( useGreenContrastEnhancement )
900 if ( useBlueContrastEnhancement )
905 color.setX( ir / 255.0f );
906 color.setY( ig / 255.0f );
907 color.setZ( ib / 255.0f );
909 output->positions.push_back( point.
toVector3D() );
910 output->colors.push_back( color );
916 makeEntity( parent, context, outNormal,
false );
919Qt3DCore::QGeometry *QgsRGBPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
921 return new QgsRGBPointCloud3DGeometry( parent, data, byteStride );
924QgsClassificationPointCloud3DSymbolHandler::QgsClassificationPointCloud3DSymbolHandler()
925 : QgsPointCloud3DSymbolHandler()
937 const int xOffset = 0;
944 QString attributeName;
945 bool attrIsX =
false;
946 bool attrIsY =
false;
947 bool attrIsZ =
false;
949 int attributeOffset = 0;
961 else if ( symbol->
attribute() ==
"Y"_L1 )
965 else if ( symbol->
attribute() ==
"Z"_L1 )
974 attributeType = attr->
type();
975 attributeName = attr->
name();
981 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
987 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
991 const char *ptr = block->data();
992 const int count = block->pointCount();
993 const std::size_t recordSize = block->attributes().pointRecordSize();
1000 bool alreadyPrintedDebug =
false;
1002 QList<QgsPointCloudCategory> categoriesList = symbol->
categoriesList();
1003 QVector<int> categoriesValues;
1004 QHash<int, double> categoriesPointSizes;
1007 categoriesValues.push_back(
c.value() );
1008 categoriesPointSizes.insert(
c.value(),
c.pointSize() > 0 ?
c.pointSize() : context.
symbol() ? context.
symbol()->
pointSize() : 1.0 );
1012 output = &outNormal;
1014 output->positionsOrigin = originFromNodeBounds( pc, n, context );
1017 for (
int i = 0; i < count; ++i )
1022 const qint32 ix = *( qint32 * ) ( ptr + i * recordSize + xOffset );
1023 const qint32 iy = *( qint32 * ) ( ptr + i * recordSize + yOffset );
1024 const qint32 iz = *( qint32 * ) ( ptr + i * recordSize + zOffset );
1026 double x = blockOffset.
x() + blockScale.
x() * ix;
1027 double y = blockOffset.
y() + blockScale.
y() * iy;
1028 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
1035 if ( !alreadyPrintedDebug )
1038 alreadyPrintedDebug =
true;
1042 float iParam = 0.0f;
1050 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
1052 if ( filteredOutValues.contains( (
int ) iParam ) || !categoriesValues.contains( (
int ) iParam ) )
1054 output->positions.push_back( point.
toVector3D() );
1057 float iParam2 = categoriesValues.indexOf( (
int ) iParam ) + 1;
1058 output->parameter.push_back( iParam2 );
1059 output->pointSizes.push_back( categoriesPointSizes.value( (
int ) iParam ) );
1065 makeEntity( parent, context, outNormal,
false );
1068Qt3DCore::QGeometry *QgsClassificationPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
1070 return new QgsClassificationPointCloud3DGeometry( parent, data, byteStride );
@ Local
Local means the source is a local file on the machine.
@ Remote
Remote means it's loaded through a protocol like HTTP.
A 3-dimensional box composed of x, y, z coordinates.
double xMinimum() const
Returns the minimum x value.
bool contains(const QgsBox3D &other) const
Returns true when box contains other box.
double width() const
Returns the width of the box.
double zMinimum() const
Returns the minimum z value.
double yMinimum() const
Returns the minimum y value.
double height() const
Returns the height of the box.
3D symbol that draws point cloud geometries as 3D objects using classification of the dataset.
QgsPointCloudCategoryList categoriesList() const
Returns the list of categories of the classification.
QString attribute() const
Returns the attribute used to select the color of the point cloud.
3D symbol that draws point cloud geometries as 3D objects using color ramp shader.
QString attribute() const
Returns the attribute used to select the color of the point cloud.
Handles contrast enhancement and clipping.
@ NoEnhancement
Default color scaling algorithm, no scaling is applied.
bool isValueInDisplayableRange(double value)
Returns true if a pixel value is in displayable range, false if pixel is outside of range (i....
int enhanceContrast(double value)
Applies the contrast enhancement to a value.
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
Custom exception class for Coordinate Reference System related exceptions.
void canceled()
Internal routines can connect to this signal if they use event loop.
Base class for all materials used within QGIS 3D views.
Encapsulates the render context for a 3D point cloud rendering operation.
void getAttribute(const char *data, std::size_t offset, QgsPointCloudAttribute::DataType type, T &value) const
Retrieves the attribute value from data at the specified offset, where type indicates the original da...
QSet< int > getFilteredOutValues() const
Returns a set containing the filtered out values.
QgsPointCloud3DSymbol * symbol() const
Returns the symbol used for rendering the point cloud.
double zValueScale() const
Returns any constant scaling factor which must be applied to z values taken from the point cloud inde...
QgsFeedback * feedback() const
Returns the feedback object used to cancel rendering and check if rendering was canceled.
QgsPointCloudAttributeCollection attributes() const
Returns the attributes associated with the rendered block.
bool isCanceled() const
Returns true if the rendering is canceled.
QgsCoordinateTransform coordinateTransform() const
Returns the coordinate transform used to transform points from layer CRS to the map CRS.
QgsRectangle layerExtent() const
Returns the 3D scene's extent in layer crs.
double zValueFixedOffset() const
Returns any constant offset which must be applied to z values taken from the point cloud index.
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.
QgsPointCloudBlockRequest * asyncNodeData(const QgsPointCloudNodeId &n, const QgsPointCloudRequest &request)
Returns a handle responsible for loading a node data block.
std::unique_ptr< QgsPointCloudBlock > nodeData(const QgsPointCloudNodeId &n, const QgsPointCloudRequest &request)
Returns node data block.
QgsPointCloudNode getNode(const QgsPointCloudNodeId &id) const
Returns object for a given node.
Qgis::PointCloudAccessType accessType() const
Returns the access type of the data If the access type is Remote, data will be fetched from an HTTP s...
Represents an indexed point cloud node's position in octree.
QgsPointCloudNodeId parentNode() const
Returns the parent of the node.
Keeps metadata for an indexed point cloud node.
qint64 pointCount() const
Returns number of points contained in node data.
QgsBox3D bounds() const
Returns node's bounding cube in CRS coords.
Point cloud data request.
void setFilterRect(QgsRectangle extent)
Sets the rectangle from which points will be taken, in point cloud's crs.
void setAttributes(const QgsPointCloudAttributeCollection &attributes)
Set attributes filter in the request.
A rectangle specified with double values.
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
void grow(double delta)
Grows the rectangle in place by the specified amount.
3D symbol that draws point cloud geometries as 3D objects using RGB colors in the dataset.
QString blueAttribute() const
Returns the attribute to use for the blue channel.
QString greenAttribute() const
Returns the attribute to use for the green channel.
QgsContrastEnhancement * blueContrastEnhancement()
Returns the contrast enhancement to use for the blue channel.
QString redAttribute() const
Returns the attribute to use for the red channel.
QgsContrastEnhancement * greenContrastEnhancement()
Returns the contrast enhancement to use for the green channel.
QgsContrastEnhancement * redContrastEnhancement()
Returns the contrast enhancement to use for the red channel.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
double y() const
Returns Y coordinate.
double z() const
Returns Z coordinate.
QVector3D toVector3D() const
Converts the current object to QVector3D.
double x() const
Returns X coordinate.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)