Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Mesh Render Extent Settings #59636

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 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/PyQt6/core/auto_additions/qgsmeshrenderersettings.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
# The following has been generated automatically from src/core/mesh/qgsmeshrenderersettings.h
QgsMeshRendererScalarSettings.NoResampling = QgsMeshRendererScalarSettings.DataResamplingMethod.NoResampling
QgsMeshRendererScalarSettings.NeighbourAverage = QgsMeshRendererScalarSettings.DataResamplingMethod.NeighbourAverage
# monkey patching scoped based enum
QgsMeshRendererScalarSettings.MinMaxValueType.UserDefined.__doc__ = ""
QgsMeshRendererScalarSettings.MinMaxValueType.WholeMesh.__doc__ = ""
QgsMeshRendererScalarSettings.MinMaxValueType.FixedCanvas.__doc__ = ""
QgsMeshRendererScalarSettings.MinMaxValueType.InteractiveFromCanvas.__doc__ = ""
QgsMeshRendererScalarSettings.MinMaxValueType.__doc__ = """This enumerator describes the extent used to compute min/max values

* ``UserDefined``:
* ``WholeMesh``:
* ``FixedCanvas``:
* ``InteractiveFromCanvas``:

"""
# --
QgsMeshRendererVectorArrowSettings.MinMax = QgsMeshRendererVectorArrowSettings.ArrowScalingMethod.MinMax
QgsMeshRendererVectorArrowSettings.Scaled = QgsMeshRendererVectorArrowSettings.ArrowScalingMethod.Scaled
QgsMeshRendererVectorArrowSettings.Fixed = QgsMeshRendererVectorArrowSettings.ArrowScalingMethod.Fixed
Expand Down
20 changes: 20 additions & 0 deletions python/PyQt6/core/auto_generated/mesh/qgsmeshlayer.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,26 @@ Sets labeling configuration. Takes ownership of the object.
.. versionadded:: 3.36
%End

bool minimumMaximumActiveScalarDataset( const QgsRectangle &extent, const QgsMeshDatasetIndex &datasetIndex, double &min /Out/, double &max /Out/ );
%Docstring
Extracts minimum and maximum value for active scalar dataset on mesh faces.

:param extent: extent in which intersecting faces are searched for
:param datasetIndex: index for which dataset the values should be extracted

:return: - ``True`` if values were extracted
- min: minimal value
- max: maximal value

.. versionadded:: 3.42
%End

QgsMeshDatasetIndex activeScalarDatasetIndex( QgsRenderContext &rendererContext );
%Docstring
Returns current active scalar dataset index for current renderer context.

.. versionadded:: 3.42
%End

public slots:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ Represents a mesh renderer settings for scalar datasets
NeighbourAverage,
};

enum class MinMaxValueType
{
UserDefined,
WholeMesh,
FixedCanvas,
InteractiveFromCanvas,
};

QgsColorRampShader colorRampShader() const;
%Docstring
Returns color ramp shader function
Expand Down Expand Up @@ -178,6 +186,20 @@ Returns the stroke width unit used to render edges scalar dataset
Sets the stroke width unit used to render edges scalar dataset

.. versionadded:: 3.14
%End

QgsMeshRendererScalarSettings::MinMaxValueType minMaxValueType() const;
%Docstring
Gets the extent type for minimum maximum calculation

.. versionadded:: 3.42
%End

void setMinMaxValueType( QgsMeshRendererScalarSettings::MinMaxValueType minMaxValueType );
%Docstring
Sets the extent type for minimum maximum calculation

.. versionadded:: 3.42
%End

QDomElement writeXml( QDomDocument &doc, const QgsReadWriteContext &context = QgsReadWriteContext() ) const;
Expand Down
14 changes: 14 additions & 0 deletions python/core/auto_additions/qgsmeshrenderersettings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# The following has been generated automatically from src/core/mesh/qgsmeshrenderersettings.h
# monkey patching scoped based enum
QgsMeshRendererScalarSettings.MinMaxValueType.UserDefined.__doc__ = ""
QgsMeshRendererScalarSettings.MinMaxValueType.WholeMesh.__doc__ = ""
QgsMeshRendererScalarSettings.MinMaxValueType.FixedCanvas.__doc__ = ""
QgsMeshRendererScalarSettings.MinMaxValueType.InteractiveFromCanvas.__doc__ = ""
QgsMeshRendererScalarSettings.MinMaxValueType.__doc__ = """This enumerator describes the extent used to compute min/max values

* ``UserDefined``:
* ``WholeMesh``:
* ``FixedCanvas``:
* ``InteractiveFromCanvas``:

"""
# --
# monkey patching scoped based enum
QgsMeshRendererVectorWindBarbSettings.WindSpeedUnit.MetersPerSecond.__doc__ = "Meters per second"
QgsMeshRendererVectorWindBarbSettings.WindSpeedUnit.KilometersPerHour.__doc__ = "Kilometers per hour"
QgsMeshRendererVectorWindBarbSettings.WindSpeedUnit.Knots.__doc__ = "Knots (Nautical miles per hour)"
Expand Down
20 changes: 20 additions & 0 deletions python/core/auto_generated/mesh/qgsmeshlayer.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,26 @@ Sets labeling configuration. Takes ownership of the object.
.. versionadded:: 3.36
%End

