diff --git a/src/3d/qgspointcloudlayerchunkloader_p.cpp b/src/3d/qgspointcloudlayerchunkloader_p.cpp index 10de64dd3bdb..994738cae70a 100644 --- a/src/3d/qgspointcloudlayerchunkloader_p.cpp +++ b/src/3d/qgspointcloudlayerchunkloader_p.cpp @@ -93,6 +93,13 @@ QgsPointCloudLayerChunkLoader::QgsPointCloudLayerChunkLoader( const QgsPointClou } mHandler->processNode( pc, pcNode, mContext ); + + if ( mContext.isCanceled() ) + { + QgsDebugMsgLevel( QStringLiteral( "canceled" ), 2 ); + return; + } + if ( mContext.symbol()->renderAsTriangles() ) mHandler->triangulate( pc, pcNode, mContext, bbox ); } ); diff --git a/src/3d/symbols/qgspointcloud3dsymbol_p.cpp b/src/3d/symbols/qgspointcloud3dsymbol_p.cpp index f4cbac3c5c06..35a87b7c03bb 100644 --- a/src/3d/symbols/qgspointcloud3dsymbol_p.cpp +++ b/src/3d/symbols/qgspointcloud3dsymbol_p.cpp @@ -54,6 +54,28 @@ typedef Qt3DCore::QGeometry Qt3DQGeometry; #include +// pick a point that we'll use as origin for coordinates for this node's points +static QgsVector3D originFromNodeBounds( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, const QgsPointCloudBlock *block ) +{ + const QgsVector3D blockScale = block->scale(); + const QgsVector3D blockOffset = block->offset(); + + QgsPointCloudDataBounds bounds = pc->nodeBounds( n ); + double nodeOriginX = bounds.xMin() * blockScale.x() + blockOffset.x(); + double nodeOriginY = bounds.yMin() * blockScale.y() + blockOffset.y(); + double nodeOriginZ = ( bounds.zMin() * blockScale.z() + blockOffset.z() ) * context.zValueScale() + context.zValueFixedOffset(); + try + { + context.coordinateTransform().transformInPlace( nodeOriginX, nodeOriginY, nodeOriginZ ); + } + catch ( QgsCsException & ) + { + QgsDebugError( QStringLiteral( "Error transforming node origin point" ) ); + } + return QgsVector3D( nodeOriginX, nodeOriginY, nodeOriginZ ); +} + + QgsPointCloud3DGeometry::QgsPointCloud3DGeometry( Qt3DCore::QNode *parent, const QgsPointCloud3DSymbolHandler::PointData &data, unsigned int byteStride ) : Qt3DQGeometry( parent ) , mPositionAttribute( new Qt3DQAttribute( this ) ) @@ -241,6 +263,7 @@ void QgsClassificationPointCloud3DGeometry::makeVertexBuffer( const QgsPointClou float *rawVertexArray = reinterpret_cast( vertexBufferData.data() ); int idx = 0; Q_ASSERT( data.positions.size() == data.parameter.size() ); + Q_ASSERT( data.positions.size() == data.pointSizes.size() ); for ( int i = 0; i < data.positions.size(); ++i ) { rawVertexArray[idx++] = data.positions.at( i ).x(); @@ -281,8 +304,12 @@ void QgsPointCloud3DSymbolHandler::makeEntity( Qt3DCore::QEntity *parent, const } gr->setGeometry( geom ); - // Transform + // Transform: chunks are using coordinates relative to chunk origin, with X,Y,Z axes being the same + // as map coordinates, so we need to rotate and translate entities to get them into world coordinates Qt3DCore::QTransform *tr = new Qt3DCore::QTransform; + QVector3D nodeTranslation = ( out.positionsOrigin - context.origin() ).toVector3D(); + tr->setRotation( QQuaternion::fromAxisAndAngle( QVector3D( 1, 0, 0 ), -90 ) ); // flip map (x,y,z) to world (x,z,-y) + tr->setTranslation( QVector3D( nodeTranslation.x(), nodeTranslation.z(), -nodeTranslation.y() ) ); // Material Qt3DRender::QMaterial *mat = new Qt3DRender::QMaterial; @@ -337,6 +364,7 @@ std::vector QgsPointCloud3DSymbolHandler::getVertices( QgsPointCloudInde bool hasColorData = !outNormal.colors.empty(); bool hasParameterData = !outNormal.parameter.empty(); + bool hasPointSizeData = !outNormal.pointSizes.empty(); // first, get the points of the concerned node std::vector vertices( outNormal.positions.size() * 2 ); @@ -344,56 +372,56 @@ std::vector QgsPointCloud3DSymbolHandler::getVertices( QgsPointCloudInde for ( int i = 0; i < outNormal.positions.size(); ++i ) { vertices[idx++] = outNormal.positions.at( i ).x(); - vertices[idx++] = outNormal.positions.at( i ).z(); + vertices[idx++] = -outNormal.positions.at( i ).y(); // flipping y to have correctly oriented triangles from delaunator } // next, we also need all points of all parents nodes to make the triangulation (also external points) IndexedPointCloudNode parentNode = n.parentNode(); - int properPointsCount = outNormal.positions.count(); - while ( parentNode.d() >= 0 ) - { - processNode( pc, parentNode, context ); - parentNode = parentNode.parentNode(); - } - - PointData filteredExtraPointData; - double span = pc->span(); //factor to take account of the density of the point to calculate extension of the bounding box // with a usual value span = 128, bounding box is extended by 12.5 % on each side. double extraBoxFactor = 16 / span; double extraX = extraBoxFactor * bbox.xExtent(); - double extraZ = extraBoxFactor * bbox.zExtent(); + double extraY = extraBoxFactor * bbox.yExtent(); // We keep all points in vertical direction to avoid odd triangulation if points are isolated on top - const QgsAABB extendedBBox( bbox.xMin - extraX, -std::numeric_limits::max(), bbox.zMin - extraZ, bbox.xMax + extraX, std::numeric_limits::max(), bbox.zMax + extraZ ); + const QgsAABB extendedBBox( bbox.xMin - extraX, bbox.yMin - extraY, -std::numeric_limits::max(), bbox.xMax + extraX, bbox.yMax + extraY, std::numeric_limits::max() ); - for ( int i = properPointsCount; i < outNormal.positions.count(); ++i ) + PointData filteredExtraPointData; + while ( parentNode.d() >= 0 ) { - const QVector3D pos = outNormal.positions.at( i ); - if ( extendedBBox.intersects( pos.x(), pos.y(), pos.z() ) ) + PointData outputParent; + processNode( pc, parentNode, context, &outputParent ); + + // the "main" chunk and each parent chunks have their origins + QVector3D originDifference = ( outputParent.positionsOrigin - outNormal.positionsOrigin ).toVector3D(); + + for ( int i = 0; i < outputParent.positions.count(); ++i ) { - filteredExtraPointData.positions.append( pos ); - vertices.push_back( pos.x() ); - vertices.push_back( pos.z() ); - - if ( hasColorData ) - filteredExtraPointData.colors.append( outNormal.colors.at( i ) ); - if ( hasParameterData ) - filteredExtraPointData.parameter.append( outNormal.parameter.at( i ) ); + const QVector3D pos = outputParent.positions.at( i ) + originDifference; + if ( extendedBBox.intersects( pos.x(), pos.y(), pos.z() ) ) + { + filteredExtraPointData.positions.append( pos ); + vertices.push_back( pos.x() ); + vertices.push_back( -pos.y() ); // flipping y to have correctly oriented triangles from delaunator + + if ( hasColorData ) + filteredExtraPointData.colors.append( outputParent.colors.at( i ) ); + if ( hasParameterData ) + filteredExtraPointData.parameter.append( outputParent.parameter.at( i ) ); + if ( hasPointSizeData ) + filteredExtraPointData.pointSizes.append( outputParent.pointSizes.at( i ) ); + } } - } - outNormal.positions.resize( properPointsCount ); - if ( hasColorData ) - outNormal.colors.resize( properPointsCount ); - if ( hasParameterData ) - outNormal.parameter.resize( properPointsCount ); + parentNode = parentNode.parentNode(); + } outNormal.positions.append( filteredExtraPointData.positions ); outNormal.colors.append( filteredExtraPointData.colors ); outNormal.parameter.append( filteredExtraPointData.parameter ); + outNormal.pointSizes.append( filteredExtraPointData.pointSizes ); return vertices; } @@ -456,13 +484,13 @@ void QgsPointCloud3DSymbolHandler::filterTriangles( const std::vector &t const QVector3D pos2 = outNormal.positions.at( triangleIndexes.at( i + ( j + 1 ) % 3 ) ); if ( verticalFilter ) - verticalSkip |= std::fabs( pos.y() - pos2.y() ) > verticalThreshold; + verticalSkip |= std::fabs( pos.z() - pos2.z() ) > verticalThreshold; if ( horizontalFilter && ! verticalSkip ) { // filter only in the horizontal plan, it is a 2.5D triangulation. horizontalSkip |= sqrt( std::pow( pos.x() - pos2.x(), 2 ) + - std::pow( pos.z() - pos2.z(), 2 ) ) > horizontalThreshold; + std::pow( pos.y() - pos2.y(), 2 ) ) > horizontalThreshold; } if ( horizontalSkip || verticalSkip ) @@ -496,11 +524,25 @@ void QgsPointCloud3DSymbolHandler::triangulate( QgsPointCloudIndex *pc, const In if ( outNormal.positions.isEmpty() ) return; + // The bbox we get is in world coordinates, we need to transform it to map coordinates + // (flip axes and add scene origin vector), but relative to the chunk's origin (subtract it) + // because that's the coordinate system used within the chunk + QgsBox3D boxRelativeToChunkOrigin( + bbox.xMin + context.origin().x() - outNormal.positionsOrigin.x(), + -bbox.zMax + context.origin().y() - outNormal.positionsOrigin.y(), + bbox.yMin + context.origin().z() - outNormal.positionsOrigin.z(), + bbox.xMax + context.origin().x() - outNormal.positionsOrigin.x(), + -bbox.zMin + context.origin().y() - outNormal.positionsOrigin.y(), + bbox.yMax + context.origin().z() - outNormal.positionsOrigin.z() ); + QgsAABB aabbRelativeToChunkOrigin( + boxRelativeToChunkOrigin.xMinimum(), boxRelativeToChunkOrigin.yMinimum(), boxRelativeToChunkOrigin.zMinimum(), + boxRelativeToChunkOrigin.xMaximum(), boxRelativeToChunkOrigin.yMaximum(), boxRelativeToChunkOrigin.zMaximum() ); + // Triangulation happens here std::unique_ptr triangulation; try { - std::vector vertices = getVertices( pc, n, context, bbox ); + std::vector vertices = getVertices( pc, n, context, aabbRelativeToChunkOrigin ); triangulation.reset( new delaunator::Delaunator( vertices ) ); } catch ( std::exception &e ) @@ -515,7 +557,7 @@ void QgsPointCloud3DSymbolHandler::triangulate( QgsPointCloudIndex *pc, const In const std::vector &triangleIndexes = triangulation->triangles; calculateNormals( triangleIndexes ); - filterTriangles( triangleIndexes, context, bbox ); + filterTriangles( triangleIndexes, context, aabbRelativeToChunkOrigin ); } std::unique_ptr QgsPointCloud3DSymbolHandler::pointCloudBlock( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloudRequest &request, const QgsPointCloud3DRenderContext &context ) @@ -561,7 +603,7 @@ bool QgsSingleColorPointCloud3DSymbolHandler::prepare( const QgsPointCloud3DRend return true; } -void QgsSingleColorPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context ) +void QgsSingleColorPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, PointData *output ) { QgsPointCloudAttributeCollection attributes; attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "X" ), QgsPointCloudAttribute::Int32 ) ); @@ -585,6 +627,11 @@ void QgsSingleColorPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *p const QgsCoordinateTransform coordinateTransform = context.coordinateTransform(); bool alreadyPrintedDebug = false; + if ( !output ) + output = &outNormal; + + output->positionsOrigin = originFromNodeBounds( pc, n, context, block.get() ); + for ( int i = 0; i < count; ++i ) { if ( context.isCanceled() ) @@ -609,8 +656,8 @@ void QgsSingleColorPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *p alreadyPrintedDebug = true; } } - const QgsVector3D point = context.mapToWorldCoordinates( QgsVector3D( x, y, z ) ); - outNormal.positions.push_back( QVector3D( static_cast( point.x() ), static_cast( point.y() ), static_cast( point.z() ) ) ); + const QgsVector3D point = QgsVector3D( x, y, z ) - output->positionsOrigin; + output->positions.push_back( point.toVector3D() ); } } @@ -636,7 +683,7 @@ bool QgsColorRampPointCloud3DSymbolHandler::prepare( const QgsPointCloud3DRender return true; } -void QgsColorRampPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context ) +void QgsColorRampPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, PointData *output ) { QgsPointCloudAttributeCollection attributes; const int xOffset = 0; @@ -705,6 +752,11 @@ void QgsColorRampPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const QgsVector3D blockScale = block->scale(); const QgsVector3D blockOffset = block->offset(); + if ( !output ) + output = &outNormal; + + output->positionsOrigin = originFromNodeBounds( pc, n, context, block.get() ); + for ( int i = 0; i < count; ++i ) { if ( context.isCanceled() ) @@ -729,20 +781,20 @@ void QgsColorRampPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, alreadyPrintedDebug = true; } } - const QgsVector3D point = context.mapToWorldCoordinates( QgsVector3D( x, y, z ) ); - outNormal.positions.push_back( QVector3D( static_cast( point.x() ), static_cast( point.y() ), static_cast( point.z() ) ) ); + const QgsVector3D point = QgsVector3D( x, y, z ) - output->positionsOrigin; + output->positions.push_back( point.toVector3D() ); if ( attrIsX ) - outNormal.parameter.push_back( x ); + output->parameter.push_back( x ); else if ( attrIsY ) - outNormal.parameter.push_back( y ); + output->parameter.push_back( y ); else if ( attrIsZ ) - outNormal.parameter.push_back( z ); + output->parameter.push_back( z ); else { float iParam = 0.0f; context.getAttribute( ptr, i * recordSize + attributeOffset, attributeType, iParam ); - outNormal.parameter.push_back( iParam ); + output->parameter.push_back( iParam ); } } } @@ -769,7 +821,7 @@ bool QgsRGBPointCloud3DSymbolHandler::prepare( const QgsPointCloud3DRenderContex return true; } -void QgsRGBPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context ) +void QgsRGBPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, PointData *output ) { QgsPointCloudAttributeCollection attributes; attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "X" ), QgsPointCloudAttribute::Int32 ) ); @@ -822,6 +874,11 @@ void QgsRGBPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const const bool useBlueContrastEnhancement = blueContrastEnhancement && blueContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement; const bool useGreenContrastEnhancement = greenContrastEnhancement && greenContrastEnhancement->contrastEnhancementAlgorithm() != QgsContrastEnhancement::NoEnhancement; + if ( !output ) + output = &outNormal; + + output->positionsOrigin = originFromNodeBounds( pc, n, context, block.get() ); + int ir = 0; int ig = 0; int ib = 0; @@ -848,7 +905,7 @@ void QgsRGBPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const alreadyPrintedDebug = true; } } - const QgsVector3D point = context.mapToWorldCoordinates( QgsVector3D( x, y, z ) ); + const QgsVector3D point = QgsVector3D( x, y, z ) - output->positionsOrigin; QVector3D color( 0.0f, 0.0f, 0.0f ); @@ -882,8 +939,8 @@ void QgsRGBPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const color.setY( ig / 255.0f ); color.setZ( ib / 255.0f ); - outNormal.positions.push_back( QVector3D( static_cast( point.x() ), static_cast( point.y() ), static_cast( point.z() ) ) ); - outNormal.colors.push_back( color ); + output->positions.push_back( point.toVector3D() ); + output->colors.push_back( color ); } } @@ -909,7 +966,7 @@ bool QgsClassificationPointCloud3DSymbolHandler::prepare( const QgsPointCloud3DR return true; } -void QgsClassificationPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context ) +void QgsClassificationPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, PointData *output ) { QgsPointCloudAttributeCollection attributes; const int xOffset = 0; @@ -987,6 +1044,11 @@ void QgsClassificationPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex context.symbol() ? context.symbol()->pointSize() : 1.0 ); } + if ( !output ) + output = &outNormal; + + output->positionsOrigin = originFromNodeBounds( pc, n, context, block.get() ); + const QSet filteredOutValues = context.getFilteredOutValues(); for ( int i = 0; i < count; ++i ) { @@ -1012,7 +1074,7 @@ void QgsClassificationPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex alreadyPrintedDebug = true; } } - const QgsVector3D point = context.mapToWorldCoordinates( QgsVector3D( x, y, z ) ); + const QgsVector3D point = QgsVector3D( x, y, z ) - output->positionsOrigin; float iParam = 0.0f; if ( attrIsX ) iParam = x; @@ -1026,12 +1088,12 @@ void QgsClassificationPointCloud3DSymbolHandler::processNode( QgsPointCloudIndex if ( filteredOutValues.contains( ( int ) iParam ) || ! categoriesValues.contains( ( int ) iParam ) ) continue; - outNormal.positions.push_back( QVector3D( static_cast( point.x() ), static_cast( point.y() ), static_cast( point.z() ) ) ); + output->positions.push_back( point.toVector3D() ); // find iParam actual index in the categories list float iParam2 = categoriesValues.indexOf( ( int )iParam ) + 1; - outNormal.parameter.push_back( iParam2 ); - outNormal.pointSizes.push_back( categoriesPointSizes.value( ( int ) iParam ) ); + output->parameter.push_back( iParam2 ); + output->pointSizes.push_back( categoriesPointSizes.value( ( int ) iParam ) ); } } diff --git a/src/3d/symbols/qgspointcloud3dsymbol_p.h b/src/3d/symbols/qgspointcloud3dsymbol_p.h index fd5d9d4b4668..b3d20c7ae70b 100644 --- a/src/3d/symbols/qgspointcloud3dsymbol_p.h +++ b/src/3d/symbols/qgspointcloud3dsymbol_p.h @@ -36,15 +36,17 @@ class IndexedPointCloudNode; class QgsAABB; -class QgsPointCloud3DSymbolHandler // : public QgsFeature3DHandler +class QgsPointCloud3DSymbolHandler { public: QgsPointCloud3DSymbolHandler(); virtual ~QgsPointCloud3DSymbolHandler() = default; + struct PointData; + virtual bool prepare( const QgsPointCloud3DRenderContext &context ) = 0;// override; - virtual void processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context ) = 0; // override; + virtual void processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, PointData *output = nullptr ) = 0; // override; virtual void finalize( Qt3DCore::QEntity *parent, const QgsPointCloud3DRenderContext &context ) = 0;// override; void triangulate( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, const QgsAABB &bbox ); @@ -55,7 +57,8 @@ class QgsPointCloud3DSymbolHandler // : public QgsFeature3DHandler //! temporary data we will pass to the tessellator struct PointData { - QVector positions; // Contains triplets of float x,y,z for each point + QgsVector3D positionsOrigin; // All "positions" are relative to this point, defined in map coordinates (with double precision) + QVector positions; // Contains triplets of float x,y,z for each point. These are in map coordinates, relative to "positionsOrigin" QVector parameter; QVector pointSizes; // Contains point sizes, in case they are overridden for classification renderer QVector colors; @@ -103,7 +106,7 @@ class QgsSingleColorPointCloud3DSymbolHandler : public QgsPointCloud3DSymbolHand QgsSingleColorPointCloud3DSymbolHandler(); bool prepare( const QgsPointCloud3DRenderContext &context ) override; - void processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context ) override; + void processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, PointData *output = nullptr ) override; void finalize( Qt3DCore::QEntity *parent, const QgsPointCloud3DRenderContext &context ) override; private: @@ -120,7 +123,7 @@ class QgsColorRampPointCloud3DSymbolHandler : public QgsPointCloud3DSymbolHandle QgsColorRampPointCloud3DSymbolHandler(); bool prepare( const QgsPointCloud3DRenderContext &context ) override; - void processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context ) override; + void processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, PointData *output = nullptr ) override; void finalize( Qt3DCore::QEntity *parent, const QgsPointCloud3DRenderContext &context ) override; private: @@ -137,7 +140,7 @@ class QgsRGBPointCloud3DSymbolHandler : public QgsPointCloud3DSymbolHandler QgsRGBPointCloud3DSymbolHandler(); bool prepare( const QgsPointCloud3DRenderContext &context ) override; - void processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context ) override; + void processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, PointData *output = nullptr ) override; void finalize( Qt3DCore::QEntity *parent, const QgsPointCloud3DRenderContext &context ) override; private: @@ -154,7 +157,7 @@ class QgsClassificationPointCloud3DSymbolHandler : public QgsPointCloud3DSymbolH QgsClassificationPointCloud3DSymbolHandler(); bool prepare( const QgsPointCloud3DRenderContext &context ) override; - void processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context ) override; + void processNode( QgsPointCloudIndex *pc, const IndexedPointCloudNode &n, const QgsPointCloud3DRenderContext &context, PointData *output = nullptr ) override; void finalize( Qt3DCore::QEntity *parent, const QgsPointCloud3DRenderContext &context ) override; private: diff --git a/tests/src/3d/testqgspointcloud3drendering.cpp b/tests/src/3d/testqgspointcloud3drendering.cpp index 79b4125bf4ea..3258038020a8 100644 --- a/tests/src/3d/testqgspointcloud3drendering.cpp +++ b/tests/src/3d/testqgspointcloud3drendering.cpp @@ -313,7 +313,7 @@ void TestQgsPointCloud3DRendering::testPointCloudAttributeByRamp() // find a better fix in the future. QImage img = Qgs3DUtils::captureSceneImage( engine, scene ); - QGSVERIFYIMAGECHECK( "pointcloud_3d_colorramp", "pointcloud_3d_colorramp", img, QString(), 80, QSize( 0, 0 ), 15 ); + QGSVERIFYIMAGECHECK( "pointcloud_3d_colorramp", "pointcloud_3d_colorramp", img, QString(), 100, QSize( 0, 0 ), 15 ); } void TestQgsPointCloud3DRendering::testPointCloudClassification() @@ -350,7 +350,7 @@ void TestQgsPointCloud3DRendering::testPointCloudClassification() // find a better fix in the future. QImage img = Qgs3DUtils::captureSceneImage( engine, scene ); - QGSVERIFYIMAGECHECK( "pointcloud_3d_classification", "pointcloud_3d_classification", img, QString(), 80, QSize( 0, 0 ), 15 ); + QGSVERIFYIMAGECHECK( "pointcloud_3d_classification", "pointcloud_3d_classification", img, QString(), 100, QSize( 0, 0 ), 15 ); } void TestQgsPointCloud3DRendering::testPointCloudClassificationOverridePointSizes()