20#include "delaunator.hpp"
33#include <Qt3DCore/QAttribute>
34#include <Qt3DCore/QBuffer>
35#include <Qt3DCore/QEntity>
36#include <Qt3DCore/QGeometry>
37#include <Qt3DRender/QEffect>
38#include <Qt3DRender/QGeometryRenderer>
39#include <Qt3DRender/QGraphicsApiFilter>
40#include <Qt3DRender/QParameter>
41#include <Qt3DRender/QShaderProgram>
42#include <Qt3DRender/QTechnique>
44#include "moc_qgspointcloud3dsymbol_p.cpp"
46using namespace Qt::StringLiterals;
54 double nodeOriginX = bounds.
xMinimum();
55 double nodeOriginY = bounds.
yMinimum();
65 return QgsVector3D( nodeOriginX, nodeOriginY, nodeOriginZ );
69QgsPointCloud3DGeometry::QgsPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
71 , mPositionAttribute( new
Qt3DCore::QAttribute( this ) )
72 , mParameterAttribute( new
Qt3DCore::QAttribute( this ) )
73 , mPointSizeAttribute( new
Qt3DCore::QAttribute( this ) )
74 , mColorAttribute( new
Qt3DCore::QAttribute( this ) )
75 , mTriangleIndexAttribute( new
Qt3DCore::QAttribute( this ) )
76 , mNormalsAttribute( new
Qt3DCore::QAttribute( this ) )
77 , mVertexBuffer( new
Qt3DCore::QBuffer( this ) )
78 , mByteStride( byteStride )
80 if ( !data.triangles.isEmpty() )
82 mTriangleBuffer = new Qt3DCore::QBuffer( this );
83 mTriangleIndexAttribute->setAttributeType( Qt3DCore::QAttribute::IndexAttribute );
84 mTriangleIndexAttribute->setBuffer( mTriangleBuffer );
85 mTriangleIndexAttribute->setVertexBaseType( Qt3DCore::QAttribute::UnsignedInt );
86 mTriangleBuffer->setData( data.triangles );
87 mTriangleIndexAttribute->setCount( data.triangles.size() / sizeof( quint32 ) );
88 addAttribute( mTriangleIndexAttribute );
91 if ( !data.normals.isEmpty() )
93 mNormalsBuffer = new Qt3DCore::QBuffer( this );
94 mNormalsAttribute->setName( Qt3DCore::QAttribute::defaultNormalAttributeName() );
95 mNormalsAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
96 mNormalsAttribute->setVertexSize( 3 );
97 mNormalsAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
98 mNormalsAttribute->setBuffer( mNormalsBuffer );
99 mNormalsBuffer->setData( data.normals );
100 mNormalsAttribute->setCount( data.normals.size() / ( 3 * sizeof( float ) ) );
101 addAttribute( mNormalsAttribute );
105QgsSingleColorPointCloud3DGeometry::QgsSingleColorPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
106 : QgsPointCloud3DGeometry( parent, data, byteStride )
108 mPositionAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
109 mPositionAttribute->setBuffer( mVertexBuffer );
110 mPositionAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
111 mPositionAttribute->setVertexSize( 3 );
112 mPositionAttribute->setName( Qt3DCore::QAttribute::defaultPositionAttributeName() );
113 mPositionAttribute->setByteOffset( 0 );
114 mPositionAttribute->setByteStride( mByteStride );
115 addAttribute( mPositionAttribute );
116 makeVertexBuffer( data );
119void QgsSingleColorPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
121 QByteArray vertexBufferData;
122 vertexBufferData.resize( data.positions.size() * mByteStride );
123 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
125 for (
int i = 0; i < data.positions.size(); ++i )
127 rawVertexArray[idx++] = data.positions.at( i ).x();
128 rawVertexArray[idx++] = data.positions.at( i ).y();
129 rawVertexArray[idx++] = data.positions.at( i ).z();
132 mVertexCount = data.positions.size();
133 mVertexBuffer->setData( vertexBufferData );
136QgsColorRampPointCloud3DGeometry::QgsColorRampPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
137 : QgsPointCloud3DGeometry( parent, data, byteStride )
139 mPositionAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
140 mPositionAttribute->setBuffer( mVertexBuffer );
141 mPositionAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
142 mPositionAttribute->setVertexSize( 3 );
143 mPositionAttribute->setName( Qt3DCore::QAttribute::defaultPositionAttributeName() );
144 mPositionAttribute->setByteOffset( 0 );
145 mPositionAttribute->setByteStride( mByteStride );
146 addAttribute( mPositionAttribute );
147 mParameterAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
148 mParameterAttribute->setBuffer( mVertexBuffer );
149 mParameterAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
150 mParameterAttribute->setVertexSize( 1 );
151 mParameterAttribute->setName(
"vertexParameter" );
152 mParameterAttribute->setByteOffset( 12 );
153 mParameterAttribute->setByteStride( mByteStride );
154 addAttribute( mParameterAttribute );
155 makeVertexBuffer( data );
158void QgsColorRampPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
160 QByteArray vertexBufferData;
161 vertexBufferData.resize( data.positions.size() * mByteStride );
162 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
164 Q_ASSERT( data.positions.size() == data.parameter.size() );
165 for (
int i = 0; i < data.positions.size(); ++i )
167 rawVertexArray[idx++] = data.positions.at( i ).x();
168 rawVertexArray[idx++] = data.positions.at( i ).y();
169 rawVertexArray[idx++] = data.positions.at( i ).z();
170 rawVertexArray[idx++] = data.parameter.at( i );
173 mVertexCount = data.positions.size();
174 mVertexBuffer->setData( vertexBufferData );
177QgsRGBPointCloud3DGeometry::QgsRGBPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
178 : QgsPointCloud3DGeometry( parent, data, byteStride )
180 mPositionAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
181 mPositionAttribute->setBuffer( mVertexBuffer );
182 mPositionAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
183 mPositionAttribute->setVertexSize( 3 );
184 mPositionAttribute->setName( Qt3DCore::QAttribute::defaultPositionAttributeName() );
185 mPositionAttribute->setByteOffset( 0 );
186 mPositionAttribute->setByteStride( mByteStride );
187 addAttribute( mPositionAttribute );
188 mColorAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
189 mColorAttribute->setBuffer( mVertexBuffer );
190 mColorAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
191 mColorAttribute->setVertexSize( 3 );
192 mColorAttribute->setName( u
"vertexColor"_s );
193 mColorAttribute->setByteOffset( 12 );
194 mColorAttribute->setByteStride( mByteStride );
195 addAttribute( mColorAttribute );
196 makeVertexBuffer( data );
199void QgsRGBPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
201 QByteArray vertexBufferData;
202 vertexBufferData.resize( data.positions.size() * mByteStride );
203 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
205 Q_ASSERT( data.positions.size() == data.colors.size() );
206 for (
int i = 0; i < data.positions.size(); ++i )
208 rawVertexArray[idx++] = data.positions.at( i ).x();
209 rawVertexArray[idx++] = data.positions.at( i ).y();
210 rawVertexArray[idx++] = data.positions.at( i ).z();
211 rawVertexArray[idx++] = data.colors.at( i ).x();
212 rawVertexArray[idx++] = data.colors.at( i ).y();
213 rawVertexArray[idx++] = data.colors.at( i ).z();
215 mVertexCount = data.positions.size();
216 mVertexBuffer->setData( vertexBufferData );
219QgsClassificationPointCloud3DGeometry::QgsClassificationPointCloud3DGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
220 : QgsPointCloud3DGeometry( parent, data, byteStride )
222 mPositionAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
223 mPositionAttribute->setBuffer( mVertexBuffer );
224 mPositionAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
225 mPositionAttribute->setVertexSize( 3 );
226 mPositionAttribute->setName( Qt3DCore::QAttribute::defaultPositionAttributeName() );
227 mPositionAttribute->setByteOffset( 0 );
228 mPositionAttribute->setByteStride( mByteStride );
229 addAttribute( mPositionAttribute );
230 mParameterAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
231 mParameterAttribute->setBuffer( mVertexBuffer );
232 mParameterAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
233 mParameterAttribute->setVertexSize( 1 );
234 mParameterAttribute->setName(
"vertexParameter" );
235 mParameterAttribute->setByteOffset( 12 );
236 mParameterAttribute->setByteStride( mByteStride );
237 addAttribute( mParameterAttribute );
238 mPointSizeAttribute->setAttributeType( Qt3DCore::QAttribute::VertexAttribute );
239 mPointSizeAttribute->setBuffer( mVertexBuffer );
240 mPointSizeAttribute->setVertexBaseType( Qt3DCore::QAttribute::Float );
241 mPointSizeAttribute->setVertexSize( 1 );
242 mPointSizeAttribute->setName(
"vertexSize" );
243 mPointSizeAttribute->setByteOffset( 16 );
244 mPointSizeAttribute->setByteStride( mByteStride );
245 addAttribute( mPointSizeAttribute );
246 makeVertexBuffer( data );
249void QgsClassificationPointCloud3DGeometry::makeVertexBuffer(
const QgsPointCloud3DSymbolHandler::PointData &data )
251 QByteArray vertexBufferData;
252 vertexBufferData.resize( data.positions.size() * mByteStride );
253 float *rawVertexArray =
reinterpret_cast<float *
>( vertexBufferData.data() );
255 Q_ASSERT( data.positions.size() == data.parameter.size() );
256 Q_ASSERT( data.positions.size() == data.pointSizes.size() );
257 for (
int i = 0; i < data.positions.size(); ++i )
259 rawVertexArray[idx++] = data.positions.at( i ).x();
260 rawVertexArray[idx++] = data.positions.at( i ).y();
261 rawVertexArray[idx++] = data.positions.at( i ).z();
262 rawVertexArray[idx++] = data.parameter.at( i );
263 rawVertexArray[idx++] = data.pointSizes.at( i );
266 mVertexCount = data.positions.size();
267 mVertexBuffer->setData( vertexBufferData );
270QgsPointCloud3DSymbolHandler::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(
429 triangleVertices.at( 1 ) - triangleVertices.at( 0 ),
430 triangleVertices.at( 2 ) - triangleVertices.at( 0 )
435 outNormal.normals.resize( ( outNormal.positions.count() ) *
sizeof(
float ) * 3 );
436 float *normPtr =
reinterpret_cast<float *
>( outNormal.normals.data() );
437 for (
int i = 0; i < normals.size(); ++i )
439 QVector3D normal = normals.at( i );
440 normal = normal.normalized();
442 *normPtr++ = normal.x();
443 *normPtr++ = normal.y();
444 *normPtr++ = normal.z();
450 outNormal.triangles.resize( triangleIndexes.size() *
sizeof( quint32 ) );
451 quint32 *indexPtr =
reinterpret_cast<quint32 *
>( outNormal.triangles.data() );
452 size_t effective = 0;
459 QgsBox3D boxRelativeToChunkOrigin = box3D - outNormal.positionsOrigin;
461 for (
size_t i = 0; i < triangleIndexes.size(); i += 3 )
463 bool atLeastOneInBox =
false;
464 bool horizontalSkip =
false;
465 bool verticalSkip =
false;
466 for (
size_t j = 0; j < 3; j++ )
468 QVector3D pos = outNormal.positions.at( triangleIndexes.at( i + j ) );
469 atLeastOneInBox |= boxRelativeToChunkOrigin.
contains( pos.x(), pos.y(), pos.z() );
471 if ( verticalFilter || horizontalFilter )
473 const QVector3D pos2 = outNormal.positions.at( triangleIndexes.at( i + ( j + 1 ) % 3 ) );
475 if ( verticalFilter )
476 verticalSkip |= std::fabs( pos.z() - pos2.z() ) > verticalThreshold;
478 if ( horizontalFilter && !verticalSkip )
481 horizontalSkip |= sqrt( std::pow( pos.x() - pos2.x(), 2 ) + std::pow( pos.y() - pos2.y(), 2 ) ) > horizontalThreshold;
484 if ( horizontalSkip || verticalSkip )
488 if ( atLeastOneInBox && !horizontalSkip && !verticalSkip )
490 for (
size_t j = 0; j < 3; j++ )
492 size_t vertIndex = triangleIndexes.at( i + j );
493 *indexPtr++ = quint32( vertIndex );
499 if ( effective != 0 )
501 outNormal.triangles.resize( effective * 3 *
sizeof( quint32 ) );
505 outNormal.triangles.clear();
506 outNormal.normals.clear();
512 if ( outNormal.positions.isEmpty() )
516 std::unique_ptr<delaunator::Delaunator> triangulation;
519 std::vector<double> vertices = getVertices( pc, n, context, box3D );
520 triangulation = std::make_unique<delaunator::Delaunator>( vertices );
522 catch ( std::exception &e )
526 outNormal = PointData();
527 processNode( pc, n, context );
531 const std::vector<size_t> &triangleIndexes = triangulation->triangles;
533 calculateNormals( triangleIndexes );
534 filterTriangles( triangleIndexes, context, box3D );
539 std::unique_ptr<QgsPointCloudBlock> block;
550 bool loopAborted =
false;
568QgsSingleColorPointCloud3DSymbolHandler::QgsSingleColorPointCloud3DSymbolHandler()
569 : QgsPointCloud3DSymbolHandler()
589 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
593 const char *ptr = block->data();
594 const int count = block->pointCount();
595 const std::size_t recordSize = block->attributes().pointRecordSize();
601 bool alreadyPrintedDebug =
false;
606 output->positionsOrigin = originFromNodeBounds( pc, n, context );
608 for (
int i = 0; i < count; ++i )
613 const qint32 ix = *( qint32 * ) ( ptr + i * recordSize + 0 );
614 const qint32 iy = *( qint32 * ) ( ptr + i * recordSize + 4 );
615 const qint32 iz = *( qint32 * ) ( ptr + i * recordSize + 8 );
617 double x = blockOffset.
x() + blockScale.
x() * ix;
618 double y = blockOffset.
y() + blockScale.
y() * iy;
619 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
626 if ( !alreadyPrintedDebug )
629 alreadyPrintedDebug =
true;
633 output->positions.push_back( point.
toVector3D() );
639 makeEntity( parent, context, outNormal,
false );
642Qt3DCore::QGeometry *QgsSingleColorPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
644 return new QgsSingleColorPointCloud3DGeometry( parent, data, byteStride );
647QgsColorRampPointCloud3DSymbolHandler::QgsColorRampPointCloud3DSymbolHandler()
648 : QgsPointCloud3DSymbolHandler()
661 const int xOffset = 0;
668 QString attributeName;
669 bool attrIsX =
false;
670 bool attrIsY =
false;
671 bool attrIsZ =
false;
673 int attributeOffset = 0;
677 bool alreadyPrintedDebug =
false;
689 else if ( symbol->
attribute() ==
"Y"_L1 )
693 else if ( symbol->
attribute() ==
"Z"_L1 )
702 attributeType = attr->
type();
703 attributeName = attr->
name();
710 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
716 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
720 const char *ptr = block->data();
721 const int count = block->pointCount();
722 const std::size_t recordSize = block->attributes().pointRecordSize();
730 output->positionsOrigin = originFromNodeBounds( pc, n, context );
732 for (
int i = 0; i < count; ++i )
737 const qint32 ix = *( qint32 * ) ( ptr + i * recordSize + xOffset );
738 const qint32 iy = *( qint32 * ) ( ptr + i * recordSize + yOffset );
739 const qint32 iz = *( qint32 * ) ( ptr + i * recordSize + zOffset );
741 double x = blockOffset.
x() + blockScale.
x() * ix;
742 double y = blockOffset.
y() + blockScale.
y() * iy;
743 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
750 if ( !alreadyPrintedDebug )
753 alreadyPrintedDebug =
true;
757 output->positions.push_back( point.
toVector3D() );
760 output->parameter.push_back( x );
762 output->parameter.push_back( y );
764 output->parameter.push_back( z );
768 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
769 output->parameter.push_back( iParam );
776 makeEntity( parent, context, outNormal,
false );
779Qt3DCore::QGeometry *QgsColorRampPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
781 return new QgsColorRampPointCloud3DGeometry( parent, data, byteStride );
784QgsRGBPointCloud3DSymbolHandler::QgsRGBPointCloud3DSymbolHandler()
785 : QgsPointCloud3DSymbolHandler()
825 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
829 const char *ptr = block->data();
830 const int count = block->pointCount();
831 const std::size_t recordSize = block->attributes().pointRecordSize();
838 bool alreadyPrintedDebug =
false;
851 output->positionsOrigin = originFromNodeBounds( pc, n, context );
856 for (
int i = 0; i < count; ++i )
861 const qint32 ix = *( qint32 * ) ( ptr + i * recordSize + 0 );
862 const qint32 iy = *( qint32 * ) ( ptr + i * recordSize + 4 );
863 const qint32 iz = *( qint32 * ) ( ptr + i * recordSize + 8 );
864 double x = blockOffset.
x() + blockScale.
x() * ix;
865 double y = blockOffset.
y() + blockScale.
y() * iy;
866 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
873 if ( !alreadyPrintedDebug )
876 alreadyPrintedDebug =
true;
881 QVector3D color( 0.0f, 0.0f, 0.0f );
883 context.
getAttribute( ptr, i * recordSize + redOffset, redType, ir );
884 context.
getAttribute( ptr, i * recordSize + greenOffset, greenType, ig );
885 context.
getAttribute( ptr, i * recordSize + blueOffset, blueType, ib );
896 if ( useRedContrastEnhancement )
900 if ( useGreenContrastEnhancement )
904 if ( useBlueContrastEnhancement )
909 color.setX( ir / 255.0f );
910 color.setY( ig / 255.0f );
911 color.setZ( ib / 255.0f );
913 output->positions.push_back( point.
toVector3D() );
914 output->colors.push_back( color );
920 makeEntity( parent, context, outNormal,
false );
923Qt3DCore::QGeometry *QgsRGBPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
925 return new QgsRGBPointCloud3DGeometry( parent, data, byteStride );
928QgsClassificationPointCloud3DSymbolHandler::QgsClassificationPointCloud3DSymbolHandler()
929 : QgsPointCloud3DSymbolHandler()
942 const int xOffset = 0;
949 QString attributeName;
950 bool attrIsX =
false;
951 bool attrIsY =
false;
952 bool attrIsZ =
false;
954 int attributeOffset = 0;
966 else if ( symbol->
attribute() ==
"Y"_L1 )
970 else if ( symbol->
attribute() ==
"Z"_L1 )
979 attributeType = attr->
type();
980 attributeName = attr->
name();
986 if ( attributeName.isEmpty() && !attrIsX && !attrIsY && !attrIsZ )
992 std::unique_ptr<QgsPointCloudBlock> block( pointCloudBlock( pc, n, request, context ) );
996 const char *ptr = block->data();
997 const int count = block->pointCount();
998 const std::size_t recordSize = block->attributes().pointRecordSize();
1005 bool alreadyPrintedDebug =
false;
1007 QList<QgsPointCloudCategory> categoriesList = symbol->
categoriesList();
1008 QVector<int> categoriesValues;
1009 QHash<int, double> categoriesPointSizes;
1012 categoriesValues.push_back(
c.value() );
1013 categoriesPointSizes.insert(
c.value(),
c.pointSize() > 0 ?
c.pointSize() : context.
symbol() ? context.
symbol()->
pointSize()
1018 output = &outNormal;
1020 output->positionsOrigin = originFromNodeBounds( pc, n, context );
1023 for (
int i = 0; i < count; ++i )
1028 const qint32 ix = *( qint32 * ) ( ptr + i * recordSize + xOffset );
1029 const qint32 iy = *( qint32 * ) ( ptr + i * recordSize + yOffset );
1030 const qint32 iz = *( qint32 * ) ( ptr + i * recordSize + zOffset );
1032 double x = blockOffset.
x() + blockScale.
x() * ix;
1033 double y = blockOffset.
y() + blockScale.
y() * iy;
1034 double z = ( blockOffset.
z() + blockScale.
z() * iz ) * zValueScale + zValueOffset;
1041 if ( !alreadyPrintedDebug )
1044 alreadyPrintedDebug =
true;
1048 float iParam = 0.0f;
1056 context.
getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam );
1058 if ( filteredOutValues.contains( (
int ) iParam ) || !categoriesValues.contains( (
int ) iParam ) )
1060 output->positions.push_back( point.
toVector3D() );
1063 float iParam2 = categoriesValues.indexOf( (
int ) iParam ) + 1;
1064 output->parameter.push_back( iParam2 );
1065 output->pointSizes.push_back( categoriesPointSizes.value( (
int ) iParam ) );
1071 makeEntity( parent, context, outNormal,
false );
1074Qt3DCore::QGeometry *QgsClassificationPointCloud3DSymbolHandler::makeGeometry( Qt3DCore::QNode *parent,
const QgsPointCloud3DSymbolHandler::PointData &data,
unsigned int byteStride )
1076 return new QgsClassificationPointCloud3DGeometry( parent, data, byteStride );
@ Local
Local means the source is a local file on the machine.
@ Remote
Remote means it's loaded through a protocol like HTTP.
A 3-dimensional box composed of x, y, z coordinates.
double xMinimum() const
Returns the minimum x value.
bool contains(const QgsBox3D &other) const
Returns true when box contains other box.
double width() const
Returns the width of the box.
double zMinimum() const
Returns the minimum z value.
double yMinimum() const
Returns the minimum y value.
double height() const
Returns the height of the box.
3D symbol that draws point cloud geometries as 3D objects using classification of the dataset.
QgsPointCloudCategoryList categoriesList() const
Returns the list of categories of the classification.
QString attribute() const
Returns the attribute used to select the color of the point cloud.
3D symbol that draws point cloud geometries as 3D objects using color ramp shader.
QString attribute() const
Returns the attribute used to select the color of the point cloud.
Handles contrast enhancement and clipping.
@ NoEnhancement
Default color scaling algorithm, no scaling is applied.
bool isValueInDisplayableRange(double value)
Returns true if a pixel value is in displayable range, false if pixel is outside of range (i....
int enhanceContrast(double value)
Applies the contrast enhancement to a value.
ContrastEnhancementAlgorithm contrastEnhancementAlgorithm() const
Custom exception class for Coordinate Reference System related exceptions.
void canceled()
Internal routines can connect to this signal if they use event loop.
Base class for all materials used within QGIS 3D views.
Encapsulates the render context for a 3D point cloud rendering operation.
void getAttribute(const char *data, std::size_t offset, QgsPointCloudAttribute::DataType type, T &value) const
Retrieves the attribute value from data at the specified offset, where type indicates the original da...
QSet< int > getFilteredOutValues() const
Returns a set containing the filtered out values.
QgsPointCloud3DSymbol * symbol() const
Returns the symbol used for rendering the point cloud.
double zValueScale() const
Returns any constant scaling factor which must be applied to z values taken from the point cloud inde...
QgsFeedback * feedback() const
Returns the feedback object used to cancel rendering and check if rendering was canceled.
QgsPointCloudAttributeCollection attributes() const
Returns the attributes associated with the rendered block.
bool isCanceled() const
Returns true if the rendering is canceled.
QgsCoordinateTransform coordinateTransform() const
Returns the coordinate transform used to transform points from layer CRS to the map CRS.
QgsRectangle layerExtent() const
Returns the 3D scene's extent in layer crs.
double zValueFixedOffset() const
Returns any constant offset which must be applied to z values taken from the point cloud index.
bool verticalTriangleFilter() const
Returns whether triangles are filtered by vertical height for rendering.
float verticalFilterThreshold() const
Returns the threshold vertical height value for filtering triangles.
virtual void fillMaterial(QgsMaterial *material)=0SIP_SKIP
Used to fill material object with necessary QParameters (and consequently opengl uniforms).
virtual unsigned int byteStride()=0
Returns the byte stride for the geometries used to for the vertex buffer.
float horizontalFilterThreshold() const
Returns the threshold horizontal size value for filtering triangles.
bool renderAsTriangles() const
Returns whether points are triangulated to render solid surface.
float pointSize() const
Returns the point size of the point cloud.
bool horizontalTriangleFilter() const
Returns whether triangles are filtered by horizontal size for rendering.
A collection of point cloud attributes.
void push_back(const QgsPointCloudAttribute &attribute)
Adds extra attribute.
int pointRecordSize() const
Returns total size of record.
const QgsPointCloudAttribute * find(const QString &attributeName, int &offset) const
Finds the attribute with the name.
Attribute for point cloud data pair of name and size in bytes.
DataType
Systems of unit measurement.
QString name() const
Returns name of the attribute.
DataType type() const
Returns the data type.
Base class for handling loading QgsPointCloudBlock asynchronously.
void finished()
Emitted when the request processing has finished.
std::unique_ptr< QgsPointCloudBlock > takeBlock()
Returns the requested block.
Represents an individual category (class) from a QgsPointCloudClassifiedRenderer.
Smart pointer for QgsAbstractPointCloudIndex.
int span() const
Returns the number of points in one direction in a single node.
QgsPointCloudBlockRequest * asyncNodeData(const QgsPointCloudNodeId &n, const QgsPointCloudRequest &request)
Returns a handle responsible for loading a node data block.
std::unique_ptr< QgsPointCloudBlock > nodeData(const QgsPointCloudNodeId &n, const QgsPointCloudRequest &request)
Returns node data block.
QgsPointCloudNode getNode(const QgsPointCloudNodeId &id) const
Returns object for a given node.
Qgis::PointCloudAccessType accessType() const
Returns the access type of the data If the access type is Remote, data will be fetched from an HTTP s...
Represents an indexed point cloud node's position in octree.
QgsPointCloudNodeId parentNode() const
Returns the parent of the node.
Keeps metadata for an indexed point cloud node.
qint64 pointCount() const
Returns number of points contained in node data.
QgsBox3D bounds() const
Returns node's bounding cube in CRS coords.
Point cloud data request.
void setFilterRect(QgsRectangle extent)
Sets the rectangle from which points will be taken, in point cloud's crs.
void setAttributes(const QgsPointCloudAttributeCollection &attributes)
Set attributes filter in the request.
A rectangle specified with double values.
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
void grow(double delta)
Grows the rectangle in place by the specified amount.
3D symbol that draws point cloud geometries as 3D objects using RGB colors in the dataset.
QString blueAttribute() const
Returns the attribute to use for the blue channel.
QString greenAttribute() const
Returns the attribute to use for the green channel.
QgsContrastEnhancement * blueContrastEnhancement()
Returns the contrast enhancement to use for the blue channel.
QString redAttribute() const
Returns the attribute to use for the red channel.
QgsContrastEnhancement * greenContrastEnhancement()
Returns the contrast enhancement to use for the green channel.
QgsContrastEnhancement * redContrastEnhancement()
Returns the contrast enhancement to use for the red channel.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
double y() const
Returns Y coordinate.
double z() const
Returns Z coordinate.
QVector3D toVector3D() const
Converts the current object to QVector3D.
double x() const
Returns X coordinate.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)