mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-15 00:07:25 -05:00
fix aggregate functions with mesh virtual dataset group (#45446)
This commit is contained in:
parent
18a782f1fb
commit
a840cbf98c
@ -10,6 +10,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsMeshCalculator
|
||||
{
|
||||
%Docstring(signature="appended")
|
||||
|
||||
@ -390,6 +390,24 @@ Returns the dataset index of the dataset in a specific dataset group at ``time``
|
||||
:param method: the method used to check the time
|
||||
|
||||
:return: the dataset index
|
||||
%End
|
||||
|
||||
QList<QgsMeshDatasetIndex> datasetIndexInTimeInterval( const QDateTime &referenceTime,
|
||||
int groupIndex,
|
||||
qint64 time1,
|
||||
qint64 time2 ) const;
|
||||
%Docstring
|
||||
Returns a list of dataset indexes of the dataset in a specific dataset group that are between ``time1`` and ``time2`` from the ``reference`` time
|
||||
|
||||
:param referenceTime: the reference time from where to find the dataset
|
||||
:param groupIndex: the index of the dataset group
|
||||
:param time1: the first relative time of the time intervale from reference time
|
||||
:param time2: the second relative time of the time intervale from reference time
|
||||
|
||||
:return: the dataset index
|
||||
|
||||
|
||||
.. versionadded:: 3.22
|
||||
%End
|
||||
|
||||
protected:
|
||||
|
||||
@ -566,6 +566,26 @@ Dataset index is valid even the temporal properties is inactive. This method is
|
||||
|
||||
|
||||
.. versionadded:: 3.16
|
||||
%End
|
||||
|
||||
QList<QgsMeshDatasetIndex> datasetIndexInRelativeTimeInterval( const QgsInterval &startRelativeTime, const QgsInterval &endRelativeTime, int datasetGroupIndex ) const;
|
||||
%Docstring
|
||||
Returns a list of dataset indexes from datasets group that are in a interval time from the layer reference time.
|
||||
Dataset index is valid even the temporal properties is inactive. This method is used for calculation on mesh layer.
|
||||
|
||||
:param startRelativeTime: the start time of the relative interval from the reference time.
|
||||
:param endRelativeTime: the end time of the relative interval from the reference time.
|
||||
:param datasetGroupIndex: the index of the dataset group
|
||||
|
||||
:return: dataset index
|
||||
|
||||
.. note::
|
||||
|
||||
indexes are used to distinguish all the dataset groups handled by the layer (from dataprovider, extra dataset group,...)
|
||||
In the layer scope, those indexes are different from the data provider indexes.
|
||||
|
||||
|
||||
.. versionadded:: 3.22
|
||||
%End
|
||||
|
||||
QgsMeshDatasetIndex activeScalarDatasetAtTime( const QgsDateTimeRange &timeRange ) const;
|
||||
|
||||
@ -104,11 +104,132 @@ QStringList QgsMeshCalcNode::usedDatasetGroupNames() const
|
||||
return res;
|
||||
}
|
||||
|
||||
bool QgsMeshCalcNode::calculate( const QgsMeshCalcUtils &dsu, QgsMeshMemoryDatasetGroup &result ) const
|
||||
QStringList QgsMeshCalcNode::aggregatedUsedDatasetGroupNames() const
|
||||
{
|
||||
QStringList res;
|
||||
|
||||
switch ( mOperator )
|
||||
{
|
||||
case QgsMeshCalcNode::opPLUS:
|
||||
case QgsMeshCalcNode::opMINUS:
|
||||
case QgsMeshCalcNode::opMUL:
|
||||
case QgsMeshCalcNode::opDIV:
|
||||
case QgsMeshCalcNode::opPOW:
|
||||
case QgsMeshCalcNode::opEQ:
|
||||
case QgsMeshCalcNode::opNE:
|
||||
case QgsMeshCalcNode::opGT:
|
||||
case QgsMeshCalcNode::opLT:
|
||||
case QgsMeshCalcNode::opGE:
|
||||
case QgsMeshCalcNode::opLE:
|
||||
case QgsMeshCalcNode::opAND:
|
||||
case QgsMeshCalcNode::opOR:
|
||||
case QgsMeshCalcNode::opNOT:
|
||||
case QgsMeshCalcNode::opIF:
|
||||
case QgsMeshCalcNode::opSIGN:
|
||||
case QgsMeshCalcNode::opMIN:
|
||||
case QgsMeshCalcNode::opMAX:
|
||||
case QgsMeshCalcNode::opABS:
|
||||
case QgsMeshCalcNode::opNONE:
|
||||
if ( mLeft )
|
||||
{
|
||||
res += mLeft->aggregatedUsedDatasetGroupNames();
|
||||
}
|
||||
|
||||
if ( mRight )
|
||||
{
|
||||
res += mRight->aggregatedUsedDatasetGroupNames();
|
||||
}
|
||||
|
||||
if ( mCondition )
|
||||
{
|
||||
res += mCondition->aggregatedUsedDatasetGroupNames();
|
||||
}
|
||||
break;
|
||||
case QgsMeshCalcNode::opSUM_AGGR:
|
||||
case QgsMeshCalcNode::opMAX_AGGR:
|
||||
case QgsMeshCalcNode::opMIN_AGGR:
|
||||
case QgsMeshCalcNode::opAVG_AGGR:
|
||||
if ( mLeft )
|
||||
{
|
||||
res += mLeft->usedDatasetGroupNames();
|
||||
}
|
||||
|
||||
if ( mRight )
|
||||
{
|
||||
res += mRight->usedDatasetGroupNames();
|
||||
}
|
||||
|
||||
if ( mCondition )
|
||||
{
|
||||
res += mCondition->usedDatasetGroupNames();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
QStringList QgsMeshCalcNode::notAggregatedUsedDatasetGroupNames() const
|
||||
{
|
||||
QStringList res;
|
||||
|
||||
if ( mType == tDatasetGroupRef )
|
||||
{
|
||||
res.append( mDatasetGroupName );
|
||||
}
|
||||
|
||||
switch ( mOperator )
|
||||
{
|
||||
case QgsMeshCalcNode::opPLUS:
|
||||
case QgsMeshCalcNode::opMINUS:
|
||||
case QgsMeshCalcNode::opMUL:
|
||||
case QgsMeshCalcNode::opDIV:
|
||||
case QgsMeshCalcNode::opPOW:
|
||||
case QgsMeshCalcNode::opEQ:
|
||||
case QgsMeshCalcNode::opNE:
|
||||
case QgsMeshCalcNode::opGT:
|
||||
case QgsMeshCalcNode::opLT:
|
||||
case QgsMeshCalcNode::opGE:
|
||||
case QgsMeshCalcNode::opLE:
|
||||
case QgsMeshCalcNode::opAND:
|
||||
case QgsMeshCalcNode::opOR:
|
||||
case QgsMeshCalcNode::opNOT:
|
||||
case QgsMeshCalcNode::opIF:
|
||||
case QgsMeshCalcNode::opSIGN:
|
||||
case QgsMeshCalcNode::opMIN:
|
||||
case QgsMeshCalcNode::opMAX:
|
||||
case QgsMeshCalcNode::opABS:
|
||||
if ( mLeft )
|
||||
{
|
||||
res += mLeft->notAggregatedUsedDatasetGroupNames();
|
||||
}
|
||||
|
||||
if ( mRight )
|
||||
{
|
||||
res += mRight->notAggregatedUsedDatasetGroupNames();
|
||||
}
|
||||
|
||||
if ( mCondition )
|
||||
{
|
||||
res += mCondition->notAggregatedUsedDatasetGroupNames();
|
||||
}
|
||||
break;
|
||||
case QgsMeshCalcNode::opSUM_AGGR:
|
||||
case QgsMeshCalcNode::opMAX_AGGR:
|
||||
case QgsMeshCalcNode::opMIN_AGGR:
|
||||
case QgsMeshCalcNode::opAVG_AGGR:
|
||||
case QgsMeshCalcNode::opNONE:
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool QgsMeshCalcNode::calculate( const QgsMeshCalcUtils &dsu, QgsMeshMemoryDatasetGroup &result, bool isAggregate ) const
|
||||
{
|
||||
if ( mType == tDatasetGroupRef )
|
||||
{
|
||||
dsu.copy( result, mDatasetGroupName );
|
||||
dsu.copy( result, mDatasetGroupName, isAggregate );
|
||||
return true;
|
||||
}
|
||||
else if ( mType == tOperator )
|
||||
@ -116,11 +237,16 @@ bool QgsMeshCalcNode::calculate( const QgsMeshCalcUtils &dsu, QgsMeshMemoryData
|
||||
QgsMeshMemoryDatasetGroup leftDatasetGroup( "left", dsu.outputType() );
|
||||
QgsMeshMemoryDatasetGroup rightDatasetGroup( "right", dsu.outputType() );
|
||||
|
||||
if ( !mLeft || !mLeft->calculate( dsu, leftDatasetGroup ) )
|
||||
bool currentOperatorIsAggregate = mOperator == opSUM_AGGR ||
|
||||
mOperator == opMAX_AGGR ||
|
||||
mOperator == opMIN_AGGR ||
|
||||
mOperator == opAVG_AGGR;
|
||||
|
||||
if ( !mLeft || !mLeft->calculate( dsu, leftDatasetGroup, isAggregate || currentOperatorIsAggregate ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ( mRight && !mRight->calculate( dsu, rightDatasetGroup ) )
|
||||
if ( mRight && !mRight->calculate( dsu, rightDatasetGroup, isAggregate || currentOperatorIsAggregate ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -132,11 +132,17 @@ class CORE_EXPORT QgsMeshCalcNode
|
||||
* \param result destination dataset group for calculation results
|
||||
* \returns TRUE on success, FALSE on failure
|
||||
*/
|
||||
bool calculate( const QgsMeshCalcUtils &dsu, QgsMeshMemoryDatasetGroup &result ) const;
|
||||
bool calculate( const QgsMeshCalcUtils &dsu, QgsMeshMemoryDatasetGroup &result, bool isAggregate = false ) const;
|
||||
|
||||
//! Returns all dataset group names used in formula
|
||||
QStringList usedDatasetGroupNames() const;
|
||||
|
||||
//! Returns dataset group names used in formula involved in aggregate function
|
||||
QStringList aggregatedUsedDatasetGroupNames() const;
|
||||
|
||||
//! Returns dataset group names used in formula not involved in aggregate function
|
||||
QStringList notAggregatedUsedDatasetGroupNames() const;
|
||||
|
||||
/**
|
||||
* Parses string to calculation node. Caller takes responsibility to delete the node
|
||||
* \param str string with formula definition
|
||||
|
||||
@ -19,9 +19,11 @@
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
||||
#include "qgsfeedback.h"
|
||||
#include "qgsmeshcalcnode.h"
|
||||
#include "qgsmeshcalculator.h"
|
||||
#include "qgsmeshcalcutils.h"
|
||||
#include "qgsmeshlayer.h"
|
||||
#include "qgsmeshmemorydataprovider.h"
|
||||
#include "qgsmeshvirtualdatasetgroup.h"
|
||||
#include "qgis.h"
|
||||
|
||||
@ -25,10 +25,12 @@
|
||||
#include "qgis_core.h"
|
||||
#include "qgis_sip.h"
|
||||
#include "qgsrectangle.h"
|
||||
#include "qgsmeshlayer.h"
|
||||
#include "qgsmeshdataprovider.h"
|
||||
#include "qgsgeometry.h"
|
||||
#include "qgsmeshdataset.h"
|
||||
#include "qgsprovidermetadata.h"
|
||||
#include "qgsfeedback.h"
|
||||
|
||||
class QgsMeshLayer;
|
||||
class QgsFeedback;
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
|
||||
@ -31,7 +31,7 @@ const double D_TRUE = 1.0;
|
||||
const double D_FALSE = 0.0;
|
||||
const double D_NODATA = std::numeric_limits<double>::quiet_NaN();
|
||||
|
||||
std::shared_ptr<QgsMeshMemoryDatasetGroup> QgsMeshCalcUtils::createMemoryDatasetGroup( const QString &datasetGroupName, const QgsInterval &relativeTime ) const
|
||||
std::shared_ptr<QgsMeshMemoryDatasetGroup> QgsMeshCalcUtils::createMemoryDatasetGroup( const QString &datasetGroupName, const QgsInterval &relativeTime, const QgsInterval &startTime, const QgsInterval &endTime ) const
|
||||
{
|
||||
std::shared_ptr<QgsMeshMemoryDatasetGroup> grp;
|
||||
const QList<int> &indexes = mMeshLayer->datasetGroupsIndexes();
|
||||
@ -52,18 +52,27 @@ std::shared_ptr<QgsMeshMemoryDatasetGroup> QgsMeshCalcUtils::createMemoryDataset
|
||||
grp->setMinimumMaximum( meta.minimum(), meta.maximum() );
|
||||
grp->setName( meta.name() );
|
||||
|
||||
if ( !relativeTime.isValid() )
|
||||
if ( !relativeTime.isValid() && ( !endTime.isValid() || !startTime.isValid() ) )
|
||||
{
|
||||
for ( int index = 0; index < mMeshLayer->datasetCount( groupIndex ); ++index )
|
||||
grp->addDataset( createMemoryDataset( QgsMeshDatasetIndex( groupIndex, index ) ) );
|
||||
}
|
||||
else
|
||||
else if ( relativeTime.isValid() )
|
||||
{
|
||||
const QgsMeshDatasetIndex datasetIndex = mMeshLayer->datasetIndexAtRelativeTime( relativeTime, groupIndex );
|
||||
if ( datasetIndex.isValid() )
|
||||
grp->addDataset( createMemoryDataset( datasetIndex ) );
|
||||
}
|
||||
else //only start time and end time are valid
|
||||
{
|
||||
QList<QgsMeshDatasetIndex> datasetIndexes = mMeshLayer->datasetIndexInRelativeTimeInterval( startTime, endTime, groupIndex );
|
||||
|
||||
if ( datasetIndexes.isEmpty() ) // if empty, at least one dataset corresponding to startTime
|
||||
datasetIndexes.append( mMeshLayer->datasetIndexAtRelativeTime( startTime, groupIndex ) );
|
||||
|
||||
for ( const QgsMeshDatasetIndex &index : datasetIndexes )
|
||||
grp->addDataset( createMemoryDataset( index ) );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@ -333,6 +342,62 @@ QgsMeshCalcUtils::QgsMeshCalcUtils( QgsMeshLayer *layer, const QStringList &used
|
||||
mIsValid = true;
|
||||
}
|
||||
|
||||
QgsMeshCalcUtils::QgsMeshCalcUtils( QgsMeshLayer *layer,
|
||||
const QStringList &usedGroupNames,
|
||||
const QStringList &usedGroupNamesForAggregate,
|
||||
const QgsInterval &relativeTime,
|
||||
const QgsInterval &startTime,
|
||||
const QgsInterval &endTime )
|
||||
: mMeshLayer( layer )
|
||||
, mIsValid( false )
|
||||
{
|
||||
// Layer must be valid
|
||||
if ( !mMeshLayer || !mMeshLayer->dataProvider() )
|
||||
return;
|
||||
|
||||
// Resolve output type of the calculation
|
||||
|
||||
mOutputType = determineResultDataType( layer, usedGroupNames + usedGroupNamesForAggregate );
|
||||
|
||||
// Data on edges are not implemented
|
||||
if ( mOutputType == QgsMeshDatasetGroupMetadata::DataOnEdges )
|
||||
return;
|
||||
|
||||
// Support for meshes with edges are not implemented
|
||||
if ( mMeshLayer->dataProvider()->contains( QgsMesh::ElementType::Edge ) )
|
||||
return;
|
||||
|
||||
for ( const QString &groupName : usedGroupNamesForAggregate )
|
||||
{
|
||||
const std::shared_ptr<QgsMeshMemoryDatasetGroup> dsg = createMemoryDatasetGroup( groupName, QgsInterval(), startTime, endTime );
|
||||
if ( !dsg )
|
||||
return;
|
||||
|
||||
mDatasetGroupMapForAggregate.insert( groupName, dsg );
|
||||
}
|
||||
|
||||
for ( const QString &groupName : usedGroupNames )
|
||||
{
|
||||
const std::shared_ptr<QgsMeshMemoryDatasetGroup> ds = createMemoryDatasetGroup( groupName, relativeTime );
|
||||
if ( ( !ds || ds->memoryDatasets.isEmpty() ) )
|
||||
{
|
||||
if ( mDatasetGroupMapForAggregate.contains( groupName ) )
|
||||
continue;
|
||||
else
|
||||
return;
|
||||
}
|
||||
mDatasetGroupMap.insert( groupName, ds );
|
||||
}
|
||||
|
||||
QgsInterval usedInterval = relativeTime;
|
||||
if ( !usedInterval.isValid() )
|
||||
usedInterval = QgsInterval( 0 );
|
||||
mTimes.append( usedInterval.hours() );
|
||||
|
||||
mIsValid = true;
|
||||
mIgnoreTime = true;
|
||||
}
|
||||
|
||||
bool QgsMeshCalcUtils::isValid() const
|
||||
{
|
||||
return mIsValid;
|
||||
@ -343,6 +408,14 @@ const QgsMeshLayer *QgsMeshCalcUtils::layer() const
|
||||
return mMeshLayer;
|
||||
}
|
||||
|
||||
std::shared_ptr<const QgsMeshMemoryDatasetGroup> QgsMeshCalcUtils::group( const QString &datasetName, bool isAggregate ) const
|
||||
{
|
||||
if ( isAggregate )
|
||||
return mDatasetGroupMapForAggregate.value( datasetName );
|
||||
else
|
||||
return mDatasetGroupMap.value( datasetName );
|
||||
}
|
||||
|
||||
std::shared_ptr<const QgsMeshMemoryDatasetGroup> QgsMeshCalcUtils::group( const QString &datasetName ) const
|
||||
{
|
||||
return mDatasetGroupMap[datasetName];
|
||||
@ -494,11 +567,11 @@ std::shared_ptr<QgsMeshMemoryDataset> QgsMeshCalcUtils::copy(
|
||||
return output;
|
||||
}
|
||||
|
||||
void QgsMeshCalcUtils::copy( QgsMeshMemoryDatasetGroup &group1, const QString &groupName ) const
|
||||
void QgsMeshCalcUtils::copy( QgsMeshMemoryDatasetGroup &group1, const QString &groupName, bool isAggregate ) const
|
||||
{
|
||||
Q_ASSERT( isValid() );
|
||||
|
||||
const std::shared_ptr<const QgsMeshMemoryDatasetGroup> group2 = group( groupName );
|
||||
const std::shared_ptr<const QgsMeshMemoryDatasetGroup> group2 = group( groupName, isAggregate );
|
||||
Q_ASSERT( group2 );
|
||||
|
||||
if ( group2->datasetCount() == 1 )
|
||||
@ -513,7 +586,8 @@ void QgsMeshCalcUtils::copy( QgsMeshMemoryDatasetGroup &group1, const QString &g
|
||||
for ( int output_index = 0; output_index < group2->datasetCount(); ++output_index )
|
||||
{
|
||||
const std::shared_ptr<const QgsMeshMemoryDataset> o0 = group2->constDataset( output_index );
|
||||
if ( qgsDoubleNear( o0->time, mTimes.first() ) ||
|
||||
if ( mIgnoreTime ||
|
||||
qgsDoubleNear( o0->time, mTimes.first() ) ||
|
||||
qgsDoubleNear( o0->time, mTimes.last() ) ||
|
||||
( ( o0->time >= mTimes.first() ) && ( o0->time <= mTimes.last() ) )
|
||||
)
|
||||
@ -552,7 +626,12 @@ void QgsMeshCalcUtils::expand( QgsMeshMemoryDatasetGroup &group1, const QgsMeshM
|
||||
for ( int i = 1; i < group2.datasetCount(); ++i )
|
||||
{
|
||||
const std::shared_ptr<QgsMeshMemoryDataset> o = copy( o0 );
|
||||
o->time = mTimes[i];
|
||||
|
||||
if ( mIgnoreTime )
|
||||
o->time = mTimes[0];
|
||||
else
|
||||
o->time = mTimes[i];
|
||||
|
||||
group1.addDataset( o );
|
||||
}
|
||||
}
|
||||
@ -604,7 +683,10 @@ int QgsMeshCalcUtils::datasetCount(
|
||||
|
||||
if ( ( group1.datasetCount() > 1 ) || ( group2.datasetCount() > 1 ) )
|
||||
{
|
||||
return mTimes.size();
|
||||
if ( mIgnoreTime )
|
||||
return std::max( group1.datasetCount(), group2.datasetCount() );
|
||||
else
|
||||
return mTimes.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -66,19 +66,49 @@ class CORE_EXPORT QgsMeshCalcUtils
|
||||
double endTime );
|
||||
|
||||
/**
|
||||
* Creates the utils and validates the input
|
||||
* Creates the utils and validates the input for a calculation only for a dataset at time \a relativeTime
|
||||
*
|
||||
* The constructor fetches dataset values from selected dataset corresponding to the relative time \a relativeTime
|
||||
* (see QgsMeshLayer::datasetIndexAtRelativeTime() and creates memory datasets from them.
|
||||
* (see QgsMeshLayer::datasetIndexAtRelativeTime()) and creates memory datasets from them.
|
||||
* There are only one dataset per group, selected with the matching method defined for the layer.
|
||||
*
|
||||
* \param layer mesh layer
|
||||
* \param usedGroupNames dataset group's names that are used in the expression
|
||||
* \param timeRange time range
|
||||
* \param relativeTime time of the calculation
|
||||
*
|
||||
* \note this instance do not support aggregate functions
|
||||
*
|
||||
* \deprecated QGIS 3.22 because the constructor does not specify any time interval to calculate aggregate functions
|
||||
*/
|
||||
Q_DECL_DEPRECATED QgsMeshCalcUtils( QgsMeshLayer *layer,
|
||||
const QStringList &usedGroupNames,
|
||||
const QgsInterval &relativeTime );
|
||||
|
||||
/**
|
||||
* Creates the utils and validates the input for a calculation only for a dataset at time \a relativeTime
|
||||
*
|
||||
* The constructor fetches dataset values from selected dataset corresponding to the relative time \a relativeTime
|
||||
* (see QgsMeshLayer::datasetIndexAtRelativeTime()) and creates memory datasets from them.
|
||||
* There are only one dataset per group, selected with the matching method defined for the layer,
|
||||
* excepted when an aggregate function is involved upstream of a node. In this case,
|
||||
* all the dataset that are between start time and end time are selected.
|
||||
*
|
||||
* \param layer mesh layer
|
||||
* \param usedGroupNames dataset group's names that are used in the expression and not involved in a aggregate function
|
||||
* \param usedGroupNamesForAggregate dataset group's names that are used in the expression and involved in a aggregate function
|
||||
* \param relativeTime time of the calculation
|
||||
* \param startTime retlative start time for aggregate functions
|
||||
* \param endTime relative end time for aggregate functions
|
||||
*
|
||||
* \since QGIS 3.22
|
||||
*/
|
||||
QgsMeshCalcUtils( QgsMeshLayer *layer,
|
||||
const QStringList &usedGroupNames,
|
||||
const QgsInterval &relativeTime );
|
||||
const QStringList &usedGroupNamesForAggregate,
|
||||
const QgsInterval &relativeTime,
|
||||
const QgsInterval &startTime,
|
||||
const QgsInterval &endTime );
|
||||
|
||||
|
||||
//! Returns whether the input parameters are consistent and valid for given mesh layer
|
||||
bool isValid() const;
|
||||
@ -99,7 +129,7 @@ class CORE_EXPORT QgsMeshCalcUtils
|
||||
std::shared_ptr<QgsMeshMemoryDataset> number( double val, double time ) const;
|
||||
|
||||
//! Creates a deepcopy of group with groupName to group1. Does not copy datasets for filtered out times.
|
||||
void copy( QgsMeshMemoryDatasetGroup &group1, const QString &groupName ) const;
|
||||
void copy( QgsMeshMemoryDatasetGroup &group1, const QString &groupName, bool forAggregate = false ) const;
|
||||
|
||||
//! Creates a deepcopy of dataset0
|
||||
std::shared_ptr<QgsMeshMemoryDataset> copy( std::shared_ptr<const QgsMeshMemoryDataset> dataset0 ) const;
|
||||
@ -229,7 +259,20 @@ class CORE_EXPORT QgsMeshCalcUtils
|
||||
* memory dataset group. Returns NULLPTR if no such dataset group
|
||||
* exists. Resulting datasets are guaranteed to have the same mOutputType type
|
||||
*/
|
||||
std::shared_ptr<QgsMeshMemoryDatasetGroup> createMemoryDatasetGroup( const QString &datasetGroupName, const QgsInterval &relativeTime = QgsInterval() ) const;
|
||||
std::shared_ptr<QgsMeshMemoryDatasetGroup> createMemoryDatasetGroup( const QString &datasetGroupName,
|
||||
const QgsInterval &relativeTime = QgsInterval(),
|
||||
const QgsInterval &startTime = QgsInterval(),
|
||||
const QgsInterval &endTime = QgsInterval() ) const;
|
||||
|
||||
/**
|
||||
* Returns dataset group based on name, the dataset count contained in the group will depend on \a isAggregate.
|
||||
* If isAggregate is TRUE, the dataset group will contained all dataset needed to calculate aggregate function.
|
||||
* If isAggregate isFALSE, the datasetgroup will only contain dataset group needed to calculate non aggregate function.
|
||||
* For example, if \a this instance is created with a relative time, a start time and an end time, that is a calculation that
|
||||
* will be operated only for this relative time, dataset group involved in a aggregate function will have all the dataset between
|
||||
* start time and end time, other dataset will only have the dataset corresponding to relative time.
|
||||
*/
|
||||
std::shared_ptr<const QgsMeshMemoryDatasetGroup> group( const QString &groupName, bool isAggregate ) const;
|
||||
|
||||
/**
|
||||
* Creates dataset based on group. Initializes values and active based on group type.
|
||||
@ -303,6 +346,9 @@ class CORE_EXPORT QgsMeshCalcUtils
|
||||
//!< E.g. one dataset with element outputs and one with node outputs
|
||||
QVector<double> mTimes;
|
||||
QMap < QString, std::shared_ptr<QgsMeshMemoryDatasetGroup> > mDatasetGroupMap; //!< Groups that are referenced in the expression
|
||||
QMap < QString, std::shared_ptr<QgsMeshMemoryDatasetGroup> > mDatasetGroupMapForAggregate; //!< Groups that are referenced in the expression and used for aggregate function
|
||||
|
||||
bool mIgnoreTime = false; // with virtual datasetgroup, we only consider the current time step, except for aggregate function where we don't care about time value
|
||||
};
|
||||
|
||||
///@endcond
|
||||
|
||||
@ -72,6 +72,35 @@ QgsMeshDatasetIndex QgsMeshDatasetSourceInterface::datasetIndexAtTime(
|
||||
return QgsMeshDatasetIndex();
|
||||
}
|
||||
|
||||
QList<QgsMeshDatasetIndex> QgsMeshDatasetSourceInterface::datasetIndexInTimeInterval( const QDateTime &referenceTime, int groupIndex, qint64 time1, qint64 time2 ) const
|
||||
{
|
||||
const QDateTime requestDateTime = referenceTime.addMSecs( time1 );
|
||||
qint64 providerTime1;
|
||||
qint64 providerTime2;
|
||||
const QDateTime providerReferenceTime = mTemporalCapabilities->referenceTime();
|
||||
if ( mTemporalCapabilities->referenceTime().isValid() )
|
||||
{
|
||||
providerTime1 = providerReferenceTime.msecsTo( requestDateTime );
|
||||
providerTime2 = providerTime1 - time1 + time2;
|
||||
}
|
||||
else
|
||||
{
|
||||
providerTime1 = time1;
|
||||
providerTime2 = time2;
|
||||
}
|
||||
|
||||
QList<QgsMeshDatasetIndex> ret;
|
||||
for ( int i = 0; i < datasetCount( groupIndex ); ++i )
|
||||
{
|
||||
QgsMeshDatasetIndex datasetIndex( groupIndex, i );
|
||||
qint64 time = mTemporalCapabilities->datasetTime( datasetIndex );
|
||||
if ( time >= providerTime1 && time <= providerTime2 )
|
||||
ret.append( datasetIndex );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QgsMeshDatasetSourceInterface::QgsMeshDatasetSourceInterface():
|
||||
mTemporalCapabilities( std::make_unique<QgsMeshDataProviderTemporalCapabilities>() ) {}
|
||||
|
||||
|
||||
@ -401,6 +401,23 @@ class CORE_EXPORT QgsMeshDatasetSourceInterface SIP_ABSTRACT
|
||||
qint64 time,
|
||||
QgsMeshDataProviderTemporalCapabilities::MatchingTemporalDatasetMethod method ) const;
|
||||
|
||||
/**
|
||||
* Returns a list of dataset indexes of the dataset in a specific dataset group that are between \a time1 and \a time2 from the \a reference time
|
||||
*
|
||||
* \param referenceTime the reference time from where to find the dataset
|
||||
* \param groupIndex the index of the dataset group
|
||||
* \param time1 the first relative time of the time intervale from reference time
|
||||
* \param time2 the second relative time of the time intervale from reference time
|
||||
*
|
||||
* \return the dataset index
|
||||
*
|
||||
* \since QGIS 3.22
|
||||
*/
|
||||
QList<QgsMeshDatasetIndex> datasetIndexInTimeInterval( const QDateTime &referenceTime,
|
||||
int groupIndex,
|
||||
qint64 time1,
|
||||
qint64 time2 ) const;
|
||||
|
||||
protected:
|
||||
std::unique_ptr<QgsMeshDataProviderTemporalCapabilities> mTemporalCapabilities;
|
||||
};
|
||||
|
||||
@ -237,6 +237,28 @@ QgsMeshDatasetIndex QgsMeshDatasetGroupStore::datasetIndexAtTime(
|
||||
group.first->datasetIndexAtTime( referenceTime, group.second, time, method ).dataset() );
|
||||
}
|
||||
|
||||
QList<QgsMeshDatasetIndex> QgsMeshDatasetGroupStore::datasetIndexInTimeInterval(
|
||||
qint64 time1,
|
||||
qint64 time2,
|
||||
int groupIndex ) const
|
||||
{
|
||||
const QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( groupIndex );
|
||||
if ( !group.first )
|
||||
return QList<QgsMeshDatasetIndex>();
|
||||
|
||||
const QDateTime &referenceTime = mPersistentProvider ? mPersistentProvider->temporalCapabilities()->referenceTime() : QDateTime();
|
||||
|
||||
const QList<QgsMeshDatasetIndex> datasetIndexes = group.first->datasetIndexInTimeInterval( referenceTime, group.second, time1, time2 );
|
||||
|
||||
QList<QgsMeshDatasetIndex> ret;
|
||||
ret.reserve( datasetIndexes.count() );
|
||||
|
||||
for ( const QgsMeshDatasetIndex &sourceDatasetIndex : datasetIndexes )
|
||||
ret.append( QgsMeshDatasetIndex( groupIndex, sourceDatasetIndex.dataset() ) );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
qint64 QgsMeshDatasetGroupStore::datasetRelativeTime( const QgsMeshDatasetIndex &index ) const
|
||||
{
|
||||
QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
|
||||
|
||||
@ -198,6 +198,13 @@ class QgsMeshDatasetGroupStore: public QObject
|
||||
int groupIndex,
|
||||
QgsMeshDataProviderTemporalCapabilities::MatchingTemporalDatasetMethod method ) const;
|
||||
|
||||
/**
|
||||
* Returns the global dataset index of the dataset int the dataset group with \a groupIndex, that is between relative times \a time1 and \a time2
|
||||
*
|
||||
* Since QGIS 3.22
|
||||
*/
|
||||
QList<QgsMeshDatasetIndex> datasetIndexInTimeInterval( qint64 time1, qint64 time2, int groupIndex ) const;
|
||||
|
||||
//! Returns the relative time of the dataset from the persistent provider reference time
|
||||
qint64 datasetRelativeTime( const QgsMeshDatasetIndex &index ) const;
|
||||
|
||||
|
||||
@ -588,6 +588,24 @@ QgsMeshDatasetIndex QgsMeshLayer::datasetIndexAtRelativeTime( const QgsInterval
|
||||
return mDatasetGroupStore->datasetIndexAtTime( relativeTime.seconds() * 1000, datasetGroupIndex, mTemporalProperties->matchingMethod() );
|
||||
}
|
||||
|
||||
QList<QgsMeshDatasetIndex> QgsMeshLayer::datasetIndexInRelativeTimeInterval( const QgsInterval &startRelativeTime, const QgsInterval &endRelativeTime, int datasetGroupIndex ) const
|
||||
{
|
||||
qint64 usedRelativeTime1 = startRelativeTime.seconds() * 1000;
|
||||
qint64 usedRelativeTime2 = endRelativeTime.seconds() * 1000;
|
||||
|
||||
//adjust relative time if layer reference time is different from provider reference time
|
||||
if ( mTemporalProperties->referenceTime().isValid() &&
|
||||
mDataProvider &&
|
||||
mDataProvider->isValid() &&
|
||||
mTemporalProperties->referenceTime() != mDataProvider->temporalCapabilities()->referenceTime() )
|
||||
{
|
||||
usedRelativeTime1 = usedRelativeTime1 + mTemporalProperties->referenceTime().msecsTo( mDataProvider->temporalCapabilities()->referenceTime() );
|
||||
usedRelativeTime2 = usedRelativeTime2 + mTemporalProperties->referenceTime().msecsTo( mDataProvider->temporalCapabilities()->referenceTime() );
|
||||
}
|
||||
|
||||
return mDatasetGroupStore->datasetIndexInTimeInterval( usedRelativeTime1, usedRelativeTime2, datasetGroupIndex );
|
||||
}
|
||||
|
||||
void QgsMeshLayer::applyClassificationOnScalarSettings( const QgsMeshDatasetGroupMetadata &meta, QgsMeshRendererScalarSettings &scalarSettings ) const
|
||||
{
|
||||
if ( meta.extraOptions().contains( QStringLiteral( "classification" ) ) )
|
||||
|
||||
@ -582,6 +582,22 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer
|
||||
*/
|
||||
QgsMeshDatasetIndex datasetIndexAtRelativeTime( const QgsInterval &relativeTime, int datasetGroupIndex ) const;
|
||||
|
||||
/**
|
||||
* Returns a list of dataset indexes from datasets group that are in a interval time from the layer reference time.
|
||||
* Dataset index is valid even the temporal properties is inactive. This method is used for calculation on mesh layer.
|
||||
*
|
||||
* \param startRelativeTime the start time of the relative interval from the reference time.
|
||||
* \param endRelativeTime the end time of the relative interval from the reference time.
|
||||
* \param datasetGroupIndex the index of the dataset group
|
||||
* \returns dataset index
|
||||
*
|
||||
* \note indexes are used to distinguish all the dataset groups handled by the layer (from dataprovider, extra dataset group,...)
|
||||
* In the layer scope, those indexes are different from the data provider indexes.
|
||||
*
|
||||
* \since QGIS 3.22
|
||||
*/
|
||||
QList<QgsMeshDatasetIndex> datasetIndexInRelativeTimeInterval( const QgsInterval &startRelativeTime, const QgsInterval &endRelativeTime, int datasetGroupIndex ) const;
|
||||
|
||||
/**
|
||||
* Returns dataset index from active scalar group depending on the time range.
|
||||
* If the temporal properties is not active, return the static dataset
|
||||
|
||||
@ -40,8 +40,10 @@ void QgsMeshVirtualDatasetGroup::initialize()
|
||||
if ( !mCalcNode || !mLayer )
|
||||
return;
|
||||
|
||||
mDatasetGroupNameUsed = mCalcNode->usedDatasetGroupNames();
|
||||
setDataType( QgsMeshCalcUtils::determineResultDataType( mLayer, mDatasetGroupNameUsed ) );
|
||||
mDatasetGroupNameUsed = mCalcNode->notAggregatedUsedDatasetGroupNames();
|
||||
mDatasetGroupNameUsedForAggregate = mCalcNode->aggregatedUsedDatasetGroupNames();
|
||||
setDataType( QgsMeshCalcUtils::determineResultDataType( mLayer,
|
||||
mDatasetGroupNameUsed + mDatasetGroupNameUsedForAggregate ) );
|
||||
|
||||
//populate used group indexes
|
||||
QMap<QString, int> usedDatasetGroupindexes;
|
||||
@ -152,7 +154,12 @@ bool QgsMeshVirtualDatasetGroup::calculateDataset() const
|
||||
if ( !mLayer )
|
||||
return false;
|
||||
|
||||
const QgsMeshCalcUtils dsu( mLayer, mDatasetGroupNameUsed, QgsInterval( mDatasetTimes[mCurrentDatasetIndex] / 1000.0 ) );
|
||||
const QgsMeshCalcUtils dsu( mLayer,
|
||||
mDatasetGroupNameUsed,
|
||||
mDatasetGroupNameUsedForAggregate,
|
||||
QgsInterval( mDatasetTimes[mCurrentDatasetIndex] / 1000.0 ),
|
||||
QgsInterval( mStartTime / 1000.0 ),
|
||||
QgsInterval( mEndTime / 1000.0 ) );
|
||||
|
||||
if ( !dsu.isValid() )
|
||||
return false;
|
||||
|
||||
@ -66,9 +66,10 @@ class CORE_EXPORT QgsMeshVirtualDatasetGroup: public QgsMeshDatasetGroup
|
||||
QString mFormula;
|
||||
std::unique_ptr<QgsMeshCalcNode> mCalcNode;
|
||||
QgsMeshLayer *mLayer = nullptr;
|
||||
qint64 mStartTime = 0.0;
|
||||
qint64 mEndTime = 0.0;
|
||||
qint64 mStartTime = 0;
|
||||
qint64 mEndTime = 0;
|
||||
QStringList mDatasetGroupNameUsed;
|
||||
QStringList mDatasetGroupNameUsedForAggregate;
|
||||
QList<qint64> mDatasetTimes;
|
||||
|
||||
mutable std::shared_ptr<QgsMeshMemoryDataset> mCacheDataset;
|
||||
|
||||
@ -362,6 +362,71 @@ void TestQgsMeshCalculator::virtualDatasetGroup()
|
||||
QCOMPARE( dataset->datasetValue( 2 ).scalar(), 7.0 );
|
||||
QCOMPARE( dataset->datasetValue( 3 ).scalar(), 5.5 );
|
||||
QCOMPARE( dataset->datasetValue( 4 ).scalar(), 4.0 );
|
||||
|
||||
formula = QStringLiteral( "\"VertexScalarDataset\" + max_aggr (\"VertexScalarDataset\")" );
|
||||
virtualDatasetGroup = QgsMeshVirtualDatasetGroup( "Virtual Dataset group", formula, mpMeshLayer, 0, 10000000 );
|
||||
virtualDatasetGroup.initialize();
|
||||
QCOMPARE( virtualDatasetGroup.datasetCount(), 2 );
|
||||
|
||||
dataset = virtualDatasetGroup.dataset( 0 );
|
||||
QCOMPARE( dataset->valuesCount(), 5 );
|
||||
QCOMPARE( dataset->datasetValue( 0 ).scalar(), 3.0 );
|
||||
QCOMPARE( dataset->datasetValue( 1 ).scalar(), 5.0 );
|
||||
QCOMPARE( dataset->datasetValue( 2 ).scalar(), 7.0 );
|
||||
QCOMPARE( dataset->datasetValue( 3 ).scalar(), 5.0 );
|
||||
QCOMPARE( dataset->datasetValue( 4 ).scalar(), 3.0 );
|
||||
|
||||
dataset = virtualDatasetGroup.dataset( 1 );
|
||||
QCOMPARE( dataset->valuesCount(), 5 );
|
||||
QCOMPARE( dataset->datasetValue( 0 ).scalar(), 4.0 );
|
||||
QCOMPARE( dataset->datasetValue( 1 ).scalar(), 6.0 );
|
||||
QCOMPARE( dataset->datasetValue( 2 ).scalar(), 8.0 );
|
||||
QCOMPARE( dataset->datasetValue( 3 ).scalar(), 6.0 );
|
||||
QCOMPARE( dataset->datasetValue( 4 ).scalar(), 4.0 );
|
||||
|
||||
formula = QStringLiteral( "max_aggr (\"FaceScalarDataset\") + min_aggr (\"FaceScalarDataset\")" );
|
||||
virtualDatasetGroup = QgsMeshVirtualDatasetGroup( "Virtual Dataset group", formula, mpMeshLayer, 0, 10000000 );
|
||||
virtualDatasetGroup.initialize();
|
||||
QCOMPARE( virtualDatasetGroup.datasetCount(), 1 );
|
||||
|
||||
dataset = virtualDatasetGroup.dataset( 0 );
|
||||
QCOMPARE( dataset->valuesCount(), 2 );
|
||||
QCOMPARE( dataset->datasetValue( 0 ).scalar(), 3.0 );
|
||||
QCOMPARE( dataset->datasetValue( 1 ).scalar(), 5.0 );
|
||||
|
||||
formula = QStringLiteral( "max_aggr (\"FaceScalarDataset\") + \"VertexScalarDataset\"" );
|
||||
virtualDatasetGroup = QgsMeshVirtualDatasetGroup( "Virtual Dataset group", formula, mpMeshLayer, 0, 10000000 );
|
||||
virtualDatasetGroup.initialize();
|
||||
QCOMPARE( virtualDatasetGroup.datasetCount(), 2 );
|
||||
|
||||
dataset = virtualDatasetGroup.dataset( 0 );
|
||||
QCOMPARE( dataset->valuesCount(), 5 );
|
||||
QCOMPARE( dataset->datasetValue( 0 ).scalar(), 3.0 );
|
||||
QCOMPARE( dataset->datasetValue( 1 ).scalar(), 4.5 );
|
||||
QCOMPARE( dataset->datasetValue( 2 ).scalar(), 6.0 );
|
||||
QCOMPARE( dataset->datasetValue( 3 ).scalar(), 4.5 );
|
||||
QCOMPARE( dataset->datasetValue( 4 ).scalar(), 3.0 );
|
||||
|
||||
dataset = virtualDatasetGroup.dataset( 1 );
|
||||
QCOMPARE( dataset->valuesCount(), 5 );
|
||||
QCOMPARE( dataset->datasetValue( 0 ).scalar(), 4.0 );
|
||||
QCOMPARE( dataset->datasetValue( 1 ).scalar(), 5.5 );
|
||||
QCOMPARE( dataset->datasetValue( 2 ).scalar(), 7.0 );
|
||||
QCOMPARE( dataset->datasetValue( 3 ).scalar(), 5.5 );
|
||||
QCOMPARE( dataset->datasetValue( 4 ).scalar(), 4.0 );
|
||||
|
||||
formula = QStringLiteral( "max_aggr (\"FaceScalarDataset\" + \"VertexScalarDataset\")" );
|
||||
virtualDatasetGroup = QgsMeshVirtualDatasetGroup( "Virtual Dataset group", formula, mpMeshLayer, 0, 10000000 );
|
||||
virtualDatasetGroup.initialize();
|
||||
QCOMPARE( virtualDatasetGroup.datasetCount(), 1 );
|
||||
|
||||
dataset = virtualDatasetGroup.dataset( 0 );
|
||||
QCOMPARE( dataset->valuesCount(), 5 );
|
||||
QCOMPARE( dataset->datasetValue( 0 ).scalar(), 4.0 );
|
||||
QCOMPARE( dataset->datasetValue( 1 ).scalar(), 5.5 );
|
||||
QCOMPARE( dataset->datasetValue( 2 ).scalar(), 7.0 );
|
||||
QCOMPARE( dataset->datasetValue( 3 ).scalar(), 5.5 );
|
||||
QCOMPARE( dataset->datasetValue( 4 ).scalar(), 4.0 );
|
||||
}
|
||||
|
||||
|
||||
@ -378,6 +443,7 @@ void TestQgsMeshCalculator::test_dataset_group_dependency()
|
||||
{
|
||||
const std::shared_ptr<QgsMeshMemoryDataset> ds = std::make_shared<QgsMeshMemoryDataset>();
|
||||
ds->time = i / 3600.0;
|
||||
ds->valid = true;
|
||||
for ( int v = 0; v < vertexCount; ++v )
|
||||
ds->values.append( QgsMeshDatasetValue( v / 2.0 + dsg ) );
|
||||
|
||||
@ -396,7 +462,7 @@ void TestQgsMeshCalculator::test_dataset_group_dependency()
|
||||
formulas.append( QStringLiteral( " max_aggr ( \"VertexScalarDataset\") + \"virtual_0\"" ) );
|
||||
formulas.append( QStringLiteral( " \"virtual_0\" + max_aggr ( \"VertexScalarDataset\") + 1" ) );
|
||||
formulas.append( QStringLiteral( "if ( \"FaceScalarDataset\" = \"VertexScalarDataset\" , 0 , 1 )" ) ); //temporal one, must have several datasets
|
||||
formulas.append( QStringLiteral( "if ( 2 = 1 , 0 , 1 )" ) ); //dtatic one, must have one dataset
|
||||
formulas.append( QStringLiteral( "if ( 2 = 1 , 0 , 1 )" ) ); //static one, must have one dataset
|
||||
formulas.append( QStringLiteral( "if ( 2 = 1 , \"FaceScalarDataset\" , 1 )" ) ); //temporal one, must have several datasets
|
||||
QVector<int> sizes{10, 10, 2, 1, 1, 10, 10, 2, 1, 2};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user