bool minimumMaximumActiveScalarDataset( const QgsRectangle &extent, const QgsMeshDatasetIndex &datasetIndex, double &min /Out/, double &max /Out/ );
%Docstring
Extracts minimum and maximum value for active scalar dataset on mesh faces.

:param extent: extent in which intersecting faces are searched for
:param datasetIndex: index for which dataset the values should be extracted

:return: - ``True`` if values were extracted
- min: minimal value
- max: maximal value

.. versionadded:: 3.42
%End

QgsMeshDatasetIndex activeScalarDatasetIndex( QgsRenderContext &rendererContext );
%Docstring
Returns current active scalar dataset index for current renderer context.

.. versionadded:: 3.42
%End

public slots:

Expand Down
22 changes: 22 additions & 0 deletions python/core/auto_generated/mesh/qgsmeshrenderersettings.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ Represents a mesh renderer settings for scalar datasets
NeighbourAverage,
};

enum class MinMaxValueType
{
UserDefined,
WholeMesh,
FixedCanvas,
InteractiveFromCanvas,
};

QgsColorRampShader colorRampShader() const;
%Docstring
Returns color ramp shader function
Expand Down Expand Up @@ -178,6 +186,20 @@ Returns the stroke width unit used to render edges scalar dataset
Sets the stroke width unit used to render edges scalar dataset

.. versionadded:: 3.14
%End

QgsMeshRendererScalarSettings::MinMaxValueType minMaxValueType() const;
%Docstring
Gets the extent type for minimum maximum calculation

.. versionadded:: 3.42
%End

void setMinMaxValueType( QgsMeshRendererScalarSettings::MinMaxValueType minMaxValueType );
%Docstring
Sets the extent type for minimum maximum calculation

.. versionadded:: 3.42
%End

QDomElement writeXml( QDomDocument &doc, const QgsReadWriteContext &context = QgsReadWriteContext() ) const;
Expand Down
14 changes: 14 additions & 0 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17612,6 +17612,20 @@ void QgisApp::handleRenderedLayerStatistics() const
rasterLayer->emitStyleChanged();
emit rasterLayer->rendererChanged();
}

QgsMeshLayer *meshLayer = qobject_cast<QgsMeshLayer *>( QgsProject::instance()->mapLayer( layerStatistics->layerId() ) );
if ( meshLayer )
{
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->emitStyleChanged();
emit meshLayer->rendererChanged();
emit meshLayer->legendChanged();
}
}
}
}
89 changes: 89 additions & 0 deletions src/core/mesh/qgsmeshlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1664,6 +1664,95 @@ QgsMapLayerRenderer *QgsMeshLayer::createMapRenderer( QgsRenderContext &renderer
return new QgsMeshLayerRenderer( this, rendererContext );
}

QgsMeshDatasetIndex QgsMeshLayer::activeScalarDatasetIndex( QgsRenderContext &rendererContext )
{
if ( rendererContext.isTemporal() )
return activeScalarDatasetAtTime( rendererContext.temporalRange(), mRendererSettings.activeScalarDatasetGroup() );
else
return staticScalarDatasetIndex( mRendererSettings.activeScalarDatasetGroup() );

return QgsMeshDatasetIndex();
}

