Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions python/3d/auto_generated/qgspointcloudlayer3drenderer.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,20 @@ Sets the renderer behavior when zoomed out
Returns the renderer behavior when zoomed out

.. versionadded:: 3.42
%End

void setZoomOutMultiplier( double multiplier );
%Docstring
Sets the zoom out multiplier for zoomed out rendering of the overview

.. versionadded:: 4.0
%End

double zoomOutMultiplier() const;
%Docstring
Returns the zoom out multiplier for zoomed out rendering of the overview

.. versionadded:: 4.0
%End

private:
Expand Down
14 changes: 14 additions & 0 deletions python/PyQt6/3d/auto_generated/qgspointcloudlayer3drenderer.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,20 @@ Sets the renderer behavior when zoomed out
Returns the renderer behavior when zoomed out

.. versionadded:: 3.42
%End

void setZoomOutMultiplier( double multiplier );
%Docstring
Sets the zoom out multiplier for zoomed out rendering of the overview

.. versionadded:: 4.0
%End

double zoomOutMultiplier() const;
%Docstring
Returns the zoom out multiplier for zoomed out rendering of the overview

.. versionadded:: 4.0
%End

private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,20 @@ Sets the renderer behavior when zoomed out
Returns the renderer behavior when zoomed out

.. versionadded:: 3.42
%End

void setZoomOutMultiplier( const double value );
%Docstring
Sets the zoom out multiplier for overview rendering

.. versionadded:: 4.0
%End

double zoomOutMultiplier() const;
%Docstring
Returns the zoom out multiplier for overview rendering

.. versionadded:: 4.0
%End

protected:
Expand Down
14 changes: 14 additions & 0 deletions python/core/auto_generated/pointcloud/qgspointcloudrenderer.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,20 @@ Sets the renderer behavior when zoomed out
Returns the renderer behavior when zoomed out

.. versionadded:: 3.42
%End

void setZoomOutMultiplier( const double value );
%Docstring
Sets the zoom out multiplier for overview rendering

.. versionadded:: 4.0
%End

double zoomOutMultiplier() const;
%Docstring
Returns the zoom out multiplier for overview rendering

.. versionadded:: 4.0
%End

protected:
Expand Down
3 changes: 3 additions & 0 deletions src/3d/qgspointcloudlayer3drenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ QgsPointCloudLayer3DRenderer *QgsPointCloudLayer3DRenderer::clone() const
r->setMaximumScreenError( mMaximumScreenError );
r->setShowBoundingBoxes( mShowBoundingBoxes );
r->setZoomOutBehavior( mZoomOutBehavior );
r->setZoomOutMultiplier( mZoomOutMultiplier );
return r;
}

