Skip to content

Commit

Permalink
Mesh Layer Rendering with Updated Canvas Fix (#59987)
Browse files Browse the repository at this point in the history
* cannot return min max if triangular mesh does not exist

* only create QgsRenderedLayerStatistics if values changed to prevent loop in rendering

* this was set from two places, remove it from here

* Revert "this was set from two places, remove it from here"

This reverts commit 5d8fbcc.

* add test case for not existing triangular mesh

* only emit signals here, everything else is handled in renderer creation (avoids double rendering of the mesh layer)

* while updating the widget the component signals need to be blocked

* do not update render here

* add const

* 3D map should not update layer statistics

* update renderer settings from here,  signals are emitted from mesh layer

* update test to simulate main canvas extent update

* do rendering in single pass

* emit renderer changed and remove emit of legendChanged
  • Loading branch information
JanCaha authored Jan 17, 2025
1 parent 48f9d5f commit 5fc5503
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 27 deletions.
6 changes: 5 additions & 1 deletion python/PyQt6/core/auto_generated/mesh/qgsmeshlayer.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,13 @@ Gets native mesh and updates (creates if it doesn't exist) the base triangular m
%Docstring
Returns renderer settings
%End
void setRendererSettings( const QgsMeshRendererSettings &settings );

void setRendererSettings( const QgsMeshRendererSettings &settings, const bool repaint = true );
%Docstring
Sets new renderer settings

:param settings:
:param repaint: should the update of renderer settings trigger repaint and emit rendererChanged signal
%End

QgsMeshTimeSettings timeSettings() const;
Expand Down
6 changes: 5 additions & 1 deletion python/core/auto_generated/mesh/qgsmeshlayer.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,13 @@ Gets native mesh and updates (creates if it doesn't exist) the base triangular m
%Docstring
Returns renderer settings
%End
void setRendererSettings( const QgsMeshRendererSettings &settings );

void setRendererSettings( const QgsMeshRendererSettings &settings, const bool repaint = true );
%Docstring
Sets new renderer settings

:param settings:
:param repaint: should the update of renderer settings trigger repaint and emit rendererChanged signal
%End

QgsMeshTimeSettings timeSettings() const;
Expand Down
5 changes: 2 additions & 3 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17326,13 +17326,12 @@ void QgisApp::handleRenderedLayerStatistics() const
{
QgsMeshRendererSettings rendererSettings = meshLayer->rendererSettings();
QgsMeshRendererScalarSettings scalarRendererSettings = rendererSettings.scalarSettings( rendererSettings.activeScalarDatasetGroup() );

scalarRendererSettings.setClassificationMinimumMaximum( layerStatistics->minimum( 0 ), layerStatistics->maximum( 0 ) );
rendererSettings.setScalarSettings( rendererSettings.activeScalarDatasetGroup(), scalarRendererSettings );
meshLayer->setRendererSettings( rendererSettings );
meshLayer->setRendererSettings( rendererSettings, false );

meshLayer->emitStyleChanged();
emit meshLayer->rendererChanged();
emit meshLayer->legendChanged();
}
}
}
Expand Down
13 changes: 11 additions & 2 deletions src/core/mesh/qgsmeshlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ QgsMeshRendererSettings QgsMeshLayer::rendererSettings() const
return mRendererSettings;
}

void QgsMeshLayer::setRendererSettings( const QgsMeshRendererSettings &settings )
void QgsMeshLayer::setRendererSettings( const QgsMeshRendererSettings &settings, const bool repaint )
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS

Expand All @@ -433,7 +433,11 @@ void QgsMeshLayer::setRendererSettings( const QgsMeshRendererSettings &settings
emit activeVectorDatasetGroupChanged( mRendererSettings.activeVectorDatasetGroup() );

emit rendererChanged();
triggerRepaint();

if ( repaint )
{
triggerRepaint();
}
}

