diff --git a/src/app/3d/qgs3dmaptoolpointcloudchangeattribute.cpp b/src/app/3d/qgs3dmaptoolpointcloudchangeattribute.cpp index 1d861ab3a536..f4c0c79ea3b0 100644 --- a/src/app/3d/qgs3dmaptoolpointcloudchangeattribute.cpp +++ b/src/app/3d/qgs3dmaptoolpointcloudchangeattribute.cpp @@ -202,15 +202,49 @@ SelectedPoints Qgs3DMapToolPointCloudChangeAttribute::searchPoints( QgsPointClou mapToPixel3D.origin = mCanvas->mapSettings()->origin(); mapToPixel3D.canvasSize = mCanvas->size(); - const QVector chunks = mCanvas->scene()->getLayerActiveChunkNodes( layer ); - for ( const QgsChunkNode *chunk : chunks ) + QgsCoordinateTransform ct( layer->crs(), mCanvas->mapSettings()->crs(), mCanvas->mapSettings()->transformContext() ); + ct.setBallparkTransformsAreAppropriate( true ); + const double zValueScale = layer->elevationProperties()->zScale(); + const double zValueOffset = layer->elevationProperties()->zOffset(); + + QgsPointCloudIndex index = layer->index(); + QVector nodes; + QQueue queue; + queue.append( index.root() ); + while ( !queue.empty() ) { - // check whether the hull intersects the search polygon - const QgsGeometry hull = box3DToPolygonInScreenSpace( chunk->box3D(), mapToPixel3D ); - if ( !searchPolygon.intersects( hull.constGet() ) ) + const QgsPointCloudNode node = index.getNode( queue.constFirst() ); + queue.removeFirst(); + + const QgsBox3D bounds = node.bounds(); + QgsVector3D extentMin3D( bounds.xMinimum(), bounds.yMinimum(), bounds.zMinimum() * zValueScale + zValueOffset ); + QgsVector3D extentMax3D( bounds.xMaximum(), bounds.yMaximum(), bounds.zMaximum() * zValueScale + zValueOffset ); + try + { + extentMin3D = ct.transform( extentMin3D ); + extentMax3D = ct.transform( extentMax3D ); + } + catch ( QgsCsException & ) + { + QgsDebugError( QStringLiteral( "Error transforming node bounds coordinate" ) ); continue; + } + + const QgsBox3D box( extentMin3D.x(), extentMin3D.y(), extentMin3D.z(), extentMax3D.x(), extentMax3D.y(), extentMax3D.z() ); + // check whether the hull intersects the search polygon + const QgsGeometry hull = box3DToPolygonInScreenSpace( box, mapToPixel3D ); + if ( searchPolygon.intersects( hull.constGet() ) ) + { + nodes.append( node.id() ); + for ( const QgsPointCloudNodeId &child : node.children() ) + { + queue.append( child ); + } + } + } - const QgsPointCloudNodeId n( chunk->tileId().d, chunk->tileId().x, chunk->tileId().y, chunk->tileId().z ); + for ( const QgsPointCloudNodeId &n : nodes ) + { const QVector pts = selectedPointsInNode( searchPolygon, n, mapToPixel3D, layer ); if ( !pts.isEmpty() ) {