Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Virtual point clouds overview in 2D #59854

Merged
merged 8 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions python/PyQt6/core/auto_additions/qgis.py
Original file line number Diff line number Diff line change
Expand Up @@ -11130,6 +11130,21 @@
"""
# --
Qgis.PointCloudAccessType.baseClass = Qgis
# monkey patching scoped based enum
Qgis.PointCloudZoomOutRenderBehavior.RenderExtents.__doc__ = "Render only point cloud extents when zoomed out"
Qgis.PointCloudZoomOutRenderBehavior.RenderOverview.__doc__ = "Render overview point cloud when zoomed out"
Qgis.PointCloudZoomOutRenderBehavior.RenderOverviewAndExtents.__doc__ = "Render point cloud extents over overview point cloud"
Qgis.PointCloudZoomOutRenderBehavior.__doc__ = """Point cloud zoom out options

.. versionadded:: 3.42

* ``RenderExtents``: Render only point cloud extents when zoomed out
* ``RenderOverview``: Render overview point cloud when zoomed out
* ``RenderOverviewAndExtents``: Render point cloud extents over overview point cloud

"""
# --
Qgis.PointCloudZoomOutRenderBehavior.baseClass = Qgis
try:
Qgis.__attribute_docs__ = {'QGIS_DEV_VERSION': 'The development version', 'DEFAULT_SEARCH_RADIUS_MM': 'Identify search radius in mm', 'DEFAULT_MAPTOPIXEL_THRESHOLD': 'Default threshold between map coordinates and device coordinates for map2pixel simplification', 'DEFAULT_HIGHLIGHT_COLOR': 'Default highlight color. The transparency is expected to only be applied to polygon\nfill. Lines and outlines are rendered opaque.', 'DEFAULT_HIGHLIGHT_BUFFER_MM': 'Default highlight buffer in mm.', 'DEFAULT_HIGHLIGHT_MIN_WIDTH_MM': 'Default highlight line/stroke minimum width in mm.', 'SCALE_PRECISION': 'Fudge factor used to compare two scales. The code is often going from scale to scale\ndenominator. So it looses precision and, when a limit is inclusive, can lead to errors.\nTo avoid that, use this factor instead of using <= or >=.\n\n.. deprecated:: 3.40\n\n No longer used by QGIS and will be removed in QGIS 4.0.', 'DEFAULT_Z_COORDINATE': 'Default Z coordinate value.\nThis value have to be assigned to the Z coordinate for the vertex.', 'DEFAULT_M_COORDINATE': 'Default M coordinate value.\nThis value have to be assigned to the M coordinate for the vertex.\n\n.. versionadded:: 3.20', 'UI_SCALE_FACTOR': 'UI scaling factor. This should be applied to all widget sizes obtained from font metrics,\nto account for differences in the default font sizes across different platforms.', 'DEFAULT_SNAP_TOLERANCE': 'Default snapping distance tolerance.', 'DEFAULT_SNAP_UNITS': 'Default snapping distance units.'}
Qgis.version = staticmethod(Qgis.version)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,20 @@ Sets the text format renderers should use for rendering labels
%Docstring
Returns the text format renderer is using for rendering labels

.. versionadded:: 3.42
%End

void setZoomOutBehavior( const Qgis::PointCloudZoomOutRenderBehavior behavior );
%Docstring
Sets the renderer behavior when zoomed out

.. versionadded:: 3.42
%End

Qgis::PointCloudZoomOutRenderBehavior zoomOutBehavior() const;
%Docstring
Returns the renderer behavior when zoomed out

.. versionadded:: 3.42
%End

Expand Down
7 changes: 7 additions & 0 deletions python/PyQt6/core/auto_generated/qgis.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -3255,6 +3255,13 @@ The development version
Remote
};

enum class PointCloudZoomOutRenderBehavior /BaseType=IntEnum/
{
RenderExtents,
RenderOverview,
RenderOverviewAndExtents
};

static const double DEFAULT_SEARCH_RADIUS_MM;

static const float DEFAULT_MAPTOPIXEL_THRESHOLD;
Expand Down
15 changes: 15 additions & 0 deletions python/core/auto_additions/qgis.py
Original file line number Diff line number Diff line change
Expand Up @@ -11040,6 +11040,21 @@
"""
# --
Qgis.PointCloudAccessType.baseClass = Qgis
# monkey patching scoped based enum
Qgis.PointCloudZoomOutRenderBehavior.RenderExtents.__doc__ = "Render only point cloud extents when zoomed out"
Qgis.PointCloudZoomOutRenderBehavior.RenderOverview.__doc__ = "Render overview point cloud when zoomed out"
Qgis.PointCloudZoomOutRenderBehavior.RenderOverviewAndExtents.__doc__ = "Render point cloud extents over overview point cloud"
Qgis.PointCloudZoomOutRenderBehavior.__doc__ = """Point cloud zoom out options

.. versionadded:: 3.42

* ``RenderExtents``: Render only point cloud extents when zoomed out
* ``RenderOverview``: Render overview point cloud when zoomed out
* ``RenderOverviewAndExtents``: Render point cloud extents over overview point cloud

"""
# --
Qgis.PointCloudZoomOutRenderBehavior.baseClass = Qgis
from enum import Enum