QgsMeshTimeSettings QgsMeshLayer::timeSettings() const
Expand Down Expand Up @@ -1704,6 +1708,11 @@ bool QgsMeshLayer::minimumMaximumActiveScalarDataset( const QgsRectangle &extent

QgsTriangularMesh *tMesh = triangularMesh();

if ( ! tMesh )
{
return false;
}

QVector<double> scalarDatasetValues;
const QgsMeshDatasetGroupMetadata metadata = datasetGroupMetadata( datasetIndex.group() );

Expand Down
10 changes: 8 additions & 2 deletions src/core/mesh/qgsmeshlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,14 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer, public QgsAbstractProfileSo

//! Returns renderer settings
QgsMeshRendererSettings rendererSettings() const;
//! Sets new renderer settings
void setRendererSettings( const QgsMeshRendererSettings &settings );

/**
* Sets new renderer settings
*
* \param settings
* \param repaint should the update of renderer settings trigger repaint and emit rendererChanged signal
*/
void setRendererSettings( const QgsMeshRendererSettings &settings, const bool repaint = true );

/**
* Returns time format settings
Expand Down
25 changes: 13 additions & 12 deletions src/core/mesh/qgsmeshlayerrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,41 +161,42 @@ QgsMeshLayerRenderer::QgsMeshLayerRenderer(

mClippingRegions = QgsMapClippingUtils::collectClippingRegionsForLayer( *renderContext(), layer );

if ( !context.testFlag( Qgis::RenderContextFlag::RenderPreviewJob ) )
if ( !context.testFlag( Qgis::RenderContextFlag::RenderPreviewJob )
&& !( context.flags() & Qgis::RenderContextFlag::Render3DMap ) )
{
QgsMeshDatasetIndex activeDatasetIndex = layer->activeScalarDatasetIndex( context );
const QgsMeshDatasetIndex activeDatasetIndex = layer->activeScalarDatasetIndex( context );

if ( activeDatasetIndex.isValid() )
{
QgsMeshRendererScalarSettings scalarRendererSettings = mRendererSettings.scalarSettings( activeDatasetIndex.group() );
double previousMin = scalarRendererSettings.classificationMinimum();
double previousMax = scalarRendererSettings.classificationMaximum();

QgsRenderedLayerStatistics *layerStatistics = new QgsRenderedLayerStatistics( layer->id(), previousMin, previousMax );
layerStatistics->setBoundingBox( layer->extent() );
const double previousMin = scalarRendererSettings.classificationMinimum();
const double previousMax = scalarRendererSettings.classificationMaximum();

if ( scalarRendererSettings.extent() == Qgis::MeshRangeExtent::UpdatedCanvas &&
scalarRendererSettings.limits() == Qgis::MeshRangeLimit::MinimumMaximum )
{
double min, max;

bool found = layer->minimumMaximumActiveScalarDataset( context.extent(), activeDatasetIndex, min, max );
const bool found = layer->minimumMaximumActiveScalarDataset( context.extent(), activeDatasetIndex, min, max );

if ( found )
{
if ( previousMin != min || previousMax != max )
{

scalarRendererSettings.setClassificationMinimumMaximum( min, max );
mRendererSettings.setScalarSettings( activeDatasetIndex.group(), scalarRendererSettings );

QgsRenderedLayerStatistics *layerStatistics = new QgsRenderedLayerStatistics( layer->id(), previousMin, previousMax );

layerStatistics->setBoundingBox( context.extent() );
layerStatistics->setMaximum( 0, max );
layerStatistics->setMinimum( 0, min );

scalarRendererSettings.setClassificationMinimumMaximum( min, max );
mRendererSettings.setScalarSettings( activeDatasetIndex.group(), scalarRendererSettings );
appendRenderedItemDetails( layerStatistics );
}
}
}

appendRenderedItemDetails( layerStatistics );
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/gui/mesh/qgsmeshrendererscalarsettingswidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ void QgsMeshRendererScalarSettingsWidget::syncToLayer()
whileBlocking( mScalarMinSpinBox )->setValue( min );
whileBlocking( mScalarMaxSpinBox )->setValue( max );

mMinMaxValueTypeComboBox->setCurrentIndex( mMinMaxValueTypeComboBox->findData( QVariant::fromValue( settings.extent() ) ) );
whileBlocking( mMinMaxValueTypeComboBox )->setCurrentIndex( mMinMaxValueTypeComboBox->findData( QVariant::fromValue( settings.extent() ) ) );

if ( settings.limits() == Qgis::MeshRangeLimit::MinimumMaximum )
{
Expand Down
9 changes: 8 additions & 1 deletion tests/src/core/testqgsmeshlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2423,10 +2423,17 @@ void TestQgsMeshLayer::testMinimumMaximumActiveScalarDataset()
QStringLiteral( "mdal" )
);
QVERIFY( layer.isValid() );
layer.updateTriangularMesh();

datasetIndex = QgsMeshDatasetIndex( 0, 0 );

// if triangular mesh does not exist cannot extract values
extent = layer.extent();
found = layer.minimumMaximumActiveScalarDataset( extent, datasetIndex, min, max );
QCOMPARE( found, false );

// crete triangular mesh for layer
layer.updateTriangularMesh();

// tests for basic dataset
extent = layer.extent();
found = layer.minimumMaximumActiveScalarDataset( extent, datasetIndex, min, max );
Expand Down
33 changes: 29 additions & 4 deletions tests/src/core/testqgsmeshlayerrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -886,39 +886,64 @@ void TestQgsMeshRenderer::test_color_scale_based_on_canvas_extent()
layer.temporalProperties()->setIsActive( false );

int groupIndex = 0;
layer.setStaticScalarDatasetIndex( QgsMeshDatasetIndex( groupIndex, 0 ) );
QgsMeshDatasetIndex meshDatasetIndex = QgsMeshDatasetIndex( groupIndex, 0 );
layer.setStaticScalarDatasetIndex( meshDatasetIndex );

double min, max;
bool found;

QgsProject::instance()->addMapLayer( &layer );
mMapSettings->setLayers( QList<QgsMapLayer *>() << &layer );
mMapSettings->setDestinationCrs( layer.crs() );
mMapSettings->setOutputDpi( 96 );
mMapSettings->setRotation( 0 );

QgsMeshRendererSettings defaultRendererSettings = layer.rendererSettings();

// min max from current canvas settings for group
QgsMeshRendererSettings rendererSettings = layer.rendererSettings();
QgsMeshRendererScalarSettings scalarRendererSettings = rendererSettings.scalarSettings( groupIndex );
scalarRendererSettings.setLimits( Qgis::MeshRangeLimit::MinimumMaximum );
scalarRendererSettings.setExtent( Qgis::MeshRangeExtent::UpdatedCanvas );
rendererSettings.setScalarSettings( groupIndex, scalarRendererSettings );
layer.setRendererSettings( rendererSettings );

QgsRectangle extent = layer.extent();
extent.grow( 0.1 );

found = layer.minimumMaximumActiveScalarDataset( extent, meshDatasetIndex, min, max );
QVERIFY( found );
scalarRendererSettings.setClassificationMinimumMaximum( min, max );
rendererSettings.setScalarSettings( groupIndex, scalarRendererSettings );
layer.setRendererSettings( rendererSettings );

mMapSettings->setExtent( extent );
QGSRENDERMAPSETTINGSCHECK( "scale_interactive_from_canvas_1", "scale_interactive_from_canvas_1", *mMapSettings, 0, 5 );

extent = QgsRectangle( 0, 8, 2, 10 );
extent.grow( 0.1 );

found = layer.minimumMaximumActiveScalarDataset( extent, meshDatasetIndex, min, max );
QVERIFY( found );
scalarRendererSettings.setClassificationMinimumMaximum( min, max );
rendererSettings.setScalarSettings( groupIndex, scalarRendererSettings );
layer.setRendererSettings( rendererSettings );

mMapSettings->setExtent( extent );
QGSRENDERMAPSETTINGSCHECK( "scale_interactive_from_canvas_2", "scale_interactive_from_canvas_2", *mMapSettings, 0, 5 );

extent = QgsRectangle( 8, 8, 10, 10 );
extent.grow( 0.1 );

found = layer.minimumMaximumActiveScalarDataset( extent, meshDatasetIndex, min, max );
QVERIFY( found );
scalarRendererSettings.setClassificationMinimumMaximum( min, max );
rendererSettings.setScalarSettings( groupIndex, scalarRendererSettings );
layer.setRendererSettings( rendererSettings );

mMapSettings->setExtent( extent );
QGSRENDERMAPSETTINGSCHECK( "scale_interactive_from_canvas_3", "scale_interactive_from_canvas_3", *mMapSettings, 0, 5 );

// min max from whole mesh settings for group
rendererSettings = layer.rendererSettings();
rendererSettings = defaultRendererSettings;
scalarRendererSettings = rendererSettings.scalarSettings( groupIndex );
scalarRendererSettings.setLimits( Qgis::MeshRangeLimit::MinimumMaximum );
scalarRendererSettings.setExtent( Qgis::MeshRangeExtent::WholeMesh );
Expand Down

0 comments on commit 5fc5503

Please sign in to comment.