bool QgsMeshLayer::minimumMaximumActiveScalarDataset( const QgsRectangle &extent, const QgsMeshDatasetIndex &datasetIndex, double &min, double &max )
{

if ( extent.isNull() || !this->extent().intersects( extent ) )
return false;

QgsTriangularMesh *tMesh = triangularMesh();

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

if ( !metadata.isScalar() )
{
return false;
}

QgsMeshDatasetGroupMetadata::DataType scalarDataType = QgsMeshLayerUtils::datasetValuesType( metadata.dataType() );

if ( !datasetIndex.isValid() )
{
return false;
}

// populate scalar values
const int count = QgsMeshLayerUtils::datasetValuesCount( mNativeMesh.get(), scalarDataType );
const QgsMeshDataBlock vals = QgsMeshLayerUtils::datasetValues(
this,
datasetIndex,
0,
count );

if ( vals.isValid() )
{
// vals could be scalar or vectors, for contour rendering we want always magnitude
scalarDatasetValues = QgsMeshLayerUtils::calculateMagnitudes( vals );
}
else
{
scalarDatasetValues = QVector<double>( count, std::numeric_limits<double>::quiet_NaN() );
}

QList<int> intersectedFacesIndices = tMesh->faceIndexesForRectangle( extent );

if ( intersectedFacesIndices.isEmpty() )
{
return false;
}

min = std::numeric_limits<double>::max();
max = -std::numeric_limits<double>::max();

double value;

for ( int intersectedFaceIndex : intersectedFacesIndices )
{
QgsMeshFace face = tMesh->triangles().at( intersectedFaceIndex );

if ( metadata.dataType() == QgsMeshDatasetGroupMetadata::DataType::DataOnFaces || metadata.dataType() == QgsMeshDatasetGroupMetadata::DataType::DataOnVolumes )
{
value = scalarDatasetValues.at( tMesh->trianglesToNativeFaces().at( intersectedFaceIndex ) );
min = std::min( min, value );
max = std::max( max, value );
}
else if ( metadata.dataType() == QgsMeshDatasetGroupMetadata::DataType::DataOnVertices )
{
QgsMeshVertex vertex;

for ( int vertexIndex : face )
{
value = scalarDatasetValues.at( vertexIndex );
min = std::min( min, value );
max = std::max( max, value );
}
}
}

return true;
}

QgsAbstractProfileGenerator *QgsMeshLayer::createProfileGenerator( const QgsProfileRequest &request )
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS
Expand Down
17 changes: 17 additions & 0 deletions src/core/mesh/qgsmeshlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,23 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer, public QgsAbstractProfileSo
*/
void setLabeling( QgsAbstractMeshLayerLabeling *labeling SIP_TRANSFER );

/**
* Extracts minimum and maximum value for active scalar dataset on mesh faces.
* \param extent extent in which intersecting faces are searched for
* \param datasetIndex index for which dataset the values should be extracted
* \param min minimal value
* \param max maximal value
* \return TRUE if values were extracted
* \since QGIS 3.42
*/
bool minimumMaximumActiveScalarDataset( const QgsRectangle &extent, const QgsMeshDatasetIndex &datasetIndex, double &min SIP_OUT, double &max SIP_OUT );

/**
* Returns current active scalar dataset index for current renderer context.
*
* \since QGIS 3.42
*/
QgsMeshDatasetIndex activeScalarDatasetIndex( QgsRenderContext &rendererContext );

public slots:

Expand Down
33 changes: 33 additions & 0 deletions src/core/mesh/qgsmeshlayerrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "qgsruntimeprofiler.h"
#include "qgsexpressioncontextutils.h"
#include "qgsmeshlayerelevationproperties.h"
#include "qgsrenderedlayerstatistics.h"

QgsMeshLayerRenderer::QgsMeshLayerRenderer(
QgsMeshLayer *layer,
Expand Down Expand Up @@ -160,6 +161,38 @@ QgsMeshLayerRenderer::QgsMeshLayerRenderer(

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

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

if ( activeDatasetIndex.isValid() )
{
QgsMeshRendererScalarSettings scalarRendererSettings = mRendererSettings.scalarSettings( activeDatasetIndex.group() );

if ( scalarRendererSettings.minMaxValueType() == QgsMeshRendererScalarSettings::MinMaxValueType::InteractiveFromCanvas )
{
double previousMin = scalarRendererSettings.classificationMinimum();
double previousMax = scalarRendererSettings.classificationMaximum();
double min, max;

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

if ( found )
{
if ( previousMin != min || previousMax != max )
{
QgsRenderedLayerStatistics *layerStatistics = new QgsRenderedLayerStatistics( layer->id(), min, max );
layerStatistics->setBoundingBox( context.extent() );
appendRenderedItemDetails( layerStatistics );

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

mPreparationTime = timer.elapsed();
}

Expand Down
Loading