Expand Down
14 changes: 14 additions & 0 deletions python/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,20 @@ Sets the text format renderers should use for rendering labels
%Docstring
Returns the text format renderer is using for rendering labels

.. versionadded:: 3.42
%End

void setZoomOutBehavior( const Qgis::PointCloudZoomOutRenderBehavior behavior );
%Docstring
Sets the renderer behavior when zoomed out

.. versionadded:: 3.42
%End

Qgis::PointCloudZoomOutRenderBehavior zoomOutBehavior() const;
%Docstring
Returns the renderer behavior when zoomed out

.. versionadded:: 3.42
%End

Expand Down
7 changes: 7 additions & 0 deletions python/core/auto_generated/qgis.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -3255,6 +3255,13 @@ The development version
Remote
};

enum class PointCloudZoomOutRenderBehavior
{
RenderExtents,
RenderOverview,
RenderOverviewAndExtents
};

static const double DEFAULT_SEARCH_RADIUS_MM;

static const float DEFAULT_MAPTOPIXEL_THRESHOLD;
Expand Down
23 changes: 15 additions & 8 deletions src/core/pointcloud/qgspointcloudlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@
#include "qgscopcpointcloudindex.h"
#endif

#include "qgsvirtualpointcloudprovider.h"


#include <QUrl>