Expand Down Expand Up @@ -188,6 +189,7 @@ void QgsPointCloudLayer3DRenderer::writeXml( QDomElement &elem, const QgsReadWri
elem.setAttribute( u"show-bounding-boxes"_s, showBoundingBoxes() ? u"1"_s : u"0"_s );
elem.setAttribute( u"point-budget"_s, mPointBudget );
elem.setAttribute( u"zoom-out-behavior"_s, qgsEnumValueToKey( mZoomOutBehavior ) );
elem.setAttribute( u"zoom-out-multiplier"_s, mZoomOutMultiplier );

QDomElement elemSymbol = doc.createElement( u"symbol"_s );
if ( mSymbol )
Expand All @@ -209,6 +211,7 @@ void QgsPointCloudLayer3DRenderer::readXml( const QDomElement &elem, const QgsRe
mMaximumScreenError = elem.attribute( u"max-screen-error"_s, u"3.0"_s ).toDouble();
mPointBudget = elem.attribute( u"point-budget"_s, u"5000000"_s ).toInt();
mZoomOutBehavior = qgsEnumKeyToValue( elem.attribute( u"zoom-out-behavior"_s ), Qgis::PointCloudZoomOutRenderBehavior::RenderExtents );
mZoomOutMultiplier = elem.attribute( u"zoom-out-multiplier"_s, u"1.0"_s ).toDouble();

if ( symbolType == "single-color"_L1 )
mSymbol = std::make_unique<QgsSingleColorPointCloud3DSymbol>();
Expand Down
13 changes: 13 additions & 0 deletions src/3d/qgspointcloudlayer3drenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,13 +315,26 @@ class _3D_EXPORT QgsPointCloudLayer3DRenderer : public QgsAbstractPointCloud3DRe
*/
Qgis::PointCloudZoomOutRenderBehavior zoomOutBehavior() const { return mZoomOutBehavior; }

/**
* Sets the zoom out multiplier for zoomed out rendering of the overview
* \since QGIS 4.0
*/
void setZoomOutMultiplier( double multiplier ) { mZoomOutMultiplier = multiplier; }

/**
* Returns the zoom out multiplier for zoomed out rendering of the overview
* \since QGIS 4.0
*/
double zoomOutMultiplier() const { return mZoomOutMultiplier; }

private:
QgsMapLayerRef mLayerRef; //!< Layer used to extract mesh data from
std::unique_ptr<QgsPointCloud3DSymbol> mSymbol;
double mMaximumScreenError = 3.0;
bool mShowBoundingBoxes = false;
int mPointBudget = 5000000;
Qgis::PointCloudZoomOutRenderBehavior mZoomOutBehavior = Qgis::PointCloudZoomOutRenderBehavior::RenderExtents;
double mZoomOutMultiplier = 1.0;

private:
#ifdef SIP_RUN
Expand Down
23 changes: 22 additions & 1 deletion src/3d/qgsvirtualpointcloudentity_p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ void QgsVirtualPointCloudEntity::handleSceneUpdate( const SceneContext &sceneCon
{
QgsVector3D cameraPosMapCoords = QgsVector3D( sceneContext.cameraPos ) + mapSettings()->origin();
const QVector<QgsPointCloudSubIndex> subIndexes = provider()->subIndexes();

const QgsPointCloudLayer3DRenderer *rendererBehavior = dynamic_cast<QgsPointCloudLayer3DRenderer *>( mLayer->renderer3D() );
const double zoomOutMultiplier = rendererBehavior ? rendererBehavior->zoomOutMultiplier() : 1;
qsizetype subIndexesRendered = 0;

for ( int i = 0; i < subIndexes.size(); ++i )
{
// If the chunked entity needs an update, do it even if it's occluded,
Expand All @@ -162,6 +167,18 @@ void QgsVirtualPointCloudEntity::handleSceneUpdate( const SceneContext &sceneCon
const float sse = Qgs3DUtils::screenSpaceError( epsilon, distance, sceneContext.screenSizePx, sceneContext.cameraFov );
constexpr float THRESHOLD = .2;

QgsBox3D scaledBox = box3D;
scaledBox.scale( zoomOutMultiplier );
const bool zoomedOut = !scaledBox.contains( cameraPosMapCoords.x(), cameraPosMapCoords.y(), cameraPosMapCoords.z() );

if ( zoomedOut )
{
setRenderSubIndexAsBbox( i, true );
continue;
}

subIndexesRendered += 1;

// always display as bbox for the initial temporary camera pos (0, 0, 0)
// then once the camera changes we display as bbox depending on screen space error
const bool displayAsBbox = sceneContext.cameraPos.isNull() || sse < THRESHOLD;
Expand All @@ -174,9 +191,13 @@ void QgsVirtualPointCloudEntity::handleSceneUpdate( const SceneContext &sceneCon
}
updateBboxEntity();

const QgsPointCloudLayer3DRenderer *rendererBehavior = dynamic_cast<QgsPointCloudLayer3DRenderer *>( mLayer->renderer3D() );
if ( provider()->overview() && rendererBehavior && ( rendererBehavior->zoomOutBehavior() == Qgis::PointCloudZoomOutRenderBehavior::RenderOverview || rendererBehavior->zoomOutBehavior() == Qgis::PointCloudZoomOutRenderBehavior::RenderOverviewAndExtents ) )
{
// no need to render the overview if all sub indexes are shown
if ( subIndexesRendered == mChunkedEntitiesMap.size() )
mOverviewEntity->setEnabled( false );
else
mOverviewEntity->setEnabled( true );
mOverviewEntity->handleSceneUpdate( sceneContext );
}
}
Expand Down
31 changes: 31 additions & 0 deletions src/app/3d/qgspointcloud3dsymbolwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,19 @@ QgsPointCloud3DSymbolWidget::QgsPointCloud3DSymbolWidget( QgsPointCloudLayer *la
else
{
mZoomOutOptions->setEnabled( false );
mZoomOutMultiplier->setEnabled( false );
}

whileBlocking( mZoomOutMultiplier )->setRange( 0, static_cast<int>( mZoomOutScale.size() - 1 ) );
mZoomOutMultiplier->setSingleStep( 1 );
mZoomOutMultiplier->setPageStep( 1 );
mZoomOutMultiplier->setTickInterval( 1 );
mZoomOutMultiplier->setTickPosition( QSlider::TicksBelow );

setZoomOutMultiplier( mZoomOutScale[mZoomOutScale.size() / 2] );

connect( mZoomOutOptions, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsPointCloud3DSymbolWidget::emitChangedSignal );
connect( mZoomOutMultiplier, &QSlider::valueChanged, this, &QgsPointCloud3DSymbolWidget::emitChangedSignal );
}
else
{
Expand Down Expand Up @@ -700,6 +710,27 @@ Qgis::PointCloudZoomOutRenderBehavior QgsPointCloud3DSymbolWidget::zoomOutBehavi
return mZoomOutOptions->currentData().value<Qgis::PointCloudZoomOutRenderBehavior>();
}

void QgsPointCloud3DSymbolWidget::setZoomOutMultiplier( double multiplier )
{
size_t idx = 0;
for ( size_t i = 0; i < mZoomOutScale.size(); ++i )
{
if ( multiplier <= mZoomOutScale[i] )
{
idx = i;
break;
}
}

whileBlocking( mZoomOutMultiplier )->setValue( idx );
}

double QgsPointCloud3DSymbolWidget::zoomOutMultiplier() const
{
const int idx = std::clamp( mZoomOutMultiplier->value(), 0, static_cast<int>( mZoomOutScale.size() ) - 1 );
return mZoomOutScale[idx];
}

void QgsPointCloud3DSymbolWidget::connectChildPanels( QgsPanelWidget *parent )
{
parent->connectChildPanel( mClassifiedRendererWidget );
Expand Down
5 changes: 5 additions & 0 deletions src/app/3d/qgspointcloud3dsymbolwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class QgsPointCloud3DSymbolWidget : public QWidget, private Ui::QgsPointCloud3DS
void setZoomOutBehavior( Qgis::PointCloudZoomOutRenderBehavior zoomOutBehavior );
Qgis::PointCloudZoomOutRenderBehavior zoomOutBehavior() const;

void setZoomOutMultiplier( double threshold );
double zoomOutMultiplier() const;

void connectChildPanels( QgsPanelWidget *parent );

private slots:
Expand Down Expand Up @@ -77,6 +80,8 @@ class QgsPointCloud3DSymbolWidget : public QWidget, private Ui::QgsPointCloud3DS
void setColorRampMinMax( double min, double max );

private:
const std::array<double, 8> mZoomOutScale = { 0.125, 0.25, 0.5, 1.0, 2.0, 4.0, 8.0, 16.0 };

int mBlockChangedSignals = 0;
int mDisableMinMaxWidgetRefresh = 0;
QgsPointCloudClassifiedRendererWidget *mClassifiedRendererWidget = nullptr;
Expand Down
1 change: 1 addition & 0 deletions src/app/3d/qgspointcloudlayer3drendererwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ QgsPointCloudLayer3DRenderer *QgsPointCloudLayer3DRendererWidget::renderer()
renderer->setMaximumScreenError( mWidgetPointCloudSymbol->maximumScreenError() );
renderer->setShowBoundingBoxes( mWidgetPointCloudSymbol->showBoundingBoxes() );
renderer->setZoomOutBehavior( mWidgetPointCloudSymbol->zoomOutBehavior() );
renderer->setZoomOutMultiplier( mWidgetPointCloudSymbol->zoomOutMultiplier() );
return renderer;
}

Expand Down
9 changes: 7 additions & 2 deletions src/core/pointcloud/qgspointcloudlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -987,9 +987,14 @@ void QgsPointCloudLayer::loadIndexesForRenderContext( QgsRenderContext &renderer
if ( subIndex.at( i ).index() )
continue;


const double zoomOutMultiplier = mRenderer ? mRenderer->zoomOutMultiplier() : 1.0;
const double widthThreshold = vpcProvider->averageSubIndexWidth() * zoomOutMultiplier;
const double heightThreshold = vpcProvider->averageSubIndexHeight() * zoomOutMultiplier;

if ( subIndex.at( i ).extent().intersects( renderExtent ) &&
( renderExtent.width() < vpcProvider->averageSubIndexWidth() ||
renderExtent.height() < vpcProvider->averageSubIndexHeight() ) )
( renderExtent.width() < widthThreshold ||
renderExtent.height() < heightThreshold ) )
{
mDataProvider->loadSubIndex( i );
}
Expand Down
5 changes: 3 additions & 2 deletions src/core/pointcloud/qgspointcloudlayerrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,9 @@ bool QgsPointCloudLayerRenderer::render()
visibleIndexes.append( si );
}
}
const bool zoomedOut = renderExtent.width() > mAverageSubIndexWidth ||
renderExtent.height() > mAverageSubIndexHeight;
const double zoomOutMultiplier = mRenderer->zoomOutMultiplier();
const bool zoomedOut = renderExtent.width() > mAverageSubIndexWidth * zoomOutMultiplier ||
renderExtent.height() > mAverageSubIndexHeight * zoomOutMultiplier;
// if the overview of virtual point cloud exists, and we are zoomed out, we render just overview
if ( mOverviewIndex && mOverviewIndex->isValid() && zoomedOut &&
mRenderer->zoomOutBehavior() == Qgis::PointCloudZoomOutRenderBehavior::RenderOverview )
Expand Down
10 changes: 10 additions & 0 deletions src/core/pointcloud/qgspointcloudrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ void QgsPointCloudRenderer::setMaximumScreenError( double error )
mMaximumScreenError = error;
}

void QgsPointCloudRenderer::setZoomOutMultiplier( double value )
{
mZoomOutMultiplier = value;
}

Qgis::RenderUnit QgsPointCloudRenderer::maximumScreenErrorUnit() const
{
return mMaximumScreenErrorUnit;
Expand Down Expand Up @@ -221,6 +226,7 @@ void QgsPointCloudRenderer::copyCommonProperties( QgsPointCloudRenderer *destina
destination->setShowLabels( mShowLabels );
destination->setLabelTextFormat( mLabelTextFormat );
destination->setZoomOutBehavior( mZoomOutBehavior );
destination->setZoomOutMultiplier( mZoomOutMultiplier );
}

void QgsPointCloudRenderer::restoreCommonProperties( const QDomElement &element, const QgsReadWriteContext &context )
Expand All @@ -246,6 +252,7 @@ void QgsPointCloudRenderer::restoreCommonProperties( const QDomElement &element,
mLabelTextFormat.readXml( element.firstChildElement( u"text-style"_s ), context );
}
mZoomOutBehavior = qgsEnumKeyToValue( element.attribute( u"zoomOutBehavior"_s ), Qgis::PointCloudZoomOutRenderBehavior::RenderExtents );
mZoomOutMultiplier = element.attribute( u"zoomOutMultiplier"_s, u"1.0"_s ).toDouble();
}

void QgsPointCloudRenderer::saveCommonProperties( QDomElement &element, const QgsReadWriteContext &context ) const
Expand All @@ -272,7 +279,10 @@ void QgsPointCloudRenderer::saveCommonProperties( QDomElement &element, const Qg
element.appendChild( mLabelTextFormat.writeXml( doc, context ) );
}
if ( mZoomOutBehavior != Qgis::PointCloudZoomOutRenderBehavior::RenderExtents )
{
element.setAttribute( u"zoomOutBehavior"_s, qgsEnumValueToKey( mZoomOutBehavior ) );
element.setAttribute( u"zoomOutMultiplier"_s, qgsDoubleToString( mZoomOutMultiplier ) );
}
}

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

/**
* Sets the zoom out multiplier for overview rendering
* \since QGIS 4.0
*/
void setZoomOutMultiplier( const double value );

/**
* Returns the zoom out multiplier for overview rendering
* \since QGIS 4.0
*/
double zoomOutMultiplier() const { return mZoomOutMultiplier; }

protected:

/**
Expand Down Expand Up @@ -855,6 +867,7 @@ class CORE_EXPORT QgsPointCloudRenderer
QgsTextFormat mLabelTextFormat;

Qgis::PointCloudZoomOutRenderBehavior mZoomOutBehavior = Qgis::PointCloudZoomOutRenderBehavior::RenderExtents;
double mZoomOutMultiplier = 1.0;
};

#endif // QGSPOINTCLOUDRENDERER_H
Loading