From a531725b794d8d75bbc0cddf9dc9317d63e1faa7 Mon Sep 17 00:00:00 2001 From: Withalion Date: Tue, 10 Dec 2024 21:13:49 +0100 Subject: [PATCH 1/8] Implement virtual point cloud overviews in 2D Load overview if it exists either by ref from vpc file or look for overview file. Render overview instead of extends by default when zoomed out. --- src/core/pointcloud/qgspointcloudlayer.cpp | 7 ++- src/core/pointcloud/qgspointcloudlayer.h | 2 +- .../pointcloud/qgspointcloudlayerrenderer.cpp | 61 ++++++++++++------- .../vpc/qgsvirtualpointcloudprovider.cpp | 37 +++++++++-- .../vpc/qgsvirtualpointcloudprovider.h | 23 +++++++ 5 files changed, 102 insertions(+), 28 deletions(-) diff --git a/src/core/pointcloud/qgspointcloudlayer.cpp b/src/core/pointcloud/qgspointcloudlayer.cpp index 2cae35482674..7f6518835346 100644 --- a/src/core/pointcloud/qgspointcloudlayer.cpp +++ b/src/core/pointcloud/qgspointcloudlayer.cpp @@ -45,6 +45,9 @@ #include "qgscopcpointcloudindex.h" #endif +#include "qgsvirtualpointcloudprovider.h" + + #include QgsPointCloudLayer::QgsPointCloudLayer( const QString &uri, @@ -956,6 +959,7 @@ void QgsPointCloudLayer::loadIndexesForRenderContext( QgsRenderContext &renderer } const QVector subIndex = mDataProvider->subIndexes(); + const QgsVirtualPointCloudProvider &vpcProvider = dynamic_cast( *mDataProvider ); for ( int i = 0; i < subIndex.size(); ++i ) { // no need to load as it's there @@ -963,7 +967,8 @@ void QgsPointCloudLayer::loadIndexesForRenderContext( QgsRenderContext &renderer continue; if ( subIndex.at( i ).extent().intersects( renderExtent ) && - renderExtent.width() < subIndex.at( i ).extent().width() ) + renderExtent.width() < vpcProvider.averageSubIndexWidth() && + renderExtent.height() < vpcProvider.averageSubIndexHeight() ) { mDataProvider->loadSubIndex( i ); } diff --git a/src/core/pointcloud/qgspointcloudlayer.h b/src/core/pointcloud/qgspointcloudlayer.h index 706e3ebbdc7a..06b9b127353b 100644 --- a/src/core/pointcloud/qgspointcloudlayer.h +++ b/src/core/pointcloud/qgspointcloudlayer.h @@ -300,4 +300,4 @@ class CORE_EXPORT QgsPointCloudLayer : public QgsMapLayer, public QgsAbstractPro }; -#endif // QGSPOINTCLOUDPLAYER_H +#endif // QGSPOINTCLOUDLAYER_H diff --git a/src/core/pointcloud/qgspointcloudlayerrenderer.cpp b/src/core/pointcloud/qgspointcloudlayerrenderer.cpp index 2528366b2e0f..752e8a018781 100644 --- a/src/core/pointcloud/qgspointcloudlayerrenderer.cpp +++ b/src/core/pointcloud/qgspointcloudlayerrenderer.cpp @@ -36,6 +36,8 @@ #include "qgspointcloudrequest.h" #include "qgsrendercontext.h" #include "qgsruntimeprofiler.h" +#include "qgsapplication.h" +#include "qgsvirtualpointcloudprovider.h" #include @@ -198,37 +200,52 @@ bool QgsPointCloudLayerRenderer::render() } else { - mSubIndexExtentRenderer->startRender( context ); + const QgsVirtualPointCloudProvider &vpcProvider = dynamic_cast( *mLayer->dataProvider() ); + QVector< QgsPointCloudSubIndex > visibleIndexes; for ( const auto &si : mSubIndexes ) { - if ( canceled ) - break; + if ( renderExtent.intersects( si.extent() ) ) + { + visibleIndexes.append( si ); + } + } + // if the overview of virtual point cloud exists we render it when we are zoomed out + if ( vpcProvider.overview() != nullptr && + renderExtent.width() > vpcProvider.averageSubIndexWidth() && + renderExtent.height() > vpcProvider.averageSubIndexHeight() ) + { + renderIndex( vpcProvider.overview() ); + } + else + { + mSubIndexExtentRenderer->startRender( context ); + for ( const auto &si : visibleIndexes ) + { + if ( canceled ) + break; QgsPointCloudIndex pc = si.index(); - if ( !renderExtent.intersects( si.extent() ) ) - continue; - - if ( !pc || !pc.isValid() || renderExtent.width() > si.extent().width() ) - { - // 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() ) + if ( !pc || !pc.isValid() ) { - mSubIndexExtentRenderer->renderLabel( - context.renderContext().mapToPixel().transformBounds( si.extent().toRectF() ), - si.uri().section( "/", -1 ).section( ".", 0, 0 ), - context ); + // TODO: render the individual extents when zoomed out and users requests them + 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 ); + } + } + else + { + canceled = !renderIndex( pc ); } } - else - { - canceled = !renderIndex( pc ); - } + mSubIndexExtentRenderer->stopRender( context ); } - mSubIndexExtentRenderer->stopRender( context ); } mRenderer->stopRender( context ); diff --git a/src/core/providers/vpc/qgsvirtualpointcloudprovider.cpp b/src/core/providers/vpc/qgsvirtualpointcloudprovider.cpp index c606dfd929d0..d0d572f981dc 100644 --- a/src/core/providers/vpc/qgsvirtualpointcloudprovider.cpp +++ b/src/core/providers/vpc/qgsvirtualpointcloudprovider.cpp @@ -177,6 +177,8 @@ void QgsVirtualPointCloudProvider::parseFile() } QSet attributeNames; + double subIndexesWidth = 0.0; + double subIndexesHeight = 0.0; for ( const auto &f : data["features"] ) { @@ -202,12 +204,35 @@ void QgsVirtualPointCloudProvider::parseFile() QgsGeometry geometry; QgsDoubleRange zRange; - for ( const auto &asset : f["assets"] ) + // look directly for link to data file + if ( f["assets"].find( "data" ) != f["assets"].end() ) { - if ( asset.contains( "href" ) ) + if ( f["assets"]["data"].contains( "href" ) ) { - uri = QString::fromStdString( asset["href"] ); - break; + uri = QString::fromStdString( f["assets"]["data"]["href"] ); + } + } + + // look for vpc overview reference + if ( mOverview == nullptr && f["assets"].find( "overview" ) != f["assets"].end() ) + { + if ( f["assets"]["overview"].contains( "href" ) ) + { + mOverview = std::make_unique(); + mOverview->load( fInfo.absoluteDir().absoluteFilePath( QString::fromStdString( f["assets"]["overview"]["href"] ) ) ); + } + } + // if it doesn't exist look for overview file in the directory + else if ( mOverview == nullptr ) + { + QDir vpcDir = fInfo.absoluteDir(); + QStringList nameFilter = { "*overview.*laz" }; + vpcDir.setNameFilters( nameFilter ); + vpcDir.setFilter( QDir::Files ); + if ( !vpcDir.entryList().empty() ) + { + mOverview = std::make_unique(); + mOverview->load( vpcDir.absoluteFilePath( vpcDir.entryList().first() ) ); } } @@ -364,12 +389,16 @@ void QgsVirtualPointCloudProvider::parseFile() } } + subIndexesWidth += extent.width(); + subIndexesHeight += extent.height(); mPolygonBounds->addPart( geometry ); mPointCount += count; QgsPointCloudSubIndex si( uri, geometry, extent, zRange, count ); mSubLayers.push_back( si ); } mExtent = mPolygonBounds->boundingBox(); + mAverageSubIndexWidth = subIndexesWidth / mSubLayers.size(); + mAverageSubIndexHeight = subIndexesHeight / mSubLayers.size(); populateAttributeCollection( attributeNames ); } diff --git a/src/core/providers/vpc/qgsvirtualpointcloudprovider.h b/src/core/providers/vpc/qgsvirtualpointcloudprovider.h index d6be5dba8434..27bf5736c751 100644 --- a/src/core/providers/vpc/qgsvirtualpointcloudprovider.h +++ b/src/core/providers/vpc/qgsvirtualpointcloudprovider.h @@ -61,6 +61,26 @@ class CORE_EXPORT QgsVirtualPointCloudProvider: public QgsPointCloudDataProvider QgsPointCloudRenderer *createRenderer( const QVariantMap &configuration = QVariantMap() ) const override SIP_FACTORY; bool renderInPreview( const QgsDataProvider::PreviewContext & ) override { return false; } + /** + * Returns pointer to the overview index. May be NULLPTR if it doesn't exist. + * \since QGIS 3.42 + */ + QgsPointCloudIndex *overview() const { return mOverview.get(); } + + /** + * Returns the calculated average width of point clouds. + * \note We use this value to calculate when to switch between overview and point clouds + * \since QGIS 3.42 + */ + double averageSubIndexWidth() const { return mAverageSubIndexWidth; } + + /** + * Returns the calculated average height of point clouds. + * \note We use this value to calculate when to switch between overview and point clouds + * \since QGIS 3.42 + */ + double averageSubIndexHeight() const { return mAverageSubIndexHeight; } + signals: void subIndexLoaded( int i ); @@ -70,11 +90,14 @@ class CORE_EXPORT QgsVirtualPointCloudProvider: public QgsPointCloudDataProvider QVector mSubLayers; std::unique_ptr mPolygonBounds; QgsPointCloudAttributeCollection mAttributes; + std::unique_ptr mOverview; QStringList mUriList; QgsRectangle mExtent; qint64 mPointCount = 0; QgsCoordinateReferenceSystem mCrs; + double mAverageSubIndexWidth = 0; + double mAverageSubIndexHeight = 0; }; class QgsVirtualPointCloudProviderMetadata : public QgsProviderMetadata From 6a33188d46e6044acc20705775284e93055b499d Mon Sep 17 00:00:00 2001 From: Withalion Date: Wed, 11 Dec 2024 14:16:15 +0100 Subject: [PATCH 2/8] Add option to change between VPC overview and extends --- .../pointcloud/qgspointcloudrenderer.sip.in | 14 ++++ .../pointcloud/qgspointcloudrenderer.sip.in | 14 ++++ .../pointcloud/qgspointcloudlayerrenderer.cpp | 10 ++- src/core/pointcloud/qgspointcloudrenderer.cpp | 3 + src/core/pointcloud/qgspointcloudrenderer.h | 14 ++++ .../qgspointcloudrendererpropertieswidget.cpp | 10 ++- .../qgspointcloudrendererpropsdialogbase.ui | 76 ++++++++++++------- 7 files changed, 106 insertions(+), 35 deletions(-) diff --git a/python/PyQt6/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in b/python/PyQt6/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in index 8960f45ba28e..4e67e5eae229 100644 --- a/python/PyQt6/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in +++ b/python/PyQt6/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in @@ -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 setShowExtends( const bool show ); +%Docstring +Set whether the renderer should render point cloud extends instead of overview when zoomed out + +.. versionadded:: 3.42 +%End + + bool showExtends() const; +%Docstring +Returns whether the renderer renders point cloud extends instead of overview when zoomed out + .. versionadded:: 3.42 %End diff --git a/python/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in b/python/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in index 8960f45ba28e..4e67e5eae229 100644 --- a/python/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in +++ b/python/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in @@ -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 setShowExtends( const bool show ); +%Docstring +Set whether the renderer should render point cloud extends instead of overview when zoomed out + +.. versionadded:: 3.42 +%End + + bool showExtends() const; +%Docstring +Returns whether the renderer renders point cloud extends instead of overview when zoomed out + .. versionadded:: 3.42 %End diff --git a/src/core/pointcloud/qgspointcloudlayerrenderer.cpp b/src/core/pointcloud/qgspointcloudlayerrenderer.cpp index 752e8a018781..eaf918cdda5a 100644 --- a/src/core/pointcloud/qgspointcloudlayerrenderer.cpp +++ b/src/core/pointcloud/qgspointcloudlayerrenderer.cpp @@ -36,7 +36,6 @@ #include "qgspointcloudrequest.h" #include "qgsrendercontext.h" #include "qgsruntimeprofiler.h" -#include "qgsapplication.h" #include "qgsvirtualpointcloudprovider.h" #include @@ -209,8 +208,10 @@ bool QgsPointCloudLayerRenderer::render() visibleIndexes.append( si ); } } - // if the overview of virtual point cloud exists we render it when we are zoomed out + // if the overview of virtual point cloud exists and user hasn't requested point cloud extends we render overview, + // when we are zoomed out if ( vpcProvider.overview() != nullptr && + !mRenderer->showExtends() && renderExtent.width() > vpcProvider.averageSubIndexWidth() && renderExtent.height() > vpcProvider.averageSubIndexHeight() ) { @@ -226,9 +227,10 @@ bool QgsPointCloudLayerRenderer::render() QgsPointCloudIndex pc = si.index(); - if ( !pc || !pc.isValid() ) + if ( ( !pc || !pc.isValid() || mRenderer->showExtends() ) && + renderExtent.width() > vpcProvider.averageSubIndexWidth() && + renderExtent.height() > vpcProvider.averageSubIndexHeight() ) { - // TODO: render the individual extents when zoomed out and users requests them mSubIndexExtentRenderer->renderExtent( si.polygonBounds(), context ); // render the label of point cloud tile if ( mSubIndexExtentRenderer->showLabels() ) diff --git a/src/core/pointcloud/qgspointcloudrenderer.cpp b/src/core/pointcloud/qgspointcloudrenderer.cpp index 6dadab581821..a5cfdab88a23 100644 --- a/src/core/pointcloud/qgspointcloudrenderer.cpp +++ b/src/core/pointcloud/qgspointcloudrenderer.cpp @@ -218,6 +218,7 @@ void QgsPointCloudRenderer::copyCommonProperties( QgsPointCloudRenderer *destina destination->setShowLabels( mShowLabels ); destination->setLabelTextFormat( mLabelTextFormat ); + destination->setShowExtends( mShowExtends ); } void QgsPointCloudRenderer::restoreCommonProperties( const QDomElement &element, const QgsReadWriteContext &context ) @@ -242,6 +243,7 @@ void QgsPointCloudRenderer::restoreCommonProperties( const QDomElement &element, mLabelTextFormat = QgsTextFormat(); mLabelTextFormat.readXml( element.firstChildElement( QStringLiteral( "text-style" ) ), context ); } + mShowExtends = element.attribute( QStringLiteral( "showExtends" ), QStringLiteral( "0" ) ).toInt(); } void QgsPointCloudRenderer::saveCommonProperties( QDomElement &element, const QgsReadWriteContext &context ) const @@ -267,6 +269,7 @@ void QgsPointCloudRenderer::saveCommonProperties( QDomElement &element, const Qg QDomDocument doc = element.ownerDocument(); element.appendChild( mLabelTextFormat.writeXml( doc, context ) ); } + element.setAttribute( QStringLiteral( "showExtends" ), QString::number( mShowExtends ) ); } Qgis::PointCloudSymbol QgsPointCloudRenderer::pointSymbol() const diff --git a/src/core/pointcloud/qgspointcloudrenderer.h b/src/core/pointcloud/qgspointcloudrenderer.h index f58db6489962..0a4711595cf2 100644 --- a/src/core/pointcloud/qgspointcloudrenderer.h +++ b/src/core/pointcloud/qgspointcloudrenderer.h @@ -701,6 +701,18 @@ class CORE_EXPORT QgsPointCloudRenderer */ QgsTextFormat labelTextFormat() const { return mLabelTextFormat; } + /** + * Set whether the renderer should render point cloud extends instead of overview when zoomed out + * \since QGIS 3.42 + */ + void setShowExtends( const bool show ) { mShowExtends = show; } + + /** + * Returns whether the renderer renders point cloud extends instead of overview when zoomed out + * \since QGIS 3.42 + */ + bool showExtends() const { return mShowExtends; } + protected: /** @@ -842,6 +854,8 @@ class CORE_EXPORT QgsPointCloudRenderer bool mShowLabels = false; QgsTextFormat mLabelTextFormat; + + bool mShowExtends = false; }; #endif // QGSPOINTCLOUDRENDERER_H diff --git a/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp b/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp index 10cff78b9836..b0000b1d9b5c 100644 --- a/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp +++ b/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp @@ -124,11 +124,11 @@ QgsPointCloudRendererPropertiesWidget::QgsPointCloudRendererPropertiesWidget( Qg connect( mHorizontalTriangleThresholdSpinBox, qOverload( &QgsDoubleSpinBox::valueChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); connect( mHorizontalTriangleUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); - // show label options only for virtual point clouds - bool showLabelOptions = !mLayer->dataProvider()->subIndexes().isEmpty(); - mLabels->setVisible( showLabelOptions ); - mLabelOptions->setVisible( showLabelOptions ); + // show virtual point cloud options only when vpc layer is selected + bool showVpcOptions = !mLayer->dataProvider()->subIndexes().isEmpty(); + mVpcGroupBox->setVisible( showVpcOptions ); mLabelOptions->setDialogTitle( tr( "Customize label text" ) ); + connect( mExtendsCheckBox, &QCheckBox::stateChanged, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); connect( mLabels, &QCheckBox::stateChanged, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); connect( mLabelOptions, &QgsFontButton::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); @@ -191,6 +191,7 @@ void QgsPointCloudRendererPropertiesWidget::syncToLayer( QgsMapLayer *layer ) { mLabels->setChecked( mLayer->renderer()->showLabels() ); mLabelOptions->setTextFormat( mLayer->renderer()->labelTextFormat() ); + mExtendsCheckBox->setChecked( mLayer->renderer()->showExtends() ); } } @@ -234,6 +235,7 @@ void QgsPointCloudRendererPropertiesWidget::apply() mLayer->renderer()->setShowLabels( mLabels->isChecked() ); mLayer->renderer()->setLabelTextFormat( mLabelOptions->textFormat() ); + mLayer->renderer()->setShowExtends( mExtendsCheckBox->isChecked() ); } void QgsPointCloudRendererPropertiesWidget::rendererChanged() diff --git a/src/ui/pointcloud/qgspointcloudrendererpropsdialogbase.ui b/src/ui/pointcloud/qgspointcloudrendererpropsdialogbase.ui index b7886305121e..bd318a6fd248 100644 --- a/src/ui/pointcloud/qgspointcloudrendererpropsdialogbase.ui +++ b/src/ui/pointcloud/qgspointcloudrendererpropsdialogbase.ui @@ -169,6 +169,55 @@ + + + + Virtual Point Cloud Options + + + false + + + false + + + + + + Show tile labels + + + + + + + Qt::Horizontal + + + + 301 + 20 + + + + + + + + + + + + + + + Show point cloud extends + + + + + + @@ -279,33 +328,6 @@ 6 - - - - Show tile labels - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - From dfcebc0b95ff9fb78628addc1717ff8f6283da1d Mon Sep 17 00:00:00 2001 From: Withalion Date: Thu, 12 Dec 2024 13:17:43 +0100 Subject: [PATCH 3/8] Remake overview vpc options --- python/PyQt6/core/auto_additions/qgis.py | 15 +++++ .../pointcloud/qgspointcloudrenderer.sip.in | 8 +-- python/PyQt6/core/auto_generated/qgis.sip.in | 7 +++ .../pointcloud/qgspointcloudrenderer.sip.in | 8 +-- python/core/auto_generated/qgis.sip.in | 7 +++ .../pointcloud/qgspointcloudlayerrenderer.cpp | 30 ++++++---- src/core/pointcloud/qgspointcloudrenderer.cpp | 9 +-- src/core/pointcloud/qgspointcloudrenderer.h | 10 ++-- .../vpc/qgsvirtualpointcloudprovider.cpp | 7 ++- src/core/qgis.h | 12 ++++ .../qgspointcloudrendererpropertieswidget.cpp | 59 ++++++++++++++++--- .../qgspointcloudrendererpropsdialogbase.ui | 21 ++++--- 12 files changed, 147 insertions(+), 46 deletions(-) diff --git a/python/PyQt6/core/auto_additions/qgis.py b/python/PyQt6/core/auto_additions/qgis.py index c55fd59435e3..bb55f022be0a 100644 --- a/python/PyQt6/core/auto_additions/qgis.py +++ b/python/PyQt6/core/auto_additions/qgis.py @@ -11088,6 +11088,21 @@ # -- Qgis.MouseHandlesAction.baseClass = Qgis # monkey patching scoped based enum +Qgis.PointCloudZoomOutBehavior.Extent.__doc__ = "" +Qgis.PointCloudZoomOutBehavior.Overview.__doc__ = "" +Qgis.PointCloudZoomOutBehavior.Both.__doc__ = "" +Qgis.PointCloudZoomOutBehavior.__doc__ = """Point cloud zoom out options + +.. versionadded:: 3.42 + +* ``Extent``: +* ``Overview``: +* ``Both``: + +""" +# -- +Qgis.PointCloudZoomOutBehavior.baseClass = Qgis +# monkey patching scoped based enum Qgis.MeshRangeLimit.NotSet.__doc__ = "User defined" Qgis.MeshRangeLimit.MinimumMaximum.__doc__ = "Real min-max values" Qgis.MeshRangeLimit.__doc__ = """Describes the limits used to compute mesh ranges (min/max values). diff --git a/python/PyQt6/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in b/python/PyQt6/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in index 4e67e5eae229..dae015de5821 100644 --- a/python/PyQt6/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in +++ b/python/PyQt6/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in @@ -578,16 +578,16 @@ Returns the text format renderer is using for rendering labels .. versionadded:: 3.42 %End - void setShowExtends( const bool show ); + void setZoomOutBehavior( const Qgis::PointCloudZoomOutBehavior behavior ); %Docstring -Set whether the renderer should render point cloud extends instead of overview when zoomed out +Sets the renderer behavior when zoomed out .. versionadded:: 3.42 %End - bool showExtends() const; + Qgis::PointCloudZoomOutBehavior zoomOutBehavior() const; %Docstring -Returns whether the renderer renders point cloud extends instead of overview when zoomed out +Returns the renderer behavior when zoomed out .. versionadded:: 3.42 %End diff --git a/python/PyQt6/core/auto_generated/qgis.sip.in b/python/PyQt6/core/auto_generated/qgis.sip.in index 51de848c4c18..5829efa5b446 100644 --- a/python/PyQt6/core/auto_generated/qgis.sip.in +++ b/python/PyQt6/core/auto_generated/qgis.sip.in @@ -3249,6 +3249,13 @@ The development version UpdatedCanvas, }; + enum class PointCloudZoomOutBehavior /BaseType=IntEnum/ + { + Extent, + Overview, + Both + }; + enum class PointCloudAccessType /BaseType=IntEnum/ { Local, diff --git a/python/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in b/python/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in index 4e67e5eae229..dae015de5821 100644 --- a/python/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in +++ b/python/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in @@ -578,16 +578,16 @@ Returns the text format renderer is using for rendering labels .. versionadded:: 3.42 %End - void setShowExtends( const bool show ); + void setZoomOutBehavior( const Qgis::PointCloudZoomOutBehavior behavior ); %Docstring -Set whether the renderer should render point cloud extends instead of overview when zoomed out +Sets the renderer behavior when zoomed out .. versionadded:: 3.42 %End - bool showExtends() const; + Qgis::PointCloudZoomOutBehavior zoomOutBehavior() const; %Docstring -Returns whether the renderer renders point cloud extends instead of overview when zoomed out +Returns the renderer behavior when zoomed out .. versionadded:: 3.42 %End diff --git a/python/core/auto_generated/qgis.sip.in b/python/core/auto_generated/qgis.sip.in index a978d6ff2b8a..8ae9abd56da7 100644 --- a/python/core/auto_generated/qgis.sip.in +++ b/python/core/auto_generated/qgis.sip.in @@ -3249,6 +3249,13 @@ The development version UpdatedCanvas, }; + enum class PointCloudZoomOutBehavior + { + Extent, + Overview, + Both + }; + enum class PointCloudAccessType { Local, diff --git a/src/core/pointcloud/qgspointcloudlayerrenderer.cpp b/src/core/pointcloud/qgspointcloudlayerrenderer.cpp index eaf918cdda5a..8c7444f94f8f 100644 --- a/src/core/pointcloud/qgspointcloudlayerrenderer.cpp +++ b/src/core/pointcloud/qgspointcloudlayerrenderer.cpp @@ -199,6 +199,7 @@ bool QgsPointCloudLayerRenderer::render() } else { + // we can be sure this won't fail as we are rendering virtual point clouds in this branch const QgsVirtualPointCloudProvider &vpcProvider = dynamic_cast( *mLayer->dataProvider() ); QVector< QgsPointCloudSubIndex > visibleIndexes; for ( const auto &si : mSubIndexes ) @@ -208,31 +209,37 @@ bool QgsPointCloudLayerRenderer::render() visibleIndexes.append( si ); } } - // if the overview of virtual point cloud exists and user hasn't requested point cloud extends we render overview, - // when we are zoomed out + const bool zoomedOut = renderExtent.width() > vpcProvider.averageSubIndexWidth() && + renderExtent.height() > vpcProvider.averageSubIndexHeight(); + // if the overview of virtual point cloud exists, and we are zoomed out, we render just overview if ( vpcProvider.overview() != nullptr && - !mRenderer->showExtends() && - renderExtent.width() > vpcProvider.averageSubIndexWidth() && - renderExtent.height() > vpcProvider.averageSubIndexHeight() ) + mRenderer->zoomOutBehavior() == Qgis::PointCloudZoomOutBehavior::Overview && + zoomedOut ) { renderIndex( vpcProvider.overview() ); } 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() != nullptr && + mRenderer->zoomOutBehavior() == Qgis::PointCloudZoomOutBehavior::Both && + zoomedOut ) + { + renderIndex( vpcProvider.overview() ); + } mSubIndexExtentRenderer->startRender( context ); for ( const auto &si : visibleIndexes ) { if ( canceled ) break; - QgsPointCloudIndex pc = si.index(); - - if ( ( !pc || !pc.isValid() || mRenderer->showExtends() ) && - renderExtent.width() > vpcProvider.averageSubIndexWidth() && - renderExtent.height() > vpcProvider.averageSubIndexHeight() ) + 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::PointCloudZoomOutBehavior::Extent || mRenderer->zoomOutBehavior() == Qgis::PointCloudZoomOutBehavior::Both ) && + zoomedOut ) ) { mSubIndexExtentRenderer->renderExtent( si.polygonBounds(), context ); - // render the label of point cloud tile if ( mSubIndexExtentRenderer->showLabels() ) { mSubIndexExtentRenderer->renderLabel( @@ -241,6 +248,7 @@ bool QgsPointCloudLayerRenderer::render() context ); } } + // else we just render the visible point cloud else { canceled = !renderIndex( pc ); diff --git a/src/core/pointcloud/qgspointcloudrenderer.cpp b/src/core/pointcloud/qgspointcloudrenderer.cpp index a5cfdab88a23..2598989dcdd9 100644 --- a/src/core/pointcloud/qgspointcloudrenderer.cpp +++ b/src/core/pointcloud/qgspointcloudrenderer.cpp @@ -25,6 +25,7 @@ #include "qgslogger.h" #include "qgscircle.h" #include "qgsunittypes.h" +#include "qgsvirtualpointcloudprovider.h" #include #include @@ -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 ) @@ -218,7 +219,7 @@ void QgsPointCloudRenderer::copyCommonProperties( QgsPointCloudRenderer *destina destination->setShowLabels( mShowLabels ); destination->setLabelTextFormat( mLabelTextFormat ); - destination->setShowExtends( mShowExtends ); + destination->setZoomOutBehavior( mZoomOutBehavior ); } void QgsPointCloudRenderer::restoreCommonProperties( const QDomElement &element, const QgsReadWriteContext &context ) @@ -243,7 +244,7 @@ void QgsPointCloudRenderer::restoreCommonProperties( const QDomElement &element, mLabelTextFormat = QgsTextFormat(); mLabelTextFormat.readXml( element.firstChildElement( QStringLiteral( "text-style" ) ), context ); } - mShowExtends = element.attribute( QStringLiteral( "showExtends" ), QStringLiteral( "0" ) ).toInt(); + mZoomOutBehavior = static_cast( element.attribute( QStringLiteral( "zoomOutBehavior" ), QStringLiteral( "0" ) ).toInt() ); } void QgsPointCloudRenderer::saveCommonProperties( QDomElement &element, const QgsReadWriteContext &context ) const @@ -269,7 +270,7 @@ void QgsPointCloudRenderer::saveCommonProperties( QDomElement &element, const Qg QDomDocument doc = element.ownerDocument(); element.appendChild( mLabelTextFormat.writeXml( doc, context ) ); } - element.setAttribute( QStringLiteral( "showExtends" ), QString::number( mShowExtends ) ); + element.setAttribute( QStringLiteral( "zoomOutBehavior" ), QString::number( static_cast( mZoomOutBehavior ) ) ); } Qgis::PointCloudSymbol QgsPointCloudRenderer::pointSymbol() const diff --git a/src/core/pointcloud/qgspointcloudrenderer.h b/src/core/pointcloud/qgspointcloudrenderer.h index 0a4711595cf2..c3ced87cfc51 100644 --- a/src/core/pointcloud/qgspointcloudrenderer.h +++ b/src/core/pointcloud/qgspointcloudrenderer.h @@ -702,16 +702,16 @@ class CORE_EXPORT QgsPointCloudRenderer QgsTextFormat labelTextFormat() const { return mLabelTextFormat; } /** - * Set whether the renderer should render point cloud extends instead of overview when zoomed out + * Sets the renderer behavior when zoomed out * \since QGIS 3.42 */ - void setShowExtends( const bool show ) { mShowExtends = show; } + void setZoomOutBehavior( const Qgis::PointCloudZoomOutBehavior behavior ) { mZoomOutBehavior = behavior; } /** - * Returns whether the renderer renders point cloud extends instead of overview when zoomed out + * Returns the renderer behavior when zoomed out * \since QGIS 3.42 */ - bool showExtends() const { return mShowExtends; } + Qgis::PointCloudZoomOutBehavior zoomOutBehavior() const { return mZoomOutBehavior; } protected: @@ -855,7 +855,7 @@ class CORE_EXPORT QgsPointCloudRenderer bool mShowLabels = false; QgsTextFormat mLabelTextFormat; - bool mShowExtends = false; + Qgis::PointCloudZoomOutBehavior mZoomOutBehavior = Qgis::PointCloudZoomOutBehavior::Extent; }; #endif // QGSPOINTCLOUDRENDERER_H diff --git a/src/core/providers/vpc/qgsvirtualpointcloudprovider.cpp b/src/core/providers/vpc/qgsvirtualpointcloudprovider.cpp index d0d572f981dc..3f5ad485fd00 100644 --- a/src/core/providers/vpc/qgsvirtualpointcloudprovider.cpp +++ b/src/core/providers/vpc/qgsvirtualpointcloudprovider.cpp @@ -538,7 +538,12 @@ QgsPointCloudRenderer *QgsVirtualPointCloudProvider::createRenderer( const QVari if ( mAttributes.indexOf( QLatin1String( "Classification" ) ) >= 0 ) { - return new QgsPointCloudClassifiedRenderer( QStringLiteral( "Classification" ), QgsPointCloudClassifiedRenderer::defaultCategories() ); + QgsPointCloudClassifiedRenderer *newRenderer = new QgsPointCloudClassifiedRenderer( QStringLiteral( "Classification" ), QgsPointCloudClassifiedRenderer::defaultCategories() ); + if ( mOverview != nullptr ) + { + newRenderer->setZoomOutBehavior( Qgis::PointCloudZoomOutBehavior::Overview ); + } + return newRenderer; } return new QgsPointCloudExtentRenderer(); diff --git a/src/core/qgis.h b/src/core/qgis.h index 1439ae053eb3..d67fea0211d1 100644 --- a/src/core/qgis.h +++ b/src/core/qgis.h @@ -5734,6 +5734,18 @@ class CORE_EXPORT Qgis }; Q_ENUM( PointCloudAccessType ) + /** + * Point cloud zoom out options + * \since QGIS 3.42 + */ + enum class PointCloudZoomOutBehavior : int + { + Extent, + Overview, + Both + }; + Q_ENUM( PointCloudZoomOutBehavior ) + /** * Identify search radius in mm */ diff --git a/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp b/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp index b0000b1d9b5c..8e7b356dd567 100644 --- a/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp +++ b/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp @@ -33,6 +33,7 @@ #include "qgsstyle.h" #include "qgssymbolwidgetcontext.h" #include "qgstextformatwidget.h" +#include "qgsvirtualpointcloudprovider.h" static bool initPointCloudRenderer( const QString &name, QgsPointCloudRendererWidgetFunc f, const QString &iconName = QString() ) { @@ -125,12 +126,44 @@ QgsPointCloudRendererPropertiesWidget::QgsPointCloudRendererPropertiesWidget( Qg connect( mHorizontalTriangleUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); // show virtual point cloud options only when vpc layer is selected - bool showVpcOptions = !mLayer->dataProvider()->subIndexes().isEmpty(); - mVpcGroupBox->setVisible( showVpcOptions ); - mLabelOptions->setDialogTitle( tr( "Customize label text" ) ); - connect( mExtendsCheckBox, &QCheckBox::stateChanged, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); - connect( mLabels, &QCheckBox::stateChanged, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); - connect( mLabelOptions, &QgsFontButton::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); + if ( !mLayer->dataProvider()->subIndexes().isEmpty() ) + { + mLabelOptions->setDialogTitle( tr( "Customize label text" ) ); + connect( mLabels, &QCheckBox::stateChanged, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); + connect( mLabelOptions, &QgsFontButton::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); + mZoomOutOptions->addItem( tr( "Show extents only" ), static_cast( Qgis::PointCloudZoomOutBehavior::Extent ) ); + try + { + const QgsVirtualPointCloudProvider &vpcProvider = dynamic_cast( *mLayer->dataProvider() ); + if ( vpcProvider.overview() != nullptr ) + { + mZoomOutOptions->addItem( tr( "Show overview only" ), static_cast( Qgis::PointCloudZoomOutBehavior::Overview ) ); + mZoomOutOptions->addItem( tr( "Show extents over overview" ), static_cast( Qgis::PointCloudZoomOutBehavior::Both ) ); + } + } + catch ( const std::bad_cast & ) + { + mZoomOutOptions->setDisabled( true ); + } + connect( mZoomOutOptions, static_cast( &QComboBox::currentIndexChanged ), this, [this]() { + Qgis::PointCloudZoomOutBehavior zoomOutBehavior = static_cast( mZoomOutOptions->currentData().toInt() ); + if ( zoomOutBehavior == Qgis::PointCloudZoomOutBehavior::Overview ) + { + mLabels->setDisabled( true ); + mLabelOptions->setDisabled( true ); + } + else + { + mLabels->setDisabled( false ); + mLabelOptions->setDisabled( false ); + } + emitWidgetChanged(); + } ); + } + else + { + mVpcGroupBox->setVisible( false ); + } syncToLayer( layer ); } @@ -191,7 +224,17 @@ void QgsPointCloudRendererPropertiesWidget::syncToLayer( QgsMapLayer *layer ) { mLabels->setChecked( mLayer->renderer()->showLabels() ); mLabelOptions->setTextFormat( mLayer->renderer()->labelTextFormat() ); - mExtendsCheckBox->setChecked( mLayer->renderer()->showExtends() ); + mZoomOutOptions->setCurrentIndex( static_cast( mLayer->renderer()->zoomOutBehavior() ) ); + if ( mLayer->renderer()->zoomOutBehavior() == Qgis::PointCloudZoomOutBehavior::Overview ) + { + mLabels->setDisabled( true ); + mLabelOptions->setDisabled( true ); + } + else + { + mLabels->setDisabled( false ); + mLabelOptions->setDisabled( false ); + } } } @@ -235,7 +278,7 @@ void QgsPointCloudRendererPropertiesWidget::apply() mLayer->renderer()->setShowLabels( mLabels->isChecked() ); mLayer->renderer()->setLabelTextFormat( mLabelOptions->textFormat() ); - mLayer->renderer()->setShowExtends( mExtendsCheckBox->isChecked() ); + mLayer->renderer()->setZoomOutBehavior( static_cast( mZoomOutOptions->currentData().toInt() ) ); } void QgsPointCloudRendererPropertiesWidget::rendererChanged() diff --git a/src/ui/pointcloud/qgspointcloudrendererpropsdialogbase.ui b/src/ui/pointcloud/qgspointcloudrendererpropsdialogbase.ui index bd318a6fd248..6fd5eca3f68c 100644 --- a/src/ui/pointcloud/qgspointcloudrendererpropsdialogbase.ui +++ b/src/ui/pointcloud/qgspointcloudrendererpropsdialogbase.ui @@ -181,13 +181,6 @@ false - - - - Show tile labels - - - @@ -201,6 +194,9 @@ + + + @@ -209,9 +205,16 @@ - + + + When zoomed out + + + + + - Show point cloud extends + Show tile labels From 790c5031f621124435deaad6e0f1b24fefe414f4 Mon Sep 17 00:00:00 2001 From: Withalion Date: Fri, 13 Dec 2024 15:15:36 +0100 Subject: [PATCH 4/8] Fix review issues --- python/PyQt6/core/auto_additions/qgis.py | 16 +++--- .../pointcloud/qgspointcloudrenderer.sip.in | 4 +- python/PyQt6/core/auto_generated/qgis.sip.in | 8 +-- python/core/auto_additions/qgis.py | 17 ++++++ .../pointcloud/qgspointcloudrenderer.sip.in | 4 +- python/core/auto_generated/qgis.sip.in | 8 +-- src/core/pointcloud/qgspointcloudlayer.cpp | 22 ++++---- .../pointcloud/qgspointcloudlayerrenderer.cpp | 24 ++++----- src/core/pointcloud/qgspointcloudrenderer.cpp | 2 +- src/core/pointcloud/qgspointcloudrenderer.h | 6 +-- .../vpc/qgsvirtualpointcloudprovider.cpp | 24 ++++----- src/core/qgis.h | 10 ++-- .../qgspointcloudrendererpropertieswidget.cpp | 54 +++++++++---------- 13 files changed, 104 insertions(+), 95 deletions(-) diff --git a/python/PyQt6/core/auto_additions/qgis.py b/python/PyQt6/core/auto_additions/qgis.py index bb55f022be0a..98b3a8a15afd 100644 --- a/python/PyQt6/core/auto_additions/qgis.py +++ b/python/PyQt6/core/auto_additions/qgis.py @@ -11088,20 +11088,20 @@ # -- Qgis.MouseHandlesAction.baseClass = Qgis # monkey patching scoped based enum -Qgis.PointCloudZoomOutBehavior.Extent.__doc__ = "" -Qgis.PointCloudZoomOutBehavior.Overview.__doc__ = "" -Qgis.PointCloudZoomOutBehavior.Both.__doc__ = "" -Qgis.PointCloudZoomOutBehavior.__doc__ = """Point cloud zoom out options +Qgis.PointCloudZoomOutRenderBehavior.RenderExtents.__doc__ = "" +Qgis.PointCloudZoomOutRenderBehavior.RenderOverview.__doc__ = "" +Qgis.PointCloudZoomOutRenderBehavior.RenderOverviewAndExtents.__doc__ = "" +Qgis.PointCloudZoomOutRenderBehavior.__doc__ = """Point cloud zoom out options .. versionadded:: 3.42 -* ``Extent``: -* ``Overview``: -* ``Both``: +* ``RenderExtents``: +* ``RenderOverview``: +* ``RenderOverviewAndExtents``: """ # -- -Qgis.PointCloudZoomOutBehavior.baseClass = Qgis +Qgis.PointCloudZoomOutRenderBehavior.baseClass = Qgis # monkey patching scoped based enum Qgis.MeshRangeLimit.NotSet.__doc__ = "User defined" Qgis.MeshRangeLimit.MinimumMaximum.__doc__ = "Real min-max values" diff --git a/python/PyQt6/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in b/python/PyQt6/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in index dae015de5821..7b4e7f2a7b5e 100644 --- a/python/PyQt6/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in +++ b/python/PyQt6/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in @@ -578,14 +578,14 @@ Returns the text format renderer is using for rendering labels .. versionadded:: 3.42 %End - void setZoomOutBehavior( const Qgis::PointCloudZoomOutBehavior behavior ); + void setZoomOutBehavior( const Qgis::PointCloudZoomOutRenderBehavior behavior ); %Docstring Sets the renderer behavior when zoomed out .. versionadded:: 3.42 %End - Qgis::PointCloudZoomOutBehavior zoomOutBehavior() const; + Qgis::PointCloudZoomOutRenderBehavior zoomOutBehavior() const; %Docstring Returns the renderer behavior when zoomed out diff --git a/python/PyQt6/core/auto_generated/qgis.sip.in b/python/PyQt6/core/auto_generated/qgis.sip.in index 5829efa5b446..ff9c22715712 100644 --- a/python/PyQt6/core/auto_generated/qgis.sip.in +++ b/python/PyQt6/core/auto_generated/qgis.sip.in @@ -3249,11 +3249,11 @@ The development version UpdatedCanvas, }; - enum class PointCloudZoomOutBehavior /BaseType=IntEnum/ + enum class PointCloudZoomOutRenderBehavior /BaseType=IntEnum/ { - Extent, - Overview, - Both + RenderExtents, + RenderOverview, + RenderOverviewAndExtents }; enum class PointCloudAccessType /BaseType=IntEnum/ diff --git a/python/core/auto_additions/qgis.py b/python/core/auto_additions/qgis.py index 50ecf2eb4c17..908b489d386a 100644 --- a/python/core/auto_additions/qgis.py +++ b/python/core/auto_additions/qgis.py @@ -10998,6 +10998,23 @@ # -- Qgis.MouseHandlesAction.baseClass = Qgis # monkey patching scoped based enum +Qgis.PointCloudZoomOutRenderBehavior.RenderExtents.__doc__ = "" +Qgis.PointCloudZoomOutRenderBehavior.RenderOverview.__doc__ = "" +Qgis.PointCloudZoomOutRenderBehavior.RenderOverviewAndExtents.__doc__ = "" +Qgis.PointCloudZoomOutRenderBehavior.__doc__ = """Point cloud zoom out options + +.. versionadded:: 3.42 + +* ``RenderExtents``: +* ``RenderOverview``: +* ``RenderOverviewAndExtents``: + +""" +# -- +Qgis.PointCloudZoomOutRenderBehavior.baseClass = Qgis +# -- +Qgis.MouseHandlesAction.baseClass = Qgis +# monkey patching scoped based enum Qgis.MeshRangeLimit.NotSet.__doc__ = "User defined" Qgis.MeshRangeLimit.MinimumMaximum.__doc__ = "Real min-max values" Qgis.MeshRangeLimit.__doc__ = """Describes the limits used to compute mesh ranges (min/max values). diff --git a/python/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in b/python/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in index dae015de5821..7b4e7f2a7b5e 100644 --- a/python/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in +++ b/python/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in @@ -578,14 +578,14 @@ Returns the text format renderer is using for rendering labels .. versionadded:: 3.42 %End - void setZoomOutBehavior( const Qgis::PointCloudZoomOutBehavior behavior ); + void setZoomOutBehavior( const Qgis::PointCloudZoomOutRenderBehavior behavior ); %Docstring Sets the renderer behavior when zoomed out .. versionadded:: 3.42 %End - Qgis::PointCloudZoomOutBehavior zoomOutBehavior() const; + Qgis::PointCloudZoomOutRenderBehavior zoomOutBehavior() const; %Docstring Returns the renderer behavior when zoomed out diff --git a/python/core/auto_generated/qgis.sip.in b/python/core/auto_generated/qgis.sip.in index 8ae9abd56da7..8a16963ede80 100644 --- a/python/core/auto_generated/qgis.sip.in +++ b/python/core/auto_generated/qgis.sip.in @@ -3249,11 +3249,11 @@ The development version UpdatedCanvas, }; - enum class PointCloudZoomOutBehavior + enum class PointCloudZoomOutRenderBehavior { - Extent, - Overview, - Both + RenderExtents, + RenderOverview, + RenderOverviewAndExtents }; enum class PointCloudAccessType diff --git a/src/core/pointcloud/qgspointcloudlayer.cpp b/src/core/pointcloud/qgspointcloudlayer.cpp index 7f6518835346..1bf95bdabf95 100644 --- a/src/core/pointcloud/qgspointcloudlayer.cpp +++ b/src/core/pointcloud/qgspointcloudlayer.cpp @@ -959,18 +959,20 @@ void QgsPointCloudLayer::loadIndexesForRenderContext( QgsRenderContext &renderer } const QVector subIndex = mDataProvider->subIndexes(); - const QgsVirtualPointCloudProvider &vpcProvider = dynamic_cast( *mDataProvider ); - for ( int i = 0; i < subIndex.size(); ++i ) + if ( const QgsVirtualPointCloudProvider *vpcProvider = dynamic_cast( 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() < vpcProvider.averageSubIndexWidth() && - renderExtent.height() < vpcProvider.averageSubIndexHeight() ) + 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 ); + } } } } diff --git a/src/core/pointcloud/qgspointcloudlayerrenderer.cpp b/src/core/pointcloud/qgspointcloudlayerrenderer.cpp index 8c7444f94f8f..eb6b5730352e 100644 --- a/src/core/pointcloud/qgspointcloudlayerrenderer.cpp +++ b/src/core/pointcloud/qgspointcloudlayerrenderer.cpp @@ -197,10 +197,8 @@ bool QgsPointCloudLayerRenderer::render() { canceled = !renderIndex( pc ); } - else + else if ( const QgsVirtualPointCloudProvider *vpcProvider = dynamic_cast( mLayer->dataProvider() ) ) { - // we can be sure this won't fail as we are rendering virtual point clouds in this branch - const QgsVirtualPointCloudProvider &vpcProvider = dynamic_cast( *mLayer->dataProvider() ); QVector< QgsPointCloudSubIndex > visibleIndexes; for ( const auto &si : mSubIndexes ) { @@ -209,24 +207,22 @@ bool QgsPointCloudLayerRenderer::render() visibleIndexes.append( si ); } } - const bool zoomedOut = renderExtent.width() > vpcProvider.averageSubIndexWidth() && - renderExtent.height() > vpcProvider.averageSubIndexHeight(); + const bool zoomedOut = renderExtent.width() > vpcProvider->averageSubIndexWidth() || + renderExtent.height() > vpcProvider->averageSubIndexHeight(); // if the overview of virtual point cloud exists, and we are zoomed out, we render just overview - if ( vpcProvider.overview() != nullptr && - mRenderer->zoomOutBehavior() == Qgis::PointCloudZoomOutBehavior::Overview && - zoomedOut ) + if ( vpcProvider->overview() && zoomedOut && + mRenderer->zoomOutBehavior() == Qgis::PointCloudZoomOutRenderBehavior::RenderOverview ) { - renderIndex( vpcProvider.overview() ); + renderIndex( vpcProvider->overview() ); } 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() != nullptr && - mRenderer->zoomOutBehavior() == Qgis::PointCloudZoomOutBehavior::Both && - zoomedOut ) + if ( vpcProvider->overview() && zoomedOut && + mRenderer->zoomOutBehavior() == Qgis::PointCloudZoomOutRenderBehavior::RenderOverviewAndExtents ) { - renderIndex( vpcProvider.overview() ); + renderIndex( vpcProvider->overview() ); } mSubIndexExtentRenderer->startRender( context ); for ( const auto &si : visibleIndexes ) @@ -236,7 +232,7 @@ bool QgsPointCloudLayerRenderer::render() 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::PointCloudZoomOutBehavior::Extent || mRenderer->zoomOutBehavior() == Qgis::PointCloudZoomOutBehavior::Both ) && + if ( !pc || !pc.isValid() || ( ( mRenderer->zoomOutBehavior() == Qgis::PointCloudZoomOutRenderBehavior::RenderExtents || mRenderer->zoomOutBehavior() == Qgis::PointCloudZoomOutRenderBehavior::RenderOverviewAndExtents ) && zoomedOut ) ) { mSubIndexExtentRenderer->renderExtent( si.polygonBounds(), context ); diff --git a/src/core/pointcloud/qgspointcloudrenderer.cpp b/src/core/pointcloud/qgspointcloudrenderer.cpp index 2598989dcdd9..3879810f9b22 100644 --- a/src/core/pointcloud/qgspointcloudrenderer.cpp +++ b/src/core/pointcloud/qgspointcloudrenderer.cpp @@ -244,7 +244,7 @@ void QgsPointCloudRenderer::restoreCommonProperties( const QDomElement &element, mLabelTextFormat = QgsTextFormat(); mLabelTextFormat.readXml( element.firstChildElement( QStringLiteral( "text-style" ) ), context ); } - mZoomOutBehavior = static_cast( element.attribute( QStringLiteral( "zoomOutBehavior" ), QStringLiteral( "0" ) ).toInt() ); + mZoomOutBehavior = static_cast( element.attribute( QStringLiteral( "zoomOutBehavior" ), QStringLiteral( "0" ) ).toInt() ); } void QgsPointCloudRenderer::saveCommonProperties( QDomElement &element, const QgsReadWriteContext &context ) const diff --git a/src/core/pointcloud/qgspointcloudrenderer.h b/src/core/pointcloud/qgspointcloudrenderer.h index c3ced87cfc51..6689e0ac6a85 100644 --- a/src/core/pointcloud/qgspointcloudrenderer.h +++ b/src/core/pointcloud/qgspointcloudrenderer.h @@ -705,13 +705,13 @@ class CORE_EXPORT QgsPointCloudRenderer * Sets the renderer behavior when zoomed out * \since QGIS 3.42 */ - void setZoomOutBehavior( const Qgis::PointCloudZoomOutBehavior behavior ) { mZoomOutBehavior = behavior; } + void setZoomOutBehavior( const Qgis::PointCloudZoomOutRenderBehavior behavior ) { mZoomOutBehavior = behavior; } /** * Returns the renderer behavior when zoomed out * \since QGIS 3.42 */ - Qgis::PointCloudZoomOutBehavior zoomOutBehavior() const { return mZoomOutBehavior; } + Qgis::PointCloudZoomOutRenderBehavior zoomOutBehavior() const { return mZoomOutBehavior; } protected: @@ -855,7 +855,7 @@ class CORE_EXPORT QgsPointCloudRenderer bool mShowLabels = false; QgsTextFormat mLabelTextFormat; - Qgis::PointCloudZoomOutBehavior mZoomOutBehavior = Qgis::PointCloudZoomOutBehavior::Extent; + Qgis::PointCloudZoomOutRenderBehavior mZoomOutBehavior = Qgis::PointCloudZoomOutRenderBehavior::RenderExtents; }; #endif // QGSPOINTCLOUDRENDERER_H diff --git a/src/core/providers/vpc/qgsvirtualpointcloudprovider.cpp b/src/core/providers/vpc/qgsvirtualpointcloudprovider.cpp index 3f5ad485fd00..9342c3c37ef5 100644 --- a/src/core/providers/vpc/qgsvirtualpointcloudprovider.cpp +++ b/src/core/providers/vpc/qgsvirtualpointcloudprovider.cpp @@ -205,28 +205,22 @@ void QgsVirtualPointCloudProvider::parseFile() QgsDoubleRange zRange; // look directly for link to data file - if ( f["assets"].find( "data" ) != f["assets"].end() ) + if ( f["assets"].contains( "data" ) && f["assets"]["data"].contains( "href" ) ) { - if ( f["assets"]["data"].contains( "href" ) ) - { - uri = QString::fromStdString( f["assets"]["data"]["href"] ); - } + uri = QString::fromStdString( f["assets"]["data"]["href"] ); } // look for vpc overview reference - if ( mOverview == nullptr && f["assets"].find( "overview" ) != f["assets"].end() ) + if ( !mOverview && f["assets"].contains( "overview" ) && f["assets"]["overview"].contains( "href" ) ) { - if ( f["assets"]["overview"].contains( "href" ) ) - { - mOverview = std::make_unique(); - mOverview->load( fInfo.absoluteDir().absoluteFilePath( QString::fromStdString( f["assets"]["overview"]["href"] ) ) ); - } + mOverview = std::make_unique(); + mOverview->load( fInfo.absoluteDir().absoluteFilePath( QString::fromStdString( f["assets"]["overview"]["href"] ) ) ); } // if it doesn't exist look for overview file in the directory - else if ( mOverview == nullptr ) + else if ( !mOverview ) { QDir vpcDir = fInfo.absoluteDir(); - QStringList nameFilter = { "*overview.*laz" }; + QStringList nameFilter = { QString( fInfo.baseName() + "-overview.copc.laz" ) }; vpcDir.setNameFilters( nameFilter ); vpcDir.setFilter( QDir::Files ); if ( !vpcDir.entryList().empty() ) @@ -539,9 +533,9 @@ QgsPointCloudRenderer *QgsVirtualPointCloudProvider::createRenderer( const QVari if ( mAttributes.indexOf( QLatin1String( "Classification" ) ) >= 0 ) { QgsPointCloudClassifiedRenderer *newRenderer = new QgsPointCloudClassifiedRenderer( QStringLiteral( "Classification" ), QgsPointCloudClassifiedRenderer::defaultCategories() ); - if ( mOverview != nullptr ) + if ( mOverview ) { - newRenderer->setZoomOutBehavior( Qgis::PointCloudZoomOutBehavior::Overview ); + newRenderer->setZoomOutBehavior( Qgis::PointCloudZoomOutRenderBehavior::RenderOverview ); } return newRenderer; } diff --git a/src/core/qgis.h b/src/core/qgis.h index d67fea0211d1..1a897d5874d1 100644 --- a/src/core/qgis.h +++ b/src/core/qgis.h @@ -5738,13 +5738,13 @@ class CORE_EXPORT Qgis * Point cloud zoom out options * \since QGIS 3.42 */ - enum class PointCloudZoomOutBehavior : int + enum class PointCloudZoomOutRenderBehavior : int { - Extent, - Overview, - Both + RenderExtents, + RenderOverview, + RenderOverviewAndExtents }; - Q_ENUM( PointCloudZoomOutBehavior ) + Q_ENUM( PointCloudZoomOutRenderBehavior ) /** * Identify search radius in mm diff --git a/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp b/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp index 8e7b356dd567..9d5ffa11aa30 100644 --- a/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp +++ b/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp @@ -131,31 +131,31 @@ QgsPointCloudRendererPropertiesWidget::QgsPointCloudRendererPropertiesWidget( Qg mLabelOptions->setDialogTitle( tr( "Customize label text" ) ); connect( mLabels, &QCheckBox::stateChanged, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); connect( mLabelOptions, &QgsFontButton::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); - mZoomOutOptions->addItem( tr( "Show extents only" ), static_cast( Qgis::PointCloudZoomOutBehavior::Extent ) ); - try + mZoomOutOptions->addItem( tr( "Show extents only" ), static_cast( Qgis::PointCloudZoomOutRenderBehavior::RenderExtents ) ); + + if ( const QgsVirtualPointCloudProvider *vpcProvider = dynamic_cast( mLayer->dataProvider() ) ) { - const QgsVirtualPointCloudProvider &vpcProvider = dynamic_cast( *mLayer->dataProvider() ); - if ( vpcProvider.overview() != nullptr ) + if ( vpcProvider->overview() ) { - mZoomOutOptions->addItem( tr( "Show overview only" ), static_cast( Qgis::PointCloudZoomOutBehavior::Overview ) ); - mZoomOutOptions->addItem( tr( "Show extents over overview" ), static_cast( Qgis::PointCloudZoomOutBehavior::Both ) ); + mZoomOutOptions->addItem( tr( "Show overview only" ), static_cast( Qgis::PointCloudZoomOutRenderBehavior::RenderOverview ) ); + mZoomOutOptions->addItem( tr( "Show extents over overview" ), static_cast( Qgis::PointCloudZoomOutRenderBehavior::RenderOverviewAndExtents ) ); } } - catch ( const std::bad_cast & ) + else { - mZoomOutOptions->setDisabled( true ); + mZoomOutOptions->setEnabled( false ); } - connect( mZoomOutOptions, static_cast( &QComboBox::currentIndexChanged ), this, [this]() { - Qgis::PointCloudZoomOutBehavior zoomOutBehavior = static_cast( mZoomOutOptions->currentData().toInt() ); - if ( zoomOutBehavior == Qgis::PointCloudZoomOutBehavior::Overview ) - { - mLabels->setDisabled( true ); - mLabelOptions->setDisabled( true ); - } - else + + connect( mZoomOutOptions, qOverload( &QComboBox::currentIndexChanged ), this, [this]( int currentZoomOutOption ) { + switch ( static_cast( currentZoomOutOption ) ) { - mLabels->setDisabled( false ); - mLabelOptions->setDisabled( false ); + case Qgis::PointCloudZoomOutRenderBehavior::RenderOverview: + mLabels->setEnabled( false ); + mLabelOptions->setEnabled( false ); + break; + default: + mLabels->setEnabled( true ); + mLabelOptions->setEnabled( true ); } emitWidgetChanged(); } ); @@ -225,15 +225,15 @@ void QgsPointCloudRendererPropertiesWidget::syncToLayer( QgsMapLayer *layer ) mLabels->setChecked( mLayer->renderer()->showLabels() ); mLabelOptions->setTextFormat( mLayer->renderer()->labelTextFormat() ); mZoomOutOptions->setCurrentIndex( static_cast( mLayer->renderer()->zoomOutBehavior() ) ); - if ( mLayer->renderer()->zoomOutBehavior() == Qgis::PointCloudZoomOutBehavior::Overview ) - { - mLabels->setDisabled( true ); - mLabelOptions->setDisabled( true ); - } - else + switch ( mLayer->renderer()->zoomOutBehavior() ) { - mLabels->setDisabled( false ); - mLabelOptions->setDisabled( false ); + case Qgis::PointCloudZoomOutRenderBehavior::RenderOverview: + mLabels->setEnabled( false ); + mLabelOptions->setEnabled( false ); + break; + default: + mLabels->setEnabled( true ); + mLabelOptions->setEnabled( true ); } } } @@ -278,7 +278,7 @@ void QgsPointCloudRendererPropertiesWidget::apply() mLayer->renderer()->setShowLabels( mLabels->isChecked() ); mLayer->renderer()->setLabelTextFormat( mLabelOptions->textFormat() ); - mLayer->renderer()->setZoomOutBehavior( static_cast( mZoomOutOptions->currentData().toInt() ) ); + mLayer->renderer()->setZoomOutBehavior( static_cast( mZoomOutOptions->currentData().toInt() ) ); } void QgsPointCloudRendererPropertiesWidget::rendererChanged() From 409972d5fe7d276da0d3f1802c169459bb70a3d4 Mon Sep 17 00:00:00 2001 From: Withalion Date: Sun, 15 Dec 2024 22:16:42 +0100 Subject: [PATCH 5/8] Fix review issues round 2 --- python/PyQt6/core/auto_additions/qgis.py | 12 +++---- python/core/auto_additions/qgis.py | 12 +++---- .../pointcloud/qgspointcloudlayerrenderer.cpp | 4 +-- src/core/pointcloud/qgspointcloudrenderer.cpp | 12 +++---- src/core/qgis.h | 6 ++-- .../qgspointcloudrendererpropertieswidget.cpp | 31 ++++++++++--------- 6 files changed, 39 insertions(+), 38 deletions(-) diff --git a/python/PyQt6/core/auto_additions/qgis.py b/python/PyQt6/core/auto_additions/qgis.py index 98b3a8a15afd..0036c32b0941 100644 --- a/python/PyQt6/core/auto_additions/qgis.py +++ b/python/PyQt6/core/auto_additions/qgis.py @@ -11088,16 +11088,16 @@ # -- Qgis.MouseHandlesAction.baseClass = Qgis # monkey patching scoped based enum -Qgis.PointCloudZoomOutRenderBehavior.RenderExtents.__doc__ = "" -Qgis.PointCloudZoomOutRenderBehavior.RenderOverview.__doc__ = "" -Qgis.PointCloudZoomOutRenderBehavior.RenderOverviewAndExtents.__doc__ = "" +Qgis.PointCloudZoomOutRenderBehavior.RenderExtents.__doc__ = "Render just point cloud extends when zoomed out" +Qgis.PointCloudZoomOutRenderBehavior.RenderOverview.__doc__ = "Render overview point cloud when zoomed out" +Qgis.PointCloudZoomOutRenderBehavior.RenderOverviewAndExtents.__doc__ = "Render extent polygons over overview point cloud" Qgis.PointCloudZoomOutRenderBehavior.__doc__ = """Point cloud zoom out options .. versionadded:: 3.42 -* ``RenderExtents``: -* ``RenderOverview``: -* ``RenderOverviewAndExtents``: +* ``RenderExtents``: Render just point cloud extends when zoomed out +* ``RenderOverview``: Render overview point cloud when zoomed out +* ``RenderOverviewAndExtents``: Render extent polygons over overview point cloud """ # -- diff --git a/python/core/auto_additions/qgis.py b/python/core/auto_additions/qgis.py index 908b489d386a..f01d0fe27377 100644 --- a/python/core/auto_additions/qgis.py +++ b/python/core/auto_additions/qgis.py @@ -10998,16 +10998,16 @@ # -- Qgis.MouseHandlesAction.baseClass = Qgis # monkey patching scoped based enum -Qgis.PointCloudZoomOutRenderBehavior.RenderExtents.__doc__ = "" -Qgis.PointCloudZoomOutRenderBehavior.RenderOverview.__doc__ = "" -Qgis.PointCloudZoomOutRenderBehavior.RenderOverviewAndExtents.__doc__ = "" +Qgis.PointCloudZoomOutRenderBehavior.RenderExtents.__doc__ = "Render just point cloud extends when zoomed out" +Qgis.PointCloudZoomOutRenderBehavior.RenderOverview.__doc__ = "Render overview point cloud when zoomed out" +Qgis.PointCloudZoomOutRenderBehavior.RenderOverviewAndExtents.__doc__ = "Render extent polygons over overview point cloud" Qgis.PointCloudZoomOutRenderBehavior.__doc__ = """Point cloud zoom out options .. versionadded:: 3.42 -* ``RenderExtents``: -* ``RenderOverview``: -* ``RenderOverviewAndExtents``: +* ``RenderExtents``: Render just point cloud extends when zoomed out +* ``RenderOverview``: Render overview point cloud when zoomed out +* ``RenderOverviewAndExtents``: Render extent polygons over overview point cloud """ # -- diff --git a/src/core/pointcloud/qgspointcloudlayerrenderer.cpp b/src/core/pointcloud/qgspointcloudlayerrenderer.cpp index eb6b5730352e..bdfc7976e808 100644 --- a/src/core/pointcloud/qgspointcloudlayerrenderer.cpp +++ b/src/core/pointcloud/qgspointcloudlayerrenderer.cpp @@ -200,7 +200,7 @@ bool QgsPointCloudLayerRenderer::render() else if ( const QgsVirtualPointCloudProvider *vpcProvider = dynamic_cast( mLayer->dataProvider() ) ) { QVector< QgsPointCloudSubIndex > visibleIndexes; - for ( const auto &si : mSubIndexes ) + for ( const QgsPointCloudSubIndex &si : mSubIndexes ) { if ( renderExtent.intersects( si.extent() ) ) { @@ -225,7 +225,7 @@ bool QgsPointCloudLayerRenderer::render() renderIndex( vpcProvider->overview() ); } mSubIndexExtentRenderer->startRender( context ); - for ( const auto &si : visibleIndexes ) + for ( const QgsPointCloudSubIndex &si : visibleIndexes ) { if ( canceled ) break; diff --git a/src/core/pointcloud/qgspointcloudrenderer.cpp b/src/core/pointcloud/qgspointcloudrenderer.cpp index 3879810f9b22..1ef20cf09d00 100644 --- a/src/core/pointcloud/qgspointcloudrenderer.cpp +++ b/src/core/pointcloud/qgspointcloudrenderer.cpp @@ -230,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(); @@ -244,7 +244,7 @@ void QgsPointCloudRenderer::restoreCommonProperties( const QDomElement &element, mLabelTextFormat = QgsTextFormat(); mLabelTextFormat.readXml( element.firstChildElement( QStringLiteral( "text-style" ) ), context ); } - mZoomOutBehavior = static_cast( element.attribute( QStringLiteral( "zoomOutBehavior" ), QStringLiteral( "0" ) ).toInt() ); + mZoomOutBehavior = qgsEnumKeyToValue( element.attribute( QStringLiteral( "zoomOutBehavior" ) ), Qgis::PointCloudZoomOutRenderBehavior::RenderExtents ); } void QgsPointCloudRenderer::saveCommonProperties( QDomElement &element, const QgsReadWriteContext &context ) const @@ -255,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 ) ) ); @@ -270,7 +270,7 @@ void QgsPointCloudRenderer::saveCommonProperties( QDomElement &element, const Qg QDomDocument doc = element.ownerDocument(); element.appendChild( mLabelTextFormat.writeXml( doc, context ) ); } - element.setAttribute( QStringLiteral( "zoomOutBehavior" ), QString::number( static_cast( mZoomOutBehavior ) ) ); + element.setAttribute( QStringLiteral( "zoomOutBehavior" ), qgsEnumValueToKey( mZoomOutBehavior ) ); } Qgis::PointCloudSymbol QgsPointCloudRenderer::pointSymbol() const diff --git a/src/core/qgis.h b/src/core/qgis.h index 1a897d5874d1..330f6a399c2e 100644 --- a/src/core/qgis.h +++ b/src/core/qgis.h @@ -5740,9 +5740,9 @@ class CORE_EXPORT Qgis */ enum class PointCloudZoomOutRenderBehavior : int { - RenderExtents, - RenderOverview, - RenderOverviewAndExtents + RenderExtents, //!< Render just point cloud extends when zoomed out + RenderOverview, //!< Render overview point cloud when zoomed out + RenderOverviewAndExtents //!< Render extent polygons over overview point cloud }; Q_ENUM( PointCloudZoomOutRenderBehavior ) diff --git a/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp b/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp index 9d5ffa11aa30..a1707a7998a6 100644 --- a/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp +++ b/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp @@ -91,8 +91,8 @@ QgsPointCloudRendererPropertiesWidget::QgsPointCloudRendererPropertiesWidget( Qg cboRenderers->setCurrentIndex( -1 ); // set no current renderer - mPointStyleComboBox->addItem( tr( "Square" ), static_cast( Qgis::PointCloudSymbol::Square ) ); - mPointStyleComboBox->addItem( tr( "Circle" ), static_cast( Qgis::PointCloudSymbol::Circle ) ); + mPointStyleComboBox->addItem( tr( "Square" ), QVariant::fromValue( Qgis::PointCloudSymbol::Square ) ); + mPointStyleComboBox->addItem( tr( "Circle" ), QVariant::fromValue( Qgis::PointCloudSymbol::Circle ) ); connect( cboRenderers, static_cast( &QComboBox::currentIndexChanged ), this, &QgsPointCloudRendererPropertiesWidget::rendererChanged ); @@ -104,9 +104,9 @@ QgsPointCloudRendererPropertiesWidget::QgsPointCloudRendererPropertiesWidget( Qg connect( mPointSizeSpinBox, qOverload( &QgsDoubleSpinBox::valueChanged ), this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); connect( mPointSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); - mDrawOrderComboBox->addItem( tr( "Default" ), static_cast( Qgis::PointCloudDrawOrder::Default ) ); - mDrawOrderComboBox->addItem( tr( "Bottom to Top" ), static_cast( Qgis::PointCloudDrawOrder::BottomToTop ) ); - mDrawOrderComboBox->addItem( tr( "Top to Bottom" ), static_cast( Qgis::PointCloudDrawOrder::TopToBottom ) ); + mDrawOrderComboBox->addItem( tr( "Default" ), QVariant::fromValue( Qgis::PointCloudDrawOrder::Default ) ); + mDrawOrderComboBox->addItem( tr( "Bottom to Top" ), QVariant::fromValue( Qgis::PointCloudDrawOrder::BottomToTop ) ); + mDrawOrderComboBox->addItem( tr( "Top to Bottom" ), QVariant::fromValue( Qgis::PointCloudDrawOrder::TopToBottom ) ); mMaxErrorUnitWidget->setUnits( { Qgis::RenderUnit::Millimeters, Qgis::RenderUnit::MetersInMapUnits, Qgis::RenderUnit::MapUnits, Qgis::RenderUnit::Pixels, Qgis::RenderUnit::Points, Qgis::RenderUnit::Inches } ); mMaxErrorSpinBox->setClearValue( 0.3 ); @@ -131,14 +131,14 @@ QgsPointCloudRendererPropertiesWidget::QgsPointCloudRendererPropertiesWidget( Qg mLabelOptions->setDialogTitle( tr( "Customize label text" ) ); connect( mLabels, &QCheckBox::stateChanged, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); connect( mLabelOptions, &QgsFontButton::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); - mZoomOutOptions->addItem( tr( "Show extents only" ), static_cast( Qgis::PointCloudZoomOutRenderBehavior::RenderExtents ) ); + mZoomOutOptions->addItem( tr( "Show Extents Only" ), QVariant::fromValue( Qgis::PointCloudZoomOutRenderBehavior::RenderExtents ) ); if ( const QgsVirtualPointCloudProvider *vpcProvider = dynamic_cast( mLayer->dataProvider() ) ) { if ( vpcProvider->overview() ) { - mZoomOutOptions->addItem( tr( "Show overview only" ), static_cast( Qgis::PointCloudZoomOutRenderBehavior::RenderOverview ) ); - mZoomOutOptions->addItem( tr( "Show extents over overview" ), static_cast( Qgis::PointCloudZoomOutRenderBehavior::RenderOverviewAndExtents ) ); + mZoomOutOptions->addItem( tr( "Show Overview Only" ), QVariant::fromValue( Qgis::PointCloudZoomOutRenderBehavior::RenderOverview ) ); + mZoomOutOptions->addItem( tr( "Show Extents Over Overview" ), QVariant::fromValue( Qgis::PointCloudZoomOutRenderBehavior::RenderOverviewAndExtents ) ); } } else @@ -153,7 +153,8 @@ QgsPointCloudRendererPropertiesWidget::QgsPointCloudRendererPropertiesWidget( Qg mLabels->setEnabled( false ); mLabelOptions->setEnabled( false ); break; - default: + case Qgis::PointCloudZoomOutRenderBehavior::RenderExtents: + case Qgis::PointCloudZoomOutRenderBehavior::RenderOverviewAndExtents: mLabels->setEnabled( true ); mLabelOptions->setEnabled( true ); } @@ -209,8 +210,8 @@ void QgsPointCloudRendererPropertiesWidget::syncToLayer( QgsMapLayer *layer ) mPointSizeUnitWidget->setUnit( mLayer->renderer()->pointSizeUnit() ); mPointSizeUnitWidget->setMapUnitScale( mLayer->renderer()->pointSizeMapUnitScale() ); - mPointStyleComboBox->setCurrentIndex( mPointStyleComboBox->findData( static_cast( mLayer->renderer()->pointSymbol() ) ) ); - mDrawOrderComboBox->setCurrentIndex( mDrawOrderComboBox->findData( static_cast( mLayer->renderer()->drawOrder2d() ) ) ); + mPointStyleComboBox->setCurrentIndex( mPointStyleComboBox->findData( QVariant::fromValue( mLayer->renderer()->pointSymbol() ) ) ); + mDrawOrderComboBox->setCurrentIndex( mDrawOrderComboBox->findData( QVariant::fromValue( mLayer->renderer()->drawOrder2d() ) ) ); mMaxErrorSpinBox->setValue( mLayer->renderer()->maximumScreenError() ); mMaxErrorUnitWidget->setUnit( mLayer->renderer()->maximumScreenErrorUnit() ); @@ -224,7 +225,7 @@ void QgsPointCloudRendererPropertiesWidget::syncToLayer( QgsMapLayer *layer ) { mLabels->setChecked( mLayer->renderer()->showLabels() ); mLabelOptions->setTextFormat( mLayer->renderer()->labelTextFormat() ); - mZoomOutOptions->setCurrentIndex( static_cast( mLayer->renderer()->zoomOutBehavior() ) ); + mZoomOutOptions->setCurrentIndex( mZoomOutOptions->findData( QVariant::fromValue( mLayer->renderer()->zoomOutBehavior() ) ) ); switch ( mLayer->renderer()->zoomOutBehavior() ) { case Qgis::PointCloudZoomOutRenderBehavior::RenderOverview: @@ -265,11 +266,11 @@ void QgsPointCloudRendererPropertiesWidget::apply() mLayer->renderer()->setPointSizeUnit( mPointSizeUnitWidget->unit() ); mLayer->renderer()->setPointSizeMapUnitScale( mPointSizeUnitWidget->getMapUnitScale() ); - mLayer->renderer()->setPointSymbol( static_cast( mPointStyleComboBox->currentData().toInt() ) ); + mLayer->renderer()->setPointSymbol( mPointStyleComboBox->currentData().value() ); mLayer->renderer()->setMaximumScreenError( mMaxErrorSpinBox->value() ); mLayer->renderer()->setMaximumScreenErrorUnit( mMaxErrorUnitWidget->unit() ); - mLayer->renderer()->setDrawOrder2d( static_cast( mDrawOrderComboBox->currentData().toInt() ) ); + mLayer->renderer()->setDrawOrder2d( mDrawOrderComboBox->currentData().value() ); mLayer->renderer()->setRenderAsTriangles( mTriangulateGroupBox->isChecked() ); mLayer->renderer()->setHorizontalTriangleFilter( mHorizontalTriangleCheckBox->isChecked() ); @@ -278,7 +279,7 @@ void QgsPointCloudRendererPropertiesWidget::apply() mLayer->renderer()->setShowLabels( mLabels->isChecked() ); mLayer->renderer()->setLabelTextFormat( mLabelOptions->textFormat() ); - mLayer->renderer()->setZoomOutBehavior( static_cast( mZoomOutOptions->currentData().toInt() ) ); + mLayer->renderer()->setZoomOutBehavior( mZoomOutOptions->currentData().value() ); } void QgsPointCloudRendererPropertiesWidget::rendererChanged() From dd61bf4b93d2d9523bbb4ced566180dde1ea2f6b Mon Sep 17 00:00:00 2001 From: Withalion Date: Wed, 18 Dec 2024 01:42:46 +0100 Subject: [PATCH 6/8] Add unit tests & fix some review issues --- python/PyQt6/core/auto_additions/qgis.py | 30 +- python/core/auto_additions/qgis.py | 32 +- src/core/qgis.h | 4 +- .../qgspointcloudrendererpropertieswidget.cpp | 5 +- tests/src/app/testqgsidentify.cpp | 2 +- .../test_qgspointcloudclassifiedrenderer.py | 61 ++ .../expected_classified_render_extents.png | Bin 0 -> 471523 bytes .../expected_classified_render_overview.png | Bin 0 -> 471523 bytes .../new-combined-overview.copc.laz | Bin 0 -> 3889 bytes .../virtual/sunshine-coast/new-combined.vpc | 877 ++++++++++++++++++ 10 files changed, 974 insertions(+), 37 deletions(-) create mode 100644 tests/testdata/control_images/pointcloudrenderer/expected_classified_render_extents/expected_classified_render_extents.png create mode 100644 tests/testdata/control_images/pointcloudrenderer/expected_classified_render_overview/expected_classified_render_overview.png create mode 100644 tests/testdata/point_clouds/virtual/sunshine-coast/new-combined-overview.copc.laz create mode 100644 tests/testdata/point_clouds/virtual/sunshine-coast/new-combined.vpc diff --git a/python/PyQt6/core/auto_additions/qgis.py b/python/PyQt6/core/auto_additions/qgis.py index 0036c32b0941..2cf2dee08ff2 100644 --- a/python/PyQt6/core/auto_additions/qgis.py +++ b/python/PyQt6/core/auto_additions/qgis.py @@ -11088,21 +11088,6 @@ # -- Qgis.MouseHandlesAction.baseClass = Qgis # monkey patching scoped based enum -Qgis.PointCloudZoomOutRenderBehavior.RenderExtents.__doc__ = "Render just point cloud extends when zoomed out" -Qgis.PointCloudZoomOutRenderBehavior.RenderOverview.__doc__ = "Render overview point cloud when zoomed out" -Qgis.PointCloudZoomOutRenderBehavior.RenderOverviewAndExtents.__doc__ = "Render extent polygons over overview point cloud" -Qgis.PointCloudZoomOutRenderBehavior.__doc__ = """Point cloud zoom out options - -.. versionadded:: 3.42 - -* ``RenderExtents``: Render just point cloud extends when zoomed out -* ``RenderOverview``: Render overview point cloud when zoomed out -* ``RenderOverviewAndExtents``: Render extent polygons over overview point cloud - -""" -# -- -Qgis.PointCloudZoomOutRenderBehavior.baseClass = Qgis -# monkey patching scoped based enum Qgis.MeshRangeLimit.NotSet.__doc__ = "User defined" Qgis.MeshRangeLimit.MinimumMaximum.__doc__ = "Real min-max values" Qgis.MeshRangeLimit.__doc__ = """Describes the limits used to compute mesh ranges (min/max values). @@ -11131,6 +11116,21 @@ # -- Qgis.MeshRangeExtent.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 +# monkey patching scoped based enum Qgis.PointCloudAccessType.Local.__doc__ = "Local means the source is a local file on the machine" Qgis.PointCloudAccessType.Remote.__doc__ = "Remote means it's loaded through a protocol like HTTP" Qgis.PointCloudAccessType.__doc__ = """The access type of the data, local is for local files and remote for remote files (over HTTP). diff --git a/python/core/auto_additions/qgis.py b/python/core/auto_additions/qgis.py index f01d0fe27377..38c77cf9fe50 100644 --- a/python/core/auto_additions/qgis.py +++ b/python/core/auto_additions/qgis.py @@ -10998,23 +10998,6 @@ # -- Qgis.MouseHandlesAction.baseClass = Qgis # monkey patching scoped based enum -Qgis.PointCloudZoomOutRenderBehavior.RenderExtents.__doc__ = "Render just point cloud extends when zoomed out" -Qgis.PointCloudZoomOutRenderBehavior.RenderOverview.__doc__ = "Render overview point cloud when zoomed out" -Qgis.PointCloudZoomOutRenderBehavior.RenderOverviewAndExtents.__doc__ = "Render extent polygons over overview point cloud" -Qgis.PointCloudZoomOutRenderBehavior.__doc__ = """Point cloud zoom out options - -.. versionadded:: 3.42 - -* ``RenderExtents``: Render just point cloud extends when zoomed out -* ``RenderOverview``: Render overview point cloud when zoomed out -* ``RenderOverviewAndExtents``: Render extent polygons over overview point cloud - -""" -# -- -Qgis.PointCloudZoomOutRenderBehavior.baseClass = Qgis -# -- -Qgis.MouseHandlesAction.baseClass = Qgis -# monkey patching scoped based enum Qgis.MeshRangeLimit.NotSet.__doc__ = "User defined" Qgis.MeshRangeLimit.MinimumMaximum.__doc__ = "Real min-max values" Qgis.MeshRangeLimit.__doc__ = """Describes the limits used to compute mesh ranges (min/max values). @@ -11043,6 +11026,21 @@ # -- Qgis.MeshRangeExtent.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 +# monkey patching scoped based enum Qgis.PointCloudAccessType.Local.__doc__ = "Local means the source is a local file on the machine" Qgis.PointCloudAccessType.Remote.__doc__ = "Remote means it's loaded through a protocol like HTTP" Qgis.PointCloudAccessType.__doc__ = """The access type of the data, local is for local files and remote for remote files (over HTTP). diff --git a/src/core/qgis.h b/src/core/qgis.h index 330f6a399c2e..c7c19ce9436b 100644 --- a/src/core/qgis.h +++ b/src/core/qgis.h @@ -5740,9 +5740,9 @@ class CORE_EXPORT Qgis */ enum class PointCloudZoomOutRenderBehavior : int { - RenderExtents, //!< Render just point cloud extends when zoomed out + RenderExtents, //!< Render only point cloud extents when zoomed out RenderOverview, //!< Render overview point cloud when zoomed out - RenderOverviewAndExtents //!< Render extent polygons over overview point cloud + RenderOverviewAndExtents //!< Render point cloud extents over overview point cloud }; Q_ENUM( PointCloudZoomOutRenderBehavior ) diff --git a/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp b/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp index a1707a7998a6..00604ee8e276 100644 --- a/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp +++ b/src/gui/pointcloud/qgspointcloudrendererpropertieswidget.cpp @@ -129,6 +129,7 @@ QgsPointCloudRendererPropertiesWidget::QgsPointCloudRendererPropertiesWidget( Qg if ( !mLayer->dataProvider()->subIndexes().isEmpty() ) { mLabelOptions->setDialogTitle( tr( "Customize label text" ) ); + mLabelOptions->setText( tr( "Label format" ) ); connect( mLabels, &QCheckBox::stateChanged, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); connect( mLabelOptions, &QgsFontButton::changed, this, &QgsPointCloudRendererPropertiesWidget::emitWidgetChanged ); mZoomOutOptions->addItem( tr( "Show Extents Only" ), QVariant::fromValue( Qgis::PointCloudZoomOutRenderBehavior::RenderExtents ) ); @@ -146,8 +147,8 @@ QgsPointCloudRendererPropertiesWidget::QgsPointCloudRendererPropertiesWidget( Qg mZoomOutOptions->setEnabled( false ); } - connect( mZoomOutOptions, qOverload( &QComboBox::currentIndexChanged ), this, [this]( int currentZoomOutOption ) { - switch ( static_cast( currentZoomOutOption ) ) + connect( mZoomOutOptions, qOverload( &QComboBox::currentIndexChanged ), this, [this]( int ) { + switch ( mZoomOutOptions->currentData().value() ) { case Qgis::PointCloudZoomOutRenderBehavior::RenderOverview: mLabels->setEnabled( false ); diff --git a/tests/src/app/testqgsidentify.cpp b/tests/src/app/testqgsidentify.cpp index 856d5077c15c..d2c79719d86b 100644 --- a/tests/src/app/testqgsidentify.cpp +++ b/tests/src/app/testqgsidentify.cpp @@ -1301,7 +1301,7 @@ void TestQgsIdentify::identifyPointCloud() void TestQgsIdentify::identifyVirtualPointCloud() { #ifdef HAVE_COPC - std::unique_ptr pointCloud = std::make_unique( QStringLiteral( TEST_DATA_DIR ) + "/point_clouds/virtual/sunshine-coast/combined.vpc", QStringLiteral( "pointcloud" ), QStringLiteral( "vpc" ) ); + std::unique_ptr pointCloud = std::make_unique( QStringLiteral( TEST_DATA_DIR ) + "/point_clouds/virtual/sunshine-coast/new-combined.vpc", QStringLiteral( "pointcloud" ), QStringLiteral( "vpc" ) ); QVERIFY( pointCloud->isValid() ); pointCloud->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:28356" ) ) ); QCOMPARE( pointCloud->crs3D().horizontalCrs().authid(), QStringLiteral( "EPSG:28356" ) ); diff --git a/tests/src/python/test_qgspointcloudclassifiedrenderer.py b/tests/src/python/test_qgspointcloudclassifiedrenderer.py index 3d6be8273afa..373b2111dc21 100644 --- a/tests/src/python/test_qgspointcloudclassifiedrenderer.py +++ b/tests/src/python/test_qgspointcloudclassifiedrenderer.py @@ -468,6 +468,67 @@ def testRenderTriangles(self): ) ) + @unittest.skipIf( + "vpc" not in QgsProviderRegistry.instance().providerList(), + "VPC provider not available", + ) + def testOverviewRender(self): + layer = QgsPointCloudLayer( + unitTestDataPath() + + "/point_clouds/virtual/sunshine-coast/new-combined.vpc", + "test", + "vpc", + ) + self.assertTrue(layer.isValid()) + + layer.setRenderer(layer.dataProvider().createRenderer()) + + layer.renderer().setPointSize(2) + layer.renderer().setPointSizeUnit(QgsUnitTypes.RenderUnit.RenderMillimeters) + + mapsettings = QgsMapSettings() + mapsettings.setOutputSize(QSize(400, 400)) + mapsettings.setOutputDpi(96) + mapsettings.setDestinationCrs(layer.crs()) + mapsettings.setExtent(QgsRectangle(498061, 7050991, 498069, 7050999)) + mapsettings.setLayers([layer]) + + self.assertTrue( + self.render_map_settings_check( + "classified_render_overview", "classified_render_overview", mapsettings + ) + ) + + @unittest.skipIf( + "vpc" not in QgsProviderRegistry.instance().providerList(), + "VPC provider not available", + ) + def testExtentsRender(self): + layer = QgsPointCloudLayer( + unitTestDataPath() + "/point_clouds/virtual/sunshine-coast/combined.vpc", + "test", + "vpc", + ) + self.assertTrue(layer.isValid()) + + layer.setRenderer(layer.dataProvider().createRenderer()) + + layer.renderer().setPointSize(2) + layer.renderer().setPointSizeUnit(QgsUnitTypes.RenderUnit.RenderMillimeters) + + mapsettings = QgsMapSettings() + mapsettings.setOutputSize(QSize(400, 400)) + mapsettings.setOutputDpi(96) + mapsettings.setDestinationCrs(layer.crs()) + mapsettings.setExtent(QgsRectangle(498061, 7050991, 498069, 7050999)) + mapsettings.setLayers([layer]) + + self.assertTrue( + self.render_map_settings_check( + "classified_render_extents", "classified_render_extents", mapsettings + ) + ) + if __name__ == "__main__": unittest.main() diff --git a/tests/testdata/control_images/pointcloudrenderer/expected_classified_render_extents/expected_classified_render_extents.png b/tests/testdata/control_images/pointcloudrenderer/expected_classified_render_extents/expected_classified_render_extents.png new file mode 100644 index 0000000000000000000000000000000000000000..0fc041ce75d26f068b4184117872939fbf55cc33 GIT binary patch literal 471523 zcmeI)U8rSM9RTn%GMY*1Lj)NZMIwD-W@J!g%7infqH+SI0>QwZQgDj0I~Cpte9*8A z1|6i#L^+@!rld%zMOr;X(FYCr)|U!HJwy}2bPslQ-#ur}J?osk_Ff-9LGIjh)?Vws ze*eSy@3r>g-hA1m7oL35n@$>yMknvtz3Yn6XvaMp|G)9X6EFn#`1y7BeP%Rz%V^K8^T%J@F&eK=)^_Yac=*UhL;n#VK!5;&K?RN*baaCg zAV7csf&U9ANInV#2oNBUgn)vSL>dG^fB*pk3X;zN0RjXv61e2Nziyluc=;?qMqvks zsyGFcxqtux0t8|RC`d6>^+|vL0Rq7S3Q{nc3kVP(Kp=*If)qnlp9BaHAP_8|AO(}T zfB=C^1oqx`?&oVb3y?`V!opOX!o0L5K!5;&NCFB{Bv{=NAV7dXn1F&5=A|_O0t5&| z5>SvL!RnR(0RjZV1Qet&FRcj_D)8K`hu`TeK%vRaa$1U0mT40-0RjZd6Ht)K%c&U= zAV45X0R<_`v^!Sk{AgPAW(sTf>c40O_2Zr0yzjMNI7Ilj06Y}s6aqLsvyY& zP4V#u4u8a1fPwH0OCWav#VPj;ik|=h0)+@DNQETQGzbtNkh_3_lzRrnPk;b{LIf0~ zLK0~j1PBnwT|hxfB7=WB^TcbN1xO+lf*?R32?50^i8Kg;009C76eOPk0t5&UNJ2nC zN+Jz{AV7cs0R_otfB*pk1dxC`g0y8=L?E0+k5tec`Py1)K#?oGSTTm?i-N z1db@&XD{@+lG^0RjZ-5Kxfn$g^1zAdrW^ z`R6_PRKQt)JSMeFl#0_bYOWzbfB=Ec1r(&tNp(no009Ea2q;L)sJVs!0RjX%7f_Ho zC)FVV0t5&wBcLEHqvjd{1QHOq@;l=boCQcA5m7==oT9MmlmGz&1VRNAq);*K2@oJa zAc}y36opl%1PBly5GtS`g^FoUfB*pkQ3MpED6BdqkeI-ohi-VpS%AcnBAj^wiqkwD z?-3wCfIx2o3Q}*>1|mR!0D*Y|3er3s?-3wCfIx2o3Q}*>1|mR!0D*Y|3er3s?^P*q z+s@k_bQYk>)SGld0*X^Y$q)(w0tBiS7_U#(RHdpv0wzy@0D*J_6r^-=Arb-v2vjYg zAXS}ylP5rcKso{nQaZWFERwTM|LpC~0%Vpn;S$J3Kyk_@RRSeIfI!&-3R2nmH9G-=86fE7|7IezbNZaLdofIg%L8>9WjI#?hD4a~HlWG*ok z#c2sNmk`(#@CCXl;U|IB1#I7~Zm5UK1)4=EWc#VqwxRQC`c?i>s($)A_8&ZaqaBLeX?emltH%LhG&o@Arc_4vVelLGNBG?7ic~dar037 zr@{PJ5wLH!ik@o;5FijF@Z8Tnd0Lle0fGk4so$d$zYn!+O&?X8{E%=j@3+2?1ZANu)s# z1qj%_D7Eq8@Ce%Ug0?lV2L)|>Q{rGoW>nuR+ zpTx4}Z~LySe3}gb0tB)Zuv*F>bt&A9XTT&x0t7M_P>?cDpzsOgE-=)VXYOt##;+ii zm{oI%D$xD{ZLVOW4ycRtHk?gcYQUlW*$F3HSnC&dpT>wiOt!PuA?=ZOfzq0RjXF^dX=i^`UGG0t5&U z*jB*4-L^!-HyC7N{oWT|xY}8O;gc@{0+k9VPL(F!w7U~%K4co?Mxwi^=!w9f0=Dl4 zG*T=RyZ7K1M5+4k(RZ++z@ zpdfXSuj3A!a*?wD9Y7Y=#b%*uf8lPvK5M#tw4FEpG^S<@L$qyE9Wu&0tKv?3QXz(Q?h-x0FovIwiDR=0^RQBVYA(| zzpmOg``oVIT-r`;+Ockz1MlZAV9PH59GXD_0^1dr1VR)7f#e1HULl?N&mVumS%4)z z7VR&*>D^=dwPv^NyUSAB&YRcNqv_C9+h(8BF=q8U>$PcH{}CXtn1JU=i#ZL_s{IAm z{!$zyD1*Kt(9X~F4LN#+$3F-J3)sF3CUXG+0t5)e5Kxd}sOqx{0jr@Z(rl7F3MfcD zVjGG80Rou{JbU2KZ+krp(Dz}7O!Fda0tEUHXg;H}8tp?otud^Y(#nTu2oNApt$-C$ z!l`$Mm~e77LTld5Pa~DDwDTpp3k^n`}AWtUJgghGG-ftm#rq?)sD?kfqnn_r1#GV>McOwvV2l71GfrULin$0D%DntdIskUvx-!h>J=M z)2?|pKaD`XhRK6b%Mq|bDkqm_Qm(+|S6%aNX93F1ubIsdP@HCZ30tEUOP>}jJ zHzEN71PII!@H}Y-N-8gTUXe;B7K_856k5zlD+0$7P>_x#<8=ZAdKYj=q<8Y92DD|D zR5}E+y1=KOdFBCU0aka^1A$=$6sKYRjh?Z9JNt~2C-fu*6r?26A}9g`2-GLwc~X5j zH)8_H3N#P(Sb-*+rg(vk*C%V1N%4I3On?9Z0s#V+NdZ`WH;s9lI6m;l&p8XwT}GR? z_tRcu=B~S_^+X_D0js5Sb0abW1PD|mpdeM1Zj&WIfIzwe3R1ec5g7pj1gaA7JSpLH zdq$CPa%P0)?+VR8@e+Xm0R?G$tmkk4$(x-8*xpGC0-XvtB+@BocAeS2%PwUCCP08d znF0z@nRzv<9t7OY_ke7OsswD`Rh4d&C6Km2^BJmwpLVWdL}!H*Lsg#y2oN9;EYNX5 zy5{;jcRLFZoCOyUAV7e?76IFLTR77C#r8#7`DjPe+-jP>CtqzLzY_=(=y|c zbqh4_?CX{=djj1E*uLw=F-k8fZeK*1Xd#`-S0RZsjll%0kOreSFaZJt2s8y0q^5>{ z6Clu)zz_FceWkMiU1?U>kL|mJliq$_VS6ayWC@J`ft3ZUmR2Uz0fCnV+BXnf2oMMp zutEy+(wYE)hyr#2BI0JywG~nZNfIIf0t9LhP>^cKvN=W(=}M^G&A57Fc=;Gt6fIWz+T z#RxP{_9*zpq;=tmSRpM;r6Baz7y<+cL=ZUj`6vFJ*;xRqr3jycuDW!$*p+0QewugoaYoQ9fw}~&mg>s4*+vv_ z0}&Bd*Hs88NL8fSBnc28kiLL|lzxsxNPqx=Dg-=3N;u8!XB4)C5>D1eX#S*7+WA>D zx?3K7;_sQA1z2=yd9@p_Pu5hZymBU50!0hB3oAOk+fL3N-nK*<5FkK+Kpz4MQXk63 zC{n=Pe35B2sR0EPqyg~_O@IIa0 ztEFO6X(9v&5Xf7=YANCTxkF4iIUAuh@8;8vRCEOL5U@hZBTu5tK)?+|21ycP(gF%n z(&-T#0RjZ-5m1oo$+ejdCh*WF-XHfYz+f{oFo9SCo+rhU?V#WG^9tKT9iT?+!rvH* zh^y-=1Qety(rl6h@(^&-l}DapMQQskmaKjW5FkJxNWcmyh-=u!%`LpfU~4<9Leie^WE009Cy2v{NIkR>q^ zAV8o30R<`FBtP=;_g!AfS%7@AAaVi(;s}h_Cu=HH99z8-AV7dXpn!rD2&Op!0t5)e z5m1ogxaySv0RjX91r($}FwF@NAV46FK=}n}=U4u++gX4(pB}vuAV46JK>5Wf5}a-c z5FkLHTLA^BTTi_aAV7e?k^&0Sl5j2~K!5;&ZUq#iZawuzfB*pkOA2f$NPoEQ#Wy$$ zu%x8R2oNAZpfiCj#i_Gibwq#w0RjX91r($}FwF@NAV46FfPxgqRj&jH5FijJpdbZ; zX-(IrcHnVfz$*Pq|`DZ9s&diR4Sk# zRhoFyCP08dY61#UY8ep^0Rk}v9z0{;2TD5&5Yub0z7?mz=nYJO009D91jg%=HC1T~ ziC+j1AV6R!0R?F&dE*iwK!Cs&0R?FbhhGQ~AV6R!0R?F&dE*jDS>VRsoqdM004Zmv z_}CPu;!|vb1PBnwLqI{wBTu3vK!8B;0t!;`DK z0t5&wEHGZ5tf@*1b7@F`009Cq1r(&1y80$SfB=Do1r(%(sWc=&fB=D*0@)X&bANj1 zkh1_WKO*`jK!8C10@)X*{>h9;fB*pkF$5H(7^?atK!5;&U;zawn9KzP2oN9;LqI`_ zp{h>;1PBnAD{%eeulv)yvjB?ITt06SAV7dXUjhnJU(&`QK!5;&xdIB(Tpn){AV7dX zUjhnJU(&`QK!5;&xdIB(Tpn){AV6Snfp`7#tnbe|3ov+qF#=GWVyNnq009C7f&~<$ zU@{jFAV7dX3;_ixhN?aZ5FkJxSU^DvCUXG+0t5)e5Kxd}sOpmdfq?`b{l4fPMt97ga82o1XdMLkX99RJplp)2y`N_V>CK)wS;8e@!q9xBlyQ6h*HgM=X(m5MPkV&=L!LZN>c5k#%n7imjT42Xgwfp~9{xpVL2o_){Wd#%0K zx7IHZ=H7G8UhDgQ-_H5&T4&|XCvU##-7miU6_+m-ix;1~@x-4m7RUZ>=ifiP?9!b_ zUV7rbKi>J{1s}ZeukKnbUh>`De~(2$BKgCGbHAV5Gvat{z7Kp>F7 zpIraHJ0}L7J_`^i?B1bjPQA%oK!5-N0yzXUq#UZoBtU=wf!+cdQg1RB5FkK+Kn?*7 zDTk^t2@oJaptpdA)SJu&1PBBXxch-Of2f7C071&pFHFs;pO;q?AV7dXCIJm86Rcqg z5FkLHpMZwc&&#U`5FkJxlYoYl3D&R#2oNC9Pe4QJ=jGJ|Di!$e&zyU`vjCMAH)L9x zQ^>Ljng9U;^$BQ5_0?2H1PBlaDWD;RESsPS5Fk*WfQD3GO=U!Y0D+JK8dAuz33^t6 zUw!s@OJ@OQErH1!5Lj-nwsfcl3N1wf1PDYB(2ycjNsI&t5NJR^Lu#PNQY1itKm-8| zDMFRRNPqx=1_U&u28ujWijO{W?(NP3%!F@R0?`FDr|1Dg5+Fc;z^noq(yaU@CqRHeBLa8- z{MAqNI18XTHF94_lK=q%#S1LAS6jML@nsSq0RjZt5YUj?sIx2y5Fk*zfQD3ji3CW1 z0D(3HG^94_EK33eVhG%D{bS$haTXv(QbVHDoQ9~mh5!Kq1dpH7J3?1it+E zUH|MXKw(7@PM3h@)TQG&0t5&Um`p%JnvB{+1PBly&?TTDb?JDH009C7CKJ$*CZjeH z0RjXFbO~rkT{@m?Qs9A09{9Sm08N%&(gg`B(+Nfj_wC`D>^9<^AW@KG)I{QH-L*+0wn!LarK83ssh5RRXu4UElam z9oP7)Dt2SZ*s^P^;L;^PfIz7N8qyS%x$ox>-{CC46w>A(K%f!<+jo@|QW~uaoIa5F z?Pt&IeShlspYDC_3jz@Ytd=5FNsI&t5NJTa3aNo2OL01Z{VSAU z2R(c@LLmAv?L=ZM?Yr3DHU*N|TQy}RDvEI@&GN+BUl(KHH4b)zu$ANlTD zoozJOh!=IuZDlwDw&6>QYfcTcfT&>Spci0&D_0;z(xXAFB>s=5rIPm zG^9gWJlLW@O-G;|LTT|1t{~^-_G(L4s-Tdyr%+S3sHs+#gf&&Oj9fINGU^a2idq_k zr9`OPPOuFKXh;ndd1#8>u!qXIj=(yB=RW7kM^c^zST|4n$2F(;HSC>%ZI|9;E+9Z) z0s&{jCqOm@0RjXF94(+B9c|XyCycE5<4x9er)@{t)87|HBrvsrhBUSKjPrTZUM#w{#r$1TGv1u0Ca^28++J}p)lyDfV-pxC z(6t@*%j4$;j_NW3WeaFX1=q)xSi!{++9&}hZbtD{d$ER8ZD}tg*7YC%g;&M?D*9RW zt{O$pE%u!y`Y8o8q$#xvoGa3sU5YpDuC1^F%OfNLO$j*Qkf7Wz|IE*>a~2>0q#+0p zAn=TU)skBwiGWo|5=Mg%Xj;H(sp;}do&W&?_o2XnDnI_Oc&cTs=xK3{;Yy{_oFozKyq1PB}y(2x##_>MsJ0=C<# zFLBreZQq40oxlkYAW)ZphE!KQWkY}ffv^I$?825#;3Wxcx(!y-=U;oD^S$Tvpi=zs zRrf#FS%5)wO|Wqbz$Mp9Pg&p9s;_w7nX^yTur-kXo#|oCy#hP@sT@baYW}`-`*xP}*65qoei; z0t5&I7O;I6xOh{CUeorC?aZm~9`g}6T0lcO+Q=&iY$V`UV{F9aMFiFgXh>^mJVBs6 zfiWvb|4&wX_e<)GeV&wB)OZ945Fju}An^+6s~@=bL1zI5Rbs-6YWgf_LN-$oATXgo z;^s7AYL=DJ3` z`*@Ts&UHCNiNDF4Ptt1z9B^1m;|T%;2(%*b>#H8SysWbTR!gnid-5c(fxwtmmj6F% z17I)d6wr`5c|18pzz6a})LcV=fbBc?009C72oxb;g;Yct1kp!e%(haWd2+sX-NA(2 zIWNv{-BwuF7&&7%Hi2vc%k9;cu9S^8?Z9L9!Y+Q7OBb2LL z>aA^+nRP7_`ZnRduP+TWdih-KX-Aa}qlN0{I1O+2uDj1A!I={`wm?ebiZi7Av19XRD<|kcJ`9N1(RD z31d!&_Hpytx&<_(AoaB+7Nk(ZBtT%WfQB@f&V_Rb)UvX02xX4D$DE}L_&llf3W<*Z z0RoK(SRqwdXsd{5MLl)ru^&4N5UpzB%`0HFl-Jkj1PBlyu%Up4v>}w25gxhhLq3N$Tm!fB=C30?X~ymaa4aF2E&MeE*WyR(2L3fVvO~5J)Cq4=)+z zyaV|FW?uhN_UPtSFgt;90vggdKUXId@TQ&+bHbtgFf<`{ba%M&!m(su2d^bXUogK z=ORX^IYq2mf|$LbBtSF-0Rl+{Y~Lm2G#CK_1PBZjutFLt=Q;xW1WMVG+ZU2A34{~S zkiwO$-hdB%Q$OUST@(RF+M`rToTUi#Ye@fj+ed!uEI=u>D>jZ?Z^WrSkS`WaU<3&4 z3HUr|kHQxO2oNAJr$E2e(wvc+n*f1g1gu<(DMeL*Xh>C+bMs`pp=@sDl>`V(BVfyJ z8fUW*AV6R~ft%j+;m-v-3!pj8ce|LG009C7_6gX&+lS#x0x1O!J>H&jf(ggUb)s^@ z6igLBKtl>pq@zMC;mx9^H{YYYJx_o@9svz0kE>CG3zX30gA)p$KyLw`A@wG60RaLv z3!J&`9iIwz7NE{@EVox%I#ivtl@$R31i}euNa0E*U;+dP)G44L)mc|r5ge0V||U zl)Q!j0RjZF3s@m#CpJOz0uSH&{`U?%3t$D({N2+mfYnm7rI$DX0tCtu(2&ZihiC{8 zAkeIU?Ym}6UvA>Lj$hAlAY_g?FRpAZ&x_~rJ%OF7u~R=e_hg`Wg?d5YTgJw zeEffIbQYkddsZ$42s9v2e{*V}h*Bg#fItlb8d42almh_*1S$~FkSZvm6bKL?P=kPm zR6`ZzK!5;&3Iq-`q#xe-iz}Q3sGzD+AV7dXaDfBODR?fzCqRGzfxrS9QsCkVod5v> zH3?`)HC0nC1PBlaETAC;E}qZ{5FoHC@V2k~_7k<81<;(_+XM&@AW(#WhEzlu1VMlR z0RkG5dw>7|0tAW>(2$BKgCGbHAV5Gvat{z7(2~H{U-Pl+YC8*1W&Jd#D$6P<0t5&I z6j*MrwsfU{g%dIX0t9Ll(2#1Zs+NzRdoFb0nKRyo=XW3AV46UfQFRL(ntgd5Fju@KtmdV=TZU$2oOjopdqERG!g*< z1PF`}(2z#pxs<@Jz%MS_zROtv_X2^m0-94=PoohaK!CtN0S##&oXZFhAV46kfQFRT z(`W<;5Fjv6Ktmb`=Q08W2oOjspdqF8G+MX7$5x;Iva&J|1PBnANXG2oNC9DWD;B z@_3Q}0RjZ363~#Qk~R+k0t5(j3TQ~3Jf0*#fWYhmSO5Dp4|kmfm_5K80ccJ+RE}dl!VbB1PBlyFjhcA8Y}2}0t5&UNFs1-v3T;yzrEtj X<=0tJ5L-ckf^IQJRKz5mnY<=Yg#dyUknj*tS=lie$Y_{gG66yO5U6#9 zF5oV$3ae63t5vZqsJjcOymqNoDvA~#)fH>OM}5@icGdJw9yCDY>wf)uzc2UPd+t5w z{P*1do=mtbCIo_4_m7T#$K%cu^FsBI|v#DbQ`^( zB|yZ2A8TNXX}}Bm-JM?X6#t=eolDKX1Cu>vtxvog8*eU?-HrOY=Z3JDfQ8qyTq1zJ zq~(b>2IQQ?lE5ag{`-;^5wov1%cUli6>HpAvn4vf5>7wXGy;f>SeO}uhiOAGnY6!U zuh66^to^f~N+>8&9>gZ8WDPqmJlcBEJWecW(FcJO`y`g!W=`r_6M8)>JSG5w%C~LX zHpVRX_}7|G$~N1nj(U%~nc^h-uu$Y*mFgrjtA7Kb#&ua_8k?XL8YQ8GpvE{pq{g$- z2yHSu9oLdLMGuS0&|{Q6(?gKKMze#)L!N*{j?fq*mBImKljK^>Dndb%8VU*+XEYtL zOEzcZvri0$?mC0Pz1Cm|8|@rm=iL5%-c(C|OfDFn#sfke0y4quH6O?^=CM7H^UQ={ zR~xzmM2lWblDQ#wCVzAOSm%xLr8y6uetcQ)5c0SB6Yf*%HqO6ss=RuKXwx|XT3l%cG(-gBd3FL0)!ZHlSwuKnMV<$tL^ zzLR>pY6YkHiyw;G0`GA<+rPCJyZtG_&3}u}p@_~)MO#O)cf9mD7<01o@P$i$`$y}~ ziI4SOJhZO-+J%orFV6GAH1{-4JcR$IM>3-A;x50T$@;;8x4{*pcftRzI{$g?8RZ*M z9kTIxow>5pjfq&p$%0+q^&NWhqV*vE*(nM++uU~gbfEXsjoVkPe(S{-{5!SLHBoO) zn=GEb)x{9qyZy!t&PDdxr&~ANJ^t`kXnuEVU#p{I?O{7rT2H~kDeJ2HSdafZF|a)8 z;TpHZNmXTa;c<`tarI{0`K9uG!b(Mgq+;Ss{4U%AIOctpr6p1$`{*ip@$ zsNDtqf4tU>oh>xDzXEXW>{vfHI~J73%uLcUGp-Ms7`Kedht}uiv+^vBnHUx8bAjLO zwRj~l&1K7T+PVGZ(fM=6cft4j{R^D7Yu&jsWdbxV;X#wj@zS2Iu8-{4L9M|x?zhKY zRyRuAzMIuP<;U}H$bAx$esnNIx7^QM?Du(65;ZyO{nkB!i}yWThPU+`nOmRuz{@-F z@%ol#_|^TBYs#7`o+qt#dKQ@PTt7STKU)EUW4UKQ&pa@0WI9rOq_1-Hr*0n9J2CGE zec<6&qU@Ua&*FFEI&@Cz1&PkL;#+&F0Tw^v=+yIYf6*XKzgc*G8BO;?PuK6tXg*Iy$LNLvEv$>4&0vZ=6A6A zUMu~X>%7eqidJWN&K$S*-S#gJ`_!#C_qE|u$0&zuXAK>Wh=G&vRqb^3f%PDHOk*mB zpDMD@I2l^~`$w^jdO&@7EPEkIXmPDVm1)+EBu|3HyNIF*N=MR}!;frj&qT5Sln8`;iB&qS zlZi;Bz$}c&lru~i?vwM&)3{ilx{}aFCPx#rUP~F7G?+mg1Y8M74&VTDhXZUvEkMC1 zCb();YQZX$SY?tSN@O~rRpV*D3a0U(F&e#AK`c_*@FanS0H;XG<$w_bmASD2tc=bA zm)Xe|mcx1O_hvL4;DkX+&a8b{>lHVHkyB7=tkhBEpz! zW&#D1TGK~dh#F5B9?VFLL2nhY@828$(pbO05@ zOH08uE~0!G@D2P&P)b~@~}i`}umU!r0jKx^T-z X4u`>@keDKk5KhP!faBT@k(2Wi+P1nx literal 0 HcmV?d00001 diff --git a/tests/testdata/point_clouds/virtual/sunshine-coast/new-combined.vpc b/tests/testdata/point_clouds/virtual/sunshine-coast/new-combined.vpc new file mode 100644 index 000000000000..f1aaded4407e --- /dev/null +++ b/tests/testdata/point_clouds/virtual/sunshine-coast/new-combined.vpc @@ -0,0 +1,877 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "stac_version": "1.0.0", + "stac_extensions": [ + "https://stac-extensions.github.io/pointcloud/v1.0.0/schema.json", + "https://stac-extensions.github.io/projection/v1.1.0/schema.json" + ], + "id": "0-0.copc", + "geometry": { + "coordinates": [ + [ + [ + 498062.0, + 7050992.85, + 74.68 + ], + [ + 498062.0, + 7050995.82, + 74.68 + ], + [ + 498064.98, + 7050995.82, + 75.16 + ], + [ + 498064.98, + 7050992.85, + 75.16 + ], + [ + 498062.0, + 7050992.85, + 74.68 + ] + ] + ], + "type": "Polygon" + }, + "bbox": [ + 498062.0, + 7050992.85, + 74.68, + 498064.98, + 7050995.82, + 75.16 + ], + "properties": { + "datetime": "2024-10-18T00:00:00Z", + "pc:count": 91, + "pc:encoding": "?", + "pc:schemas": [ + { + "name": "X", + "size": 8, + "type": "floating" + }, + { + "name": "Y", + "size": 8, + "type": "floating" + }, + { + "name": "Z", + "size": 8, + "type": "floating" + }, + { + "name": "Intensity", + "size": 2, + "type": "unsigned" + }, + { + "name": "ReturnNumber", + "size": 1, + "type": "unsigned" + }, + { + "name": "NumberOfReturns", + "size": 1, + "type": "unsigned" + }, + { + "name": "ScanDirectionFlag", + "size": 1, + "type": "unsigned" + }, + { + "name": "EdgeOfFlightLine", + "size": 1, + "type": "unsigned" + }, + { + "name": "Classification", + "size": 1, + "type": "unsigned" + }, + { + "name": "Synthetic", + "size": 1, + "type": "unsigned" + }, + { + "name": "KeyPoint", + "size": 1, + "type": "unsigned" + }, + { + "name": "Withheld", + "size": 1, + "type": "unsigned" + }, + { + "name": "Overlap", + "size": 1, + "type": "unsigned" + }, + { + "name": "ScanAngleRank", + "size": 4, + "type": "floating" + }, + { + "name": "UserData", + "size": 1, + "type": "unsigned" + }, + { + "name": "PointSourceId", + "size": 2, + "type": "unsigned" + }, + { + "name": "GpsTime", + "size": 8, + "type": "floating" + }, + { + "name": "ScanChannel", + "size": 1, + "type": "unsigned" + }, + { + "name": "Red", + "size": 2, + "type": "unsigned" + }, + { + "name": "Green", + "size": 2, + "type": "unsigned" + }, + { + "name": "Blue", + "size": 2, + "type": "unsigned" + } + ], + "pc:type": "lidar", + "proj:bbox": [ + 498062.0, + 7050992.85, + 74.68, + 498064.98, + 7050995.82, + 75.16 + ], + "proj:geometry": { + "coordinates": [ + [ + [ + 498062.0, + 7050992.85, + 74.68 + ], + [ + 498062.0, + 7050995.82, + 74.68 + ], + [ + 498064.98, + 7050995.82, + 75.16 + ], + [ + 498064.98, + 7050992.85, + 75.16 + ], + [ + 498062.0, + 7050992.85, + 74.68 + ] + ] + ], + "type": "Polygon" + }, + "proj:wkt2": "" + }, + "links": [], + "assets": { + "data": { + "href": "./0-0.copc.laz", + "roles": [ + "data" + ] + }, + "overview": { + "href": "./new-combined-overview.copc.laz", + "roles": [ + "overview" + ] + } + } + }, + { + "type": "Feature", + "stac_version": "1.0.0", + "stac_extensions": [ + "https://stac-extensions.github.io/pointcloud/v1.0.0/schema.json", + "https://stac-extensions.github.io/projection/v1.1.0/schema.json" + ], + "id": "0-1.copc", + "geometry": { + "coordinates": [ + [ + [ + 498062.04, + 7050995.84, + 74.64 + ], + [ + 498062.04, + 7050997.03, + 74.64 + ], + [ + 498064.91, + 7050997.03, + 79.0 + ], + [ + 498064.91, + 7050995.84, + 79.0 + ], + [ + 498062.04, + 7050995.84, + 74.64 + ] + ] + ], + "type": "Polygon" + }, + "bbox": [ + 498062.04, + 7050995.84, + 74.64, + 498064.91, + 7050997.03, + 79.0 + ], + "properties": { + "datetime": "2024-10-18T00:00:00Z", + "pc:count": 47, + "pc:encoding": "?", + "pc:schemas": [ + { + "name": "X", + "size": 8, + "type": "floating" + }, + { + "name": "Y", + "size": 8, + "type": "floating" + }, + { + "name": "Z", + "size": 8, + "type": "floating" + }, + { + "name": "Intensity", + "size": 2, + "type": "unsigned" + }, + { + "name": "ReturnNumber", + "size": 1, + "type": "unsigned" + }, + { + "name": "NumberOfReturns", + "size": 1, + "type": "unsigned" + }, + { + "name": "ScanDirectionFlag", + "size": 1, + "type": "unsigned" + }, + { + "name": "EdgeOfFlightLine", + "size": 1, + "type": "unsigned" + }, + { + "name": "Classification", + "size": 1, + "type": "unsigned" + }, + { + "name": "Synthetic", + "size": 1, + "type": "unsigned" + }, + { + "name": "KeyPoint", + "size": 1, + "type": "unsigned" + }, + { + "name": "Withheld", + "size": 1, + "type": "unsigned" + }, + { + "name": "Overlap", + "size": 1, + "type": "unsigned" + }, + { + "name": "ScanAngleRank", + "size": 4, + "type": "floating" + }, + { + "name": "UserData", + "size": 1, + "type": "unsigned" + }, + { + "name": "PointSourceId", + "size": 2, + "type": "unsigned" + }, + { + "name": "GpsTime", + "size": 8, + "type": "floating" + }, + { + "name": "ScanChannel", + "size": 1, + "type": "unsigned" + }, + { + "name": "Red", + "size": 2, + "type": "unsigned" + }, + { + "name": "Green", + "size": 2, + "type": "unsigned" + }, + { + "name": "Blue", + "size": 2, + "type": "unsigned" + } + ], + "pc:type": "lidar", + "proj:bbox": [ + 498062.04, + 7050995.84, + 74.64, + 498064.91, + 7050997.03, + 79.0 + ], + "proj:geometry": { + "coordinates": [ + [ + [ + 498062.04, + 7050995.84, + 74.64 + ], + [ + 498062.04, + 7050997.03, + 74.64 + ], + [ + 498064.91, + 7050997.03, + 79.0 + ], + [ + 498064.91, + 7050995.84, + 79.0 + ], + [ + 498062.04, + 7050995.84, + 74.64 + ] + ] + ], + "type": "Polygon" + }, + "proj:wkt2": "" + }, + "links": [], + "assets": { + "data": { + "href": "./0-1.copc.laz", + "roles": [ + "data" + ] + }, + "overview": { + "href": "./new-combined-overview.copc.laz", + "roles": [ + "overview" + ] + } + } + }, + { + "type": "Feature", + "stac_version": "1.0.0", + "stac_extensions": [ + "https://stac-extensions.github.io/pointcloud/v1.0.0/schema.json", + "https://stac-extensions.github.io/projection/v1.1.0/schema.json" + ], + "id": "1-0.copc", + "geometry": { + "coordinates": [ + [ + [ + 498065.0, + 7050992.84, + 74.46 + ], + [ + 498065.0, + 7050995.83, + 74.46 + ], + [ + 498067.39, + 7050995.83, + 74.91 + ], + [ + 498067.39, + 7050992.84, + 74.91 + ], + [ + 498065.0, + 7050992.84, + 74.46 + ] + ] + ], + "type": "Polygon" + }, + "bbox": [ + 498065.0, + 7050992.84, + 74.46, + 498067.39, + 7050995.83, + 74.91 + ], + "properties": { + "datetime": "2024-10-18T00:00:00Z", + "pc:count": 77, + "pc:encoding": "?", + "pc:schemas": [ + { + "name": "X", + "size": 8, + "type": "floating" + }, + { + "name": "Y", + "size": 8, + "type": "floating" + }, + { + "name": "Z", + "size": 8, + "type": "floating" + }, + { + "name": "Intensity", + "size": 2, + "type": "unsigned" + }, + { + "name": "ReturnNumber", + "size": 1, + "type": "unsigned" + }, + { + "name": "NumberOfReturns", + "size": 1, + "type": "unsigned" + }, + { + "name": "ScanDirectionFlag", + "size": 1, + "type": "unsigned" + }, + { + "name": "EdgeOfFlightLine", + "size": 1, + "type": "unsigned" + }, + { + "name": "Classification", + "size": 1, + "type": "unsigned" + }, + { + "name": "Synthetic", + "size": 1, + "type": "unsigned" + }, + { + "name": "KeyPoint", + "size": 1, + "type": "unsigned" + }, + { + "name": "Withheld", + "size": 1, + "type": "unsigned" + }, + { + "name": "Overlap", + "size": 1, + "type": "unsigned" + }, + { + "name": "ScanAngleRank", + "size": 4, + "type": "floating" + }, + { + "name": "UserData", + "size": 1, + "type": "unsigned" + }, + { + "name": "PointSourceId", + "size": 2, + "type": "unsigned" + }, + { + "name": "GpsTime", + "size": 8, + "type": "floating" + }, + { + "name": "ScanChannel", + "size": 1, + "type": "unsigned" + }, + { + "name": "Red", + "size": 2, + "type": "unsigned" + }, + { + "name": "Green", + "size": 2, + "type": "unsigned" + }, + { + "name": "Blue", + "size": 2, + "type": "unsigned" + } + ], + "pc:type": "lidar", + "proj:bbox": [ + 498065.0, + 7050992.84, + 74.46, + 498067.39, + 7050995.83, + 74.91 + ], + "proj:geometry": { + "coordinates": [ + [ + [ + 498065.0, + 7050992.84, + 74.46 + ], + [ + 498065.0, + 7050995.83, + 74.46 + ], + [ + 498067.39, + 7050995.83, + 74.91 + ], + [ + 498067.39, + 7050992.84, + 74.91 + ], + [ + 498065.0, + 7050992.84, + 74.46 + ] + ] + ], + "type": "Polygon" + }, + "proj:wkt2": "" + }, + "links": [], + "assets": { + "data": { + "href": "./1-0.copc.laz", + "roles": [ + "data" + ] + }, + "overview": { + "href": "./new-combined-overview.copc.laz", + "roles": [ + "overview" + ] + } + } + }, + { + "type": "Feature", + "stac_version": "1.0.0", + "stac_extensions": [ + "https://stac-extensions.github.io/pointcloud/v1.0.0/schema.json", + "https://stac-extensions.github.io/projection/v1.1.0/schema.json" + ], + "id": "1-1.copc", + "geometry": { + "coordinates": [ + [ + [ + 498065.01, + 7050995.9, + 74.34 + ], + [ + 498065.01, + 7050997.04, + 74.34 + ], + [ + 498067.32, + 7050997.04, + 80.02 + ], + [ + 498067.32, + 7050995.9, + 80.02 + ], + [ + 498065.01, + 7050995.9, + 74.34 + ] + ] + ], + "type": "Polygon" + }, + "bbox": [ + 498065.01, + 7050995.9, + 74.34, + 498067.32, + 7050997.04, + 80.02 + ], + "properties": { + "datetime": "2024-10-18T00:00:00Z", + "pc:count": 38, + "pc:encoding": "?", + "pc:schemas": [ + { + "name": "X", + "size": 8, + "type": "floating" + }, + { + "name": "Y", + "size": 8, + "type": "floating" + }, + { + "name": "Z", + "size": 8, + "type": "floating" + }, + { + "name": "Intensity", + "size": 2, + "type": "unsigned" + }, + { + "name": "ReturnNumber", + "size": 1, + "type": "unsigned" + }, + { + "name": "NumberOfReturns", + "size": 1, + "type": "unsigned" + }, + { + "name": "ScanDirectionFlag", + "size": 1, + "type": "unsigned" + }, + { + "name": "EdgeOfFlightLine", + "size": 1, + "type": "unsigned" + }, + { + "name": "Classification", + "size": 1, + "type": "unsigned" + }, + { + "name": "Synthetic", + "size": 1, + "type": "unsigned" + }, + { + "name": "KeyPoint", + "size": 1, + "type": "unsigned" + }, + { + "name": "Withheld", + "size": 1, + "type": "unsigned" + }, + { + "name": "Overlap", + "size": 1, + "type": "unsigned" + }, + { + "name": "ScanAngleRank", + "size": 4, + "type": "floating" + }, + { + "name": "UserData", + "size": 1, + "type": "unsigned" + }, + { + "name": "PointSourceId", + "size": 2, + "type": "unsigned" + }, + { + "name": "GpsTime", + "size": 8, + "type": "floating" + }, + { + "name": "ScanChannel", + "size": 1, + "type": "unsigned" + }, + { + "name": "Red", + "size": 2, + "type": "unsigned" + }, + { + "name": "Green", + "size": 2, + "type": "unsigned" + }, + { + "name": "Blue", + "size": 2, + "type": "unsigned" + } + ], + "pc:type": "lidar", + "proj:bbox": [ + 498065.01, + 7050995.9, + 74.34, + 498067.32, + 7050997.04, + 80.02 + ], + "proj:geometry": { + "coordinates": [ + [ + [ + 498065.01, + 7050995.9, + 74.34 + ], + [ + 498065.01, + 7050997.04, + 74.34 + ], + [ + 498067.32, + 7050997.04, + 80.02 + ], + [ + 498067.32, + 7050995.9, + 80.02 + ], + [ + 498065.01, + 7050995.9, + 74.34 + ] + ] + ], + "type": "Polygon" + }, + "proj:wkt2": "" + }, + "links": [], + "assets": { + "data": { + "href": "./1-1.copc.laz", + "roles": [ + "data" + ] + }, + "overview": { + "href": "./new-combined-overview.copc.laz", + "roles": [ + "overview" + ] + } + } + } + ] +} From f8222ae3d1caf122c079fd4fd157ef1f7feaed8b Mon Sep 17 00:00:00 2001 From: Withalion Date: Wed, 18 Dec 2024 12:05:36 +0100 Subject: [PATCH 7/8] Fix to more descriptive test data naming --- tests/src/app/testqgsidentify.cpp | 2 +- .../python/test_qgspointcloudclassifiedrenderer.py | 2 +- ...laz => combined-with-overview-overview.copc.laz} | Bin ...{new-combined.vpc => combined-with-overview.vpc} | 8 ++++---- 4 files changed, 6 insertions(+), 6 deletions(-) rename tests/testdata/point_clouds/virtual/sunshine-coast/{new-combined-overview.copc.laz => combined-with-overview-overview.copc.laz} (100%) rename tests/testdata/point_clouds/virtual/sunshine-coast/{new-combined.vpc => combined-with-overview.vpc} (98%) diff --git a/tests/src/app/testqgsidentify.cpp b/tests/src/app/testqgsidentify.cpp index d2c79719d86b..3133da33b080 100644 --- a/tests/src/app/testqgsidentify.cpp +++ b/tests/src/app/testqgsidentify.cpp @@ -1301,7 +1301,7 @@ void TestQgsIdentify::identifyPointCloud() void TestQgsIdentify::identifyVirtualPointCloud() { #ifdef HAVE_COPC - std::unique_ptr pointCloud = std::make_unique( QStringLiteral( TEST_DATA_DIR ) + "/point_clouds/virtual/sunshine-coast/new-combined.vpc", QStringLiteral( "pointcloud" ), QStringLiteral( "vpc" ) ); + std::unique_ptr pointCloud = std::make_unique( QStringLiteral( TEST_DATA_DIR ) + "/point_clouds/virtual/sunshine-coast/combined-with-overview.vpc", QStringLiteral( "pointcloud" ), QStringLiteral( "vpc" ) ); QVERIFY( pointCloud->isValid() ); pointCloud->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:28356" ) ) ); QCOMPARE( pointCloud->crs3D().horizontalCrs().authid(), QStringLiteral( "EPSG:28356" ) ); diff --git a/tests/src/python/test_qgspointcloudclassifiedrenderer.py b/tests/src/python/test_qgspointcloudclassifiedrenderer.py index 373b2111dc21..d1f882004b6f 100644 --- a/tests/src/python/test_qgspointcloudclassifiedrenderer.py +++ b/tests/src/python/test_qgspointcloudclassifiedrenderer.py @@ -475,7 +475,7 @@ def testRenderTriangles(self): def testOverviewRender(self): layer = QgsPointCloudLayer( unitTestDataPath() - + "/point_clouds/virtual/sunshine-coast/new-combined.vpc", + + "/point_clouds/virtual/sunshine-coast/combined-with-overview.vpc", "test", "vpc", ) diff --git a/tests/testdata/point_clouds/virtual/sunshine-coast/new-combined-overview.copc.laz b/tests/testdata/point_clouds/virtual/sunshine-coast/combined-with-overview-overview.copc.laz similarity index 100% rename from tests/testdata/point_clouds/virtual/sunshine-coast/new-combined-overview.copc.laz rename to tests/testdata/point_clouds/virtual/sunshine-coast/combined-with-overview-overview.copc.laz diff --git a/tests/testdata/point_clouds/virtual/sunshine-coast/new-combined.vpc b/tests/testdata/point_clouds/virtual/sunshine-coast/combined-with-overview.vpc similarity index 98% rename from tests/testdata/point_clouds/virtual/sunshine-coast/new-combined.vpc rename to tests/testdata/point_clouds/virtual/sunshine-coast/combined-with-overview.vpc index f1aaded4407e..054337c51212 100644 --- a/tests/testdata/point_clouds/virtual/sunshine-coast/new-combined.vpc +++ b/tests/testdata/point_clouds/virtual/sunshine-coast/combined-with-overview.vpc @@ -212,7 +212,7 @@ ] }, "overview": { - "href": "./new-combined-overview.copc.laz", + "href": "./combined-with-overview-overview.copc.laz", "roles": [ "overview" ] @@ -430,7 +430,7 @@ ] }, "overview": { - "href": "./new-combined-overview.copc.laz", + "href": "./combined-with-overview-overview.copc.laz", "roles": [ "overview" ] @@ -648,7 +648,7 @@ ] }, "overview": { - "href": "./new-combined-overview.copc.laz", + "href": "./combined-with-overview-overview.copc.laz", "roles": [ "overview" ] @@ -866,7 +866,7 @@ ] }, "overview": { - "href": "./new-combined-overview.copc.laz", + "href": "./combined-with-overview-overview.copc.laz", "roles": [ "overview" ] From 08380e269700c4582fc1f21c7f5c9d83c489f78e Mon Sep 17 00:00:00 2001 From: Withalion Date: Tue, 7 Jan 2025 14:38:42 +0100 Subject: [PATCH 8/8] Fix issues introduced by PointCloudIndex refactor --- python/PyQt6/core/auto_additions/qgis.py | 30 +++++++++---------- python/PyQt6/core/auto_generated/qgis.sip.in | 12 ++++---- python/core/auto_additions/qgis.py | 30 +++++++++---------- python/core/auto_generated/qgis.sip.in | 12 ++++---- .../pointcloud/qgspointcloudlayerrenderer.cpp | 7 +++-- .../vpc/qgsvirtualpointcloudprovider.cpp | 8 ++--- .../vpc/qgsvirtualpointcloudprovider.h | 4 +-- 7 files changed, 52 insertions(+), 51 deletions(-) diff --git a/python/PyQt6/core/auto_additions/qgis.py b/python/PyQt6/core/auto_additions/qgis.py index 2cf2dee08ff2..6402003184f9 100644 --- a/python/PyQt6/core/auto_additions/qgis.py +++ b/python/PyQt6/core/auto_additions/qgis.py @@ -11116,21 +11116,6 @@ # -- Qgis.MeshRangeExtent.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 -# monkey patching scoped based enum Qgis.PointCloudAccessType.Local.__doc__ = "Local means the source is a local file on the machine" Qgis.PointCloudAccessType.Remote.__doc__ = "Remote means it's loaded through a protocol like HTTP" Qgis.PointCloudAccessType.__doc__ = """The access type of the data, local is for local files and remote for remote files (over HTTP). @@ -11145,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) diff --git a/python/PyQt6/core/auto_generated/qgis.sip.in b/python/PyQt6/core/auto_generated/qgis.sip.in index ff9c22715712..4d30981e6609 100644 --- a/python/PyQt6/core/auto_generated/qgis.sip.in +++ b/python/PyQt6/core/auto_generated/qgis.sip.in @@ -3249,6 +3249,12 @@ The development version UpdatedCanvas, }; + enum class PointCloudAccessType /BaseType=IntEnum/ + { + Local, + Remote + }; + enum class PointCloudZoomOutRenderBehavior /BaseType=IntEnum/ { RenderExtents, @@ -3256,12 +3262,6 @@ The development version RenderOverviewAndExtents }; - enum class PointCloudAccessType /BaseType=IntEnum/ - { - Local, - Remote - }; - static const double DEFAULT_SEARCH_RADIUS_MM; static const float DEFAULT_MAPTOPIXEL_THRESHOLD; diff --git a/python/core/auto_additions/qgis.py b/python/core/auto_additions/qgis.py index 38c77cf9fe50..0f9f1168ba09 100644 --- a/python/core/auto_additions/qgis.py +++ b/python/core/auto_additions/qgis.py @@ -11026,21 +11026,6 @@ # -- Qgis.MeshRangeExtent.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 -# monkey patching scoped based enum Qgis.PointCloudAccessType.Local.__doc__ = "Local means the source is a local file on the machine" Qgis.PointCloudAccessType.Remote.__doc__ = "Remote means it's loaded through a protocol like HTTP" Qgis.PointCloudAccessType.__doc__ = """The access type of the data, local is for local files and remote for remote files (over HTTP). @@ -11055,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 diff --git a/python/core/auto_generated/qgis.sip.in b/python/core/auto_generated/qgis.sip.in index 8a16963ede80..a2b885ed6ddb 100644 --- a/python/core/auto_generated/qgis.sip.in +++ b/python/core/auto_generated/qgis.sip.in @@ -3249,6 +3249,12 @@ The development version UpdatedCanvas, }; + enum class PointCloudAccessType + { + Local, + Remote + }; + enum class PointCloudZoomOutRenderBehavior { RenderExtents, @@ -3256,12 +3262,6 @@ The development version RenderOverviewAndExtents }; - enum class PointCloudAccessType - { - Local, - Remote - }; - static const double DEFAULT_SEARCH_RADIUS_MM; static const float DEFAULT_MAPTOPIXEL_THRESHOLD; diff --git a/src/core/pointcloud/qgspointcloudlayerrenderer.cpp b/src/core/pointcloud/qgspointcloudlayerrenderer.cpp index bdfc7976e808..7194fe818487 100644 --- a/src/core/pointcloud/qgspointcloudlayerrenderer.cpp +++ b/src/core/pointcloud/qgspointcloudlayerrenderer.cpp @@ -209,11 +209,12 @@ bool QgsPointCloudLayerRenderer::render() } 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( vpcProvider->overview() ); + renderIndex( overviewIndex ); } else { @@ -222,7 +223,7 @@ bool QgsPointCloudLayerRenderer::render() if ( vpcProvider->overview() && zoomedOut && mRenderer->zoomOutBehavior() == Qgis::PointCloudZoomOutRenderBehavior::RenderOverviewAndExtents ) { - renderIndex( vpcProvider->overview() ); + renderIndex( overviewIndex ); } mSubIndexExtentRenderer->startRender( context ); for ( const QgsPointCloudSubIndex &si : visibleIndexes ) @@ -233,7 +234,7 @@ bool QgsPointCloudLayerRenderer::render() 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 ) ) + zoomedOut ) ) { mSubIndexExtentRenderer->renderExtent( si.polygonBounds(), context ); if ( mSubIndexExtentRenderer->showLabels() ) diff --git a/src/core/providers/vpc/qgsvirtualpointcloudprovider.cpp b/src/core/providers/vpc/qgsvirtualpointcloudprovider.cpp index 9342c3c37ef5..5d9d2cc19c9f 100644 --- a/src/core/providers/vpc/qgsvirtualpointcloudprovider.cpp +++ b/src/core/providers/vpc/qgsvirtualpointcloudprovider.cpp @@ -213,8 +213,8 @@ void QgsVirtualPointCloudProvider::parseFile() // look for vpc overview reference if ( !mOverview && f["assets"].contains( "overview" ) && f["assets"]["overview"].contains( "href" ) ) { - mOverview = std::make_unique(); - mOverview->load( fInfo.absoluteDir().absoluteFilePath( QString::fromStdString( f["assets"]["overview"]["href"] ) ) ); + mOverview = QgsPointCloudIndex( new QgsCopcPointCloudIndex() ); + mOverview.load( fInfo.absoluteDir().absoluteFilePath( QString::fromStdString( f["assets"]["overview"]["href"] ) ) ); } // if it doesn't exist look for overview file in the directory else if ( !mOverview ) @@ -225,8 +225,8 @@ void QgsVirtualPointCloudProvider::parseFile() vpcDir.setFilter( QDir::Files ); if ( !vpcDir.entryList().empty() ) { - mOverview = std::make_unique(); - mOverview->load( vpcDir.absoluteFilePath( vpcDir.entryList().first() ) ); + mOverview = QgsPointCloudIndex( new QgsCopcPointCloudIndex() );; + mOverview.load( vpcDir.absoluteFilePath( vpcDir.entryList().first() ) ); } } diff --git a/src/core/providers/vpc/qgsvirtualpointcloudprovider.h b/src/core/providers/vpc/qgsvirtualpointcloudprovider.h index 27bf5736c751..c9a49bb674f0 100644 --- a/src/core/providers/vpc/qgsvirtualpointcloudprovider.h +++ b/src/core/providers/vpc/qgsvirtualpointcloudprovider.h @@ -65,7 +65,7 @@ class CORE_EXPORT QgsVirtualPointCloudProvider: public QgsPointCloudDataProvider * Returns pointer to the overview index. May be NULLPTR if it doesn't exist. * \since QGIS 3.42 */ - QgsPointCloudIndex *overview() const { return mOverview.get(); } + QgsPointCloudIndex overview() const { return mOverview; } /** * Returns the calculated average width of point clouds. @@ -90,7 +90,7 @@ class CORE_EXPORT QgsVirtualPointCloudProvider: public QgsPointCloudDataProvider QVector mSubLayers; std::unique_ptr mPolygonBounds; QgsPointCloudAttributeCollection mAttributes; - std::unique_ptr mOverview; + QgsPointCloudIndex mOverview = QgsPointCloudIndex( nullptr ); QStringList mUriList; QgsRectangle mExtent;