QgsPointCloudLayer::QgsPointCloudLayer( const QString &uri,
Expand Down Expand Up @@ -956,16 +959,20 @@ void QgsPointCloudLayer::loadIndexesForRenderContext( QgsRenderContext &renderer
}

const QVector<QgsPointCloudSubIndex> subIndex = mDataProvider->subIndexes();
for ( int i = 0; i < subIndex.size(); ++i )
if ( const QgsVirtualPointCloudProvider *vpcProvider = dynamic_cast<QgsVirtualPointCloudProvider *>( mDataProvider.get() ) )
{
// no need to load as it's there
if ( subIndex.at( i ).index() )
continue;

if ( subIndex.at( i ).extent().intersects( renderExtent ) &&
renderExtent.width() < subIndex.at( i ).extent().width() )
for ( int i = 0; i < subIndex.size(); ++i )
{
mDataProvider->loadSubIndex( i );
// no need to load as it's there
if ( subIndex.at( i ).index() )
continue;

if ( subIndex.at( i ).extent().intersects( renderExtent ) &&
( renderExtent.width() < vpcProvider->averageSubIndexWidth() ||
renderExtent.height() < vpcProvider->averageSubIndexHeight() ) )
{
mDataProvider->loadSubIndex( i );
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/pointcloud/qgspointcloudlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,4 +300,4 @@ class CORE_EXPORT QgsPointCloudLayer : public QgsMapLayer, public QgsAbstractPro
};


#endif // QGSPOINTCLOUDPLAYER_H
#endif // QGSPOINTCLOUDLAYER_H
76 changes: 50 additions & 26 deletions src/core/pointcloud/qgspointcloudlayerrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "qgspointcloudrequest.h"
#include "qgsrendercontext.h"
#include "qgsruntimeprofiler.h"
#include "qgsvirtualpointcloudprovider.h"

#include <delaunator.hpp>

Expand Down Expand Up @@ -196,39 +197,62 @@ bool QgsPointCloudLayerRenderer::render()
{
canceled = !renderIndex( pc );
}
else
else if ( const QgsVirtualPointCloudProvider *vpcProvider = dynamic_cast<QgsVirtualPointCloudProvider *>( mLayer->dataProvider() ) )
{
mSubIndexExtentRenderer->startRender( context );
for ( const auto &si : mSubIndexes )
QVector< QgsPointCloudSubIndex > visibleIndexes;
for ( const QgsPointCloudSubIndex &si : mSubIndexes )
{
if ( canceled )
break;

QgsPointCloudIndex pc = si.index();

if ( !renderExtent.intersects( si.extent() ) )
continue;

if ( !pc || !pc.isValid() || renderExtent.width() > si.extent().width() )
if ( renderExtent.intersects( si.extent() ) )
{
// when dealing with virtual point clouds, we want to render the individual extents when zoomed out
// and only use the selected renderer when zoomed in
mSubIndexExtentRenderer->renderExtent( si.polygonBounds(), context );
// render the label of point cloud tile
if ( mSubIndexExtentRenderer->showLabels() )
{
mSubIndexExtentRenderer->renderLabel(
context.renderContext().mapToPixel().transformBounds( si.extent().toRectF() ),
si.uri().section( "/", -1 ).section( ".", 0, 0 ),
context );
}
visibleIndexes.append( si );
}
}
const bool zoomedOut = renderExtent.width() > vpcProvider->averageSubIndexWidth() ||
renderExtent.height() > vpcProvider->averageSubIndexHeight();
QgsPointCloudIndex overviewIndex = vpcProvider->overview();
// if the overview of virtual point cloud exists, and we are zoomed out, we render just overview
if ( vpcProvider->overview() && zoomedOut &&
mRenderer->zoomOutBehavior() == Qgis::PointCloudZoomOutRenderBehavior::RenderOverview )
{
renderIndex( overviewIndex );
}
else
{
// if the overview of virtual point cloud exists, and we are zoomed out, but we want both overview and extents,
// we render overview
if ( vpcProvider->overview() && zoomedOut &&
mRenderer->zoomOutBehavior() == Qgis::PointCloudZoomOutRenderBehavior::RenderOverviewAndExtents )
{
renderIndex( overviewIndex );
}
else
mSubIndexExtentRenderer->startRender( context );
for ( const QgsPointCloudSubIndex &si : visibleIndexes )
{
canceled = !renderIndex( pc );
if ( canceled )
break;

QgsPointCloudIndex pc = si.index();
// if the index of point cloud is invalid, or we are zoomed out and want extents, we render the point cloud extent
if ( !pc || !pc.isValid() || ( ( mRenderer->zoomOutBehavior() == Qgis::PointCloudZoomOutRenderBehavior::RenderExtents || mRenderer->zoomOutBehavior() == Qgis::PointCloudZoomOutRenderBehavior::RenderOverviewAndExtents ) &&
zoomedOut ) )
{
mSubIndexExtentRenderer->renderExtent( si.polygonBounds(), context );
if ( mSubIndexExtentRenderer->showLabels() )
{
mSubIndexExtentRenderer->renderLabel(
context.renderContext().mapToPixel().transformBounds( si.extent().toRectF() ),
si.uri().section( "/", -1 ).section( ".", 0, 0 ),
context );
}
}
// else we just render the visible point cloud
else
{
canceled = !renderIndex( pc );
}
}
mSubIndexExtentRenderer->stopRender( context );
}
mSubIndexExtentRenderer->stopRender( context );
}

mRenderer->stopRender( context );
Expand Down
14 changes: 9 additions & 5 deletions src/core/pointcloud/qgspointcloudrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "qgslogger.h"
#include "qgscircle.h"
#include "qgsunittypes.h"
#include "qgsvirtualpointcloudprovider.h"

#include <QThread>
#include <QPointer>
Expand Down Expand Up @@ -68,7 +69,7 @@ QgsPointCloudRenderer::QgsPointCloudRenderer()
settings.setEnabled( true );
settings.setSize( 1 );
textFormat.setBuffer( settings );
mLabelTextFormat = ( textFormat );
mLabelTextFormat = textFormat;
}

QgsPointCloudRenderer *QgsPointCloudRenderer::load( QDomElement &element, const QgsReadWriteContext &context )
Expand Down Expand Up @@ -218,6 +219,7 @@ void QgsPointCloudRenderer::copyCommonProperties( QgsPointCloudRenderer *destina

destination->setShowLabels( mShowLabels );
destination->setLabelTextFormat( mLabelTextFormat );
destination->setZoomOutBehavior( mZoomOutBehavior );
}

void QgsPointCloudRenderer::restoreCommonProperties( const QDomElement &element, const QgsReadWriteContext &context )
Expand All @@ -228,8 +230,8 @@ void QgsPointCloudRenderer::restoreCommonProperties( const QDomElement &element,

mMaximumScreenError = element.attribute( QStringLiteral( "maximumScreenError" ), QStringLiteral( "0.3" ) ).toDouble();
mMaximumScreenErrorUnit = QgsUnitTypes::decodeRenderUnit( element.attribute( QStringLiteral( "maximumScreenErrorUnit" ), QStringLiteral( "MM" ) ) );
mPointSymbol = static_cast< Qgis::PointCloudSymbol >( element.attribute( QStringLiteral( "pointSymbol" ), QStringLiteral( "0" ) ).toInt() );
mDrawOrder2d = static_cast< Qgis::PointCloudDrawOrder >( element.attribute( QStringLiteral( "drawOrder2d" ), QStringLiteral( "0" ) ).toInt() );
mPointSymbol = qgsEnumKeyToValue( element.attribute( QStringLiteral( "pointSymbol" ) ), Qgis::PointCloudSymbol::Square );
mDrawOrder2d = qgsEnumKeyToValue( element.attribute( QStringLiteral( "drawOrder2d" ) ), Qgis::PointCloudDrawOrder::Default );

mRenderAsTriangles = element.attribute( QStringLiteral( "renderAsTriangles" ), QStringLiteral( "0" ) ).toInt();
mHorizontalTriangleFilter = element.attribute( QStringLiteral( "horizontalTriangleFilter" ), QStringLiteral( "0" ) ).toInt();
Expand All @@ -242,6 +244,7 @@ void QgsPointCloudRenderer::restoreCommonProperties( const QDomElement &element,
mLabelTextFormat = QgsTextFormat();
mLabelTextFormat.readXml( element.firstChildElement( QStringLiteral( "text-style" ) ), context );
}
mZoomOutBehavior = qgsEnumKeyToValue( element.attribute( QStringLiteral( "zoomOutBehavior" ) ), Qgis::PointCloudZoomOutRenderBehavior::RenderExtents );
}

void QgsPointCloudRenderer::saveCommonProperties( QDomElement &element, const QgsReadWriteContext &context ) const
Expand All @@ -252,8 +255,8 @@ void QgsPointCloudRenderer::saveCommonProperties( QDomElement &element, const Qg

element.setAttribute( QStringLiteral( "maximumScreenError" ), qgsDoubleToString( mMaximumScreenError ) );
element.setAttribute( QStringLiteral( "maximumScreenErrorUnit" ), QgsUnitTypes::encodeUnit( mMaximumScreenErrorUnit ) );
element.setAttribute( QStringLiteral( "pointSymbol" ), QString::number( static_cast< int >( mPointSymbol ) ) );
element.setAttribute( QStringLiteral( "drawOrder2d" ), QString::number( static_cast< int >( mDrawOrder2d ) ) );
element.setAttribute( QStringLiteral( "pointSymbol" ), qgsEnumValueToKey( mPointSymbol ) );
element.setAttribute( QStringLiteral( "drawOrder2d" ), qgsEnumValueToKey( mDrawOrder2d ) );

element.setAttribute( QStringLiteral( "renderAsTriangles" ), QString::number( static_cast< int >( mRenderAsTriangles ) ) );
element.setAttribute( QStringLiteral( "horizontalTriangleFilter" ), QString::number( static_cast< int >( mHorizontalTriangleFilter ) ) );
Expand All @@ -267,6 +270,7 @@ void QgsPointCloudRenderer::saveCommonProperties( QDomElement &element, const Qg
QDomDocument doc = element.ownerDocument();
element.appendChild( mLabelTextFormat.writeXml( doc, context ) );
}
element.setAttribute( QStringLiteral( "zoomOutBehavior" ), qgsEnumValueToKey( mZoomOutBehavior ) );
}

Qgis::PointCloudSymbol QgsPointCloudRenderer::pointSymbol() const
Expand Down
14 changes: 14 additions & 0 deletions src/core/pointcloud/qgspointcloudrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,18 @@ class CORE_EXPORT QgsPointCloudRenderer
*/
QgsTextFormat labelTextFormat() const { return mLabelTextFormat; }

/**
* Sets the renderer behavior when zoomed out
* \since QGIS 3.42
*/
void setZoomOutBehavior( const Qgis::PointCloudZoomOutRenderBehavior behavior ) { mZoomOutBehavior = behavior; }

/**
* Returns the renderer behavior when zoomed out
* \since QGIS 3.42
*/
Qgis::PointCloudZoomOutRenderBehavior zoomOutBehavior() const { return mZoomOutBehavior; }

protected:

/**
Expand Down Expand Up @@ -842,6 +854,8 @@ class CORE_EXPORT QgsPointCloudRenderer

bool mShowLabels = false;
QgsTextFormat mLabelTextFormat;

Qgis::PointCloudZoomOutRenderBehavior mZoomOutBehavior = Qgis::PointCloudZoomOutRenderBehavior::RenderExtents;
};

#endif // QGSPOINTCLOUDRENDERER_H
Loading
Loading