23 #include "qgsmeshmemorydataprovider.h"
30 const double D_TRUE = 1.0;
31 const double D_FALSE = 0.0;
32 const double D_NODATA = std::numeric_limits<double>::quiet_NaN();
34 std::shared_ptr<QgsMeshMemoryDatasetGroup> QgsMeshCalcUtils::createMemoryDatasetGroup(
const QString &datasetGroupName,
const QgsInterval &relativeTime )
const
36 std::shared_ptr<QgsMeshMemoryDatasetGroup> grp;
37 const QList<int> &indexes = mMeshLayer->datasetGroupsIndexes();
38 for (
int groupIndex : indexes )
41 const QString name = meta.
name();
42 if ( name == datasetGroupName )
49 grp = std::make_shared<QgsMeshMemoryDatasetGroup>();
51 grp->setDataType( mOutputType );
53 grp->setName( meta.
name() );
57 for (
int index = 0; index < mMeshLayer->datasetCount( groupIndex ); ++index )
62 QgsMeshDatasetIndex datasetIndex = mMeshLayer->datasetIndexAtRelativeTime( relativeTime, groupIndex );
64 grp->addDataset( createMemoryDataset( datasetIndex ) );
77 return createMemoryDataset( grp.
dataType() );
80 std::shared_ptr<QgsMeshMemoryDataset> QgsMeshCalcUtils::createMemoryDataset(
const QgsMeshDatasetIndex &datasetIndex )
const
83 int groupIndex = datasetIndex.
group();
84 const auto meta = mMeshLayer->datasetGroupMetadata( groupIndex );
90 std::shared_ptr<QgsMeshMemoryDataset> ds = createMemoryDataset( mOutputType );
93 ds->time = dsMeta.
time();
97 QgsMeshDataBlock block = QgsMeshLayerUtils::datasetValues( mMeshLayer, datasetIndex, 0, nativeCount );
100 Q_ASSERT( block.
count() == nativeCount );
107 QVector<double> data =
108 QgsMeshLayerUtils::interpolateFromFacesData(
115 Q_ASSERT( data.size() == resultCount );
116 for (
int valueIndex = 0; valueIndex < resultCount; ++valueIndex )
121 QVector<double> buf = block.
values();
122 QVector<double> x( nativeCount );
123 QVector<double> y( nativeCount );
124 for (
int value_i = 0; value_i < nativeCount; ++value_i )
126 x[value_i] = buf[2 * value_i];
127 y[value_i] = buf[2 * value_i + 1];
130 QVector<double> dataX =
131 QgsMeshLayerUtils::interpolateFromFacesData(
133 mMeshLayer->nativeMesh(),
134 mMeshLayer->triangularMesh(),
136 mMeshLayer->rendererSettings().scalarSettings( groupIndex ).dataResamplingMethod()
138 Q_ASSERT( dataX.size() == resultCount );
139 QVector<double> dataY =
140 QgsMeshLayerUtils::interpolateFromFacesData(
142 mMeshLayer->nativeMesh(),
143 mMeshLayer->triangularMesh(),
145 mMeshLayer->rendererSettings().scalarSettings( groupIndex ).dataResamplingMethod()
148 Q_ASSERT( dataY.size() == resultCount );
150 for (
int value_i = 0; value_i < resultCount; ++value_i )
158 for (
int value_i = 0; value_i < resultCount; ++value_i )
159 ds->values[value_i] = block.
value( value_i );
166 for (
int value_i = 0; value_i < dp->
faceCount(); ++value_i )
167 ds->active[value_i] = active.
active( value_i );
177 std::shared_ptr<QgsMeshMemoryDataset> ds = std::make_shared<QgsMeshMemoryDataset>();
180 ds->values.resize( mMeshLayer->dataProvider()->vertexCount() );
181 ds->active.resize( mMeshLayer->dataProvider()->faceCount() );
182 memset( ds->active.data(), 1,
static_cast<size_t>( ds->active.size() ) *
sizeof(
int ) );
186 ds->values.resize( mMeshLayer->dataProvider()->faceCount() );
192 QgsMeshCalcUtils:: QgsMeshCalcUtils(
QgsMeshLayer *layer,
193 const QStringList &usedGroupNames,
196 : mMeshLayer( layer )
204 mOutputType = determineResultDataType( layer, usedGroupNames );
216 for (
const QString &groupName : usedGroupNames )
218 std::shared_ptr<QgsMeshMemoryDatasetGroup> ds = createMemoryDatasetGroup( groupName );
222 mDatasetGroupMap.insert( groupName, ds );
227 bool timesPopulated =
false;
228 const QList<std::shared_ptr<QgsMeshMemoryDatasetGroup>> vals = mDatasetGroupMap.values();
229 for (
const std::shared_ptr<QgsMeshMemoryDatasetGroup> &ds : vals )
231 if ( ds->datasetCount() == 0 )
237 if ( ds->datasetCount() > 1 )
239 if ( timesPopulated )
241 if ( ds->datasetCount() != mTimes.size() )
248 for (
int datasetIndex = 0; datasetIndex < ds->datasetCount(); ++datasetIndex )
250 std::shared_ptr<const QgsMeshMemoryDataset> o = ds->constDataset( datasetIndex );
251 if ( timesPopulated )
261 mTimes.append( o->time );
265 timesPopulated =
true;
270 if ( mTimes.isEmpty() )
272 mTimes.push_back( 0.0 );
277 for ( QVector<double>::iterator it = mTimes.begin(); it != mTimes.end(); )
281 ( ( *it >= startTime ) && ( *it <= endTime ) ) )
284 it = mTimes.erase( it );
289 for (
const std::shared_ptr<QgsMeshMemoryDatasetGroup> &ds : vals )
291 if ( ds->dataType() != mOutputType )
299 QgsMeshCalcUtils::QgsMeshCalcUtils(
QgsMeshLayer *layer,
const QStringList &usedGroupNames,
const QgsInterval &relativeTime )
300 : mMeshLayer( layer )
308 mOutputType = determineResultDataType( layer, usedGroupNames );
322 for (
const QString &groupName : usedGroupNames )
324 std::shared_ptr<QgsMeshMemoryDatasetGroup> ds = createMemoryDatasetGroup( groupName, relativeTime );
325 if ( !ds || ds->memoryDatasets.isEmpty() )
328 mDatasetGroupMap.insert( groupName, ds );
331 mTimes.push_back( usedInterval.
hours() );
336 bool QgsMeshCalcUtils::isValid()
const
346 std::shared_ptr<const QgsMeshMemoryDatasetGroup> QgsMeshCalcUtils::group(
const QString &datasetName )
const
348 return mDatasetGroupMap[datasetName];
357 std::shared_ptr<QgsMeshMemoryDataset> output = createMemoryDataset( filter );
358 output->time = mTimes[0];
360 const QList<int> faceIndexesForRectangle = triangularMesh()->faceIndexesForRectangle( extent );
361 const QVector<int> trianglesToNativeFaces = triangularMesh()->trianglesToNativeFaces();
365 for (
const int faceIndex : faceIndexesForRectangle )
367 const int nativeIndex = trianglesToNativeFaces[faceIndex];
368 const QgsMeshFace face = nativeMesh()->face( nativeIndex );
369 for (
const int vertexIndex : face )
371 output->values[vertexIndex].set( D_TRUE );
377 for (
const int faceIndex : faceIndexesForRectangle )
379 const int nativeIndex = trianglesToNativeFaces[faceIndex];
380 output->values[nativeIndex].set( D_TRUE );
392 std::shared_ptr<QgsMeshMemoryDataset> output = createMemoryDataset( filter );
393 output->time = mTimes[0];
395 const QVector<QgsMeshVertex> &vertices = triangularMesh()->vertices();
399 int nativeVertexCount = mMeshLayer->dataProvider()->vertexCount();
401 for (
int i = 0; i < nativeVertexCount; ++i )
406 output->values[i].set( D_TRUE );
410 output->values[i].set( D_FALSE );
416 const QVector<QgsMeshFace> &triangles = triangularMesh()->triangles();
417 for (
int i = 0; i < triangles.size(); ++i )
424 output->values[i].
set( D_TRUE );
428 output->values[i].set( D_FALSE );
435 std::shared_ptr<QgsMeshMemoryDataset> QgsMeshCalcUtils::number(
double val,
double time )
const
437 Q_ASSERT( isValid() );
439 std::shared_ptr<QgsMeshMemoryDataset> output = createMemoryDataset( mOutputType );
443 if ( std::isnan( val ) )
446 memset( output->active.data(), 0,
static_cast<size_t>( output->active.size() ) *
sizeof(
int ) );
450 for (
int i = 0; i < output->values.size(); ++i )
452 output->values[i].set( val );
461 Q_ASSERT( isValid() );
464 std::shared_ptr<QgsMeshMemoryDataset> output = number( val, mTimes[0] );
471 Q_ASSERT( isValid() );
472 number( group1, 1.0 );
477 Q_ASSERT( isValid() );
478 number( group1, D_NODATA );
482 std::shared_ptr<QgsMeshMemoryDataset> QgsMeshCalcUtils::copy(
483 std::shared_ptr<const QgsMeshMemoryDataset> dataset0
486 Q_ASSERT( isValid() );
487 Q_ASSERT( dataset0 );
489 std::shared_ptr<QgsMeshMemoryDataset> output = std::make_shared<QgsMeshMemoryDataset>();
490 output->values = dataset0->values;
491 output->active = dataset0->active;
492 output->time = dataset0->time;
493 output->valid = dataset0->valid;
499 Q_ASSERT( isValid() );
501 std::shared_ptr<const QgsMeshMemoryDatasetGroup> group2 = group( groupName );
504 if ( group2->datasetCount() == 1 )
507 std::shared_ptr<const QgsMeshMemoryDataset> o0 = group2->constDataset( 0 );
508 std::shared_ptr<QgsMeshMemoryDataset> output = copy( o0 );
513 for (
int output_index = 0; output_index < group2->datasetCount(); ++output_index )
515 std::shared_ptr<const QgsMeshMemoryDataset> o0 = group2->constDataset( output_index );
518 ( ( o0->time >= mTimes.first() ) && ( o0->time <= mTimes.last() ) )
521 std::shared_ptr<QgsMeshMemoryDataset> output = copy( o0 );
530 Q_ASSERT( isValid() );
535 std::shared_ptr<QgsMeshMemoryDataset> o = group2.
memoryDatasets[i];
544 Q_ASSERT( isValid() );
550 const std::shared_ptr<QgsMeshMemoryDataset> o0 = group1.
memoryDatasets[0];
554 std::shared_ptr<QgsMeshMemoryDataset> o = copy( o0 );
563 std::shared_ptr<QgsMeshMemoryDataset> QgsMeshCalcUtils::canditateDataset(
565 int datasetIndex )
const
567 Q_ASSERT( isValid() );
581 std::shared_ptr<const QgsMeshMemoryDataset> QgsMeshCalcUtils::constCandidateDataset(
583 int datasetIndex )
const
585 Q_ASSERT( isValid() );
599 int QgsMeshCalcUtils::datasetCount(
603 Q_ASSERT( isValid() );
607 return mTimes.size();
616 std::function<
double(
double )> func )
const
618 Q_ASSERT( isValid() );
620 for (
int time_index = 0; time_index < group.
datasetCount(); ++time_index )
622 std::shared_ptr<QgsMeshMemoryDataset> output = canditateDataset( group, time_index );
624 for (
int n = 0; n < output->values.size(); ++n )
626 double val1 = output->values[n].scalar();
627 double res_val = D_NODATA;
628 if ( !std::isnan( val1 ) )
629 res_val = func( val1 );
630 output->values[n] = res_val;
641 std::function<
double(
double,
double )> func )
const
643 Q_ASSERT( isValid() );
646 expand( group1, group2 );
648 for (
int time_index = 0; time_index < datasetCount( group1, group2 ); ++time_index )
650 std::shared_ptr<QgsMeshMemoryDataset> o1 = canditateDataset( group1, time_index );
651 std::shared_ptr<const QgsMeshMemoryDataset> o2 = constCandidateDataset( group2, time_index );
653 for (
int n = 0; n < o2->values.size(); ++n )
655 double val1 = o1->values[n].scalar();
656 double val2 = o2->values[n].scalar();
657 double res_val = D_NODATA;
658 if ( !std::isnan( val1 ) && !std::isnan( val2 ) )
659 res_val = func( val1, val2 );
660 o1->values[n] = res_val;
671 void QgsMeshCalcUtils::funcAggr(
673 std::function<
double( QVector<double>& )> func
676 Q_ASSERT( isValid() );
681 output->time = mTimes[0];
682 for (
int n = 0; n < mMeshLayer->dataProvider()->vertexCount(); ++n )
684 QVector < double > vals;
685 for (
int datasetIndex = 0; datasetIndex < group1.
datasetCount(); ++datasetIndex )
687 const std::shared_ptr<QgsMeshMemoryDataset> o1 = canditateDataset( group1, datasetIndex );
689 double val1 = o1->values[n].scalar();
693 if ( !std::isnan( val1 ) )
695 vals.push_back( val1 );
699 double res_val = D_NODATA;
700 if ( !vals.isEmpty() )
702 res_val = func( vals );
705 output->values[n] = res_val;
718 output->time = mTimes[0];
720 int facesCount = mMeshLayer->dataProvider()->faceCount();
721 output->values.resize( facesCount );
723 for (
int n = 0; n < mMeshLayer->dataProvider()->faceCount(); ++n )
725 QVector < double > vals;
726 for (
int datasetIndex = 0; datasetIndex < group1.
datasetCount(); ++datasetIndex )
728 const std::shared_ptr<QgsMeshMemoryDataset> o1 = canditateDataset( group1, datasetIndex );
729 double val1 = o1->values[n].scalar();
730 if ( !std::isnan( val1 ) )
732 vals.push_back( val1 );
736 double res_val = D_NODATA;
737 if ( !vals.isEmpty() )
739 res_val = func( vals );
742 output->values[n] = res_val;
753 Q_ASSERT( mMeshLayer->triangularMesh() );
754 return mMeshLayer->triangularMesh();
757 const QgsMesh *QgsMeshCalcUtils::nativeMesh()
const
760 Q_ASSERT( mMeshLayer->nativeMesh() );
761 return mMeshLayer->nativeMesh();
764 void QgsMeshCalcUtils::updateMesh()
const
766 if ( ! mMeshLayer->nativeMesh() )
769 mMeshLayer->updateTriangularMesh();
782 Q_ASSERT( isValid() );
785 expand( trueGroup, condition );
786 expand( trueGroup, falseGroup );
791 for (
int time_index = 0; time_index < trueGroup.
datasetCount(); ++time_index )
793 std::shared_ptr<QgsMeshMemoryDataset> true_o = canditateDataset( trueGroup, time_index );
794 std::shared_ptr<const QgsMeshMemoryDataset> false_o = constCandidateDataset( falseGroup, time_index );
795 std::shared_ptr<const QgsMeshMemoryDataset> condition_o = constCandidateDataset( condition, time_index );
796 for (
int n = 0; n < true_o->values.size(); ++n )
798 double conditionValue = condition_o->values[n].scalar();
799 double resultValue = D_NODATA;
800 if ( !std::isnan( conditionValue ) )
803 resultValue = true_o->values[n].scalar();
805 resultValue = false_o->values[n].scalar();
807 true_o->values[n] = resultValue;
814 activate( true_o, condition_o );
822 Q_ASSERT( isValid() );
826 for (
int datasetIndex = 0; datasetIndex < group.
datasetCount(); ++datasetIndex )
828 std::shared_ptr<QgsMeshMemoryDataset> o1 = canditateDataset( group, datasetIndex );
836 void QgsMeshCalcUtils::activate(
837 std::shared_ptr<QgsMeshMemoryDataset> dataset,
838 std::shared_ptr<const QgsMeshMemoryDataset> refDataset
842 Q_ASSERT( isValid() );
846 for (
int idx = 0; idx < mMeshLayer->dataProvider()->faceCount(); ++idx )
848 if ( refDataset && !refDataset->active.isEmpty() && ( !refDataset->active[idx] ) )
850 dataset->active[idx] =
false;
854 if ( !dataset->active[idx] )
861 bool isActive =
true;
862 for (
int j = 0; j < face.size(); ++j )
864 if ( std::isnan( dataset->values[face[j]].scalar() ) )
870 dataset->active[idx] = isActive;
874 double QgsMeshCalcUtils::ffilter(
double val1,
double filter )
const
876 Q_ASSERT( !std::isnan( val1 ) );
884 double QgsMeshCalcUtils::fadd(
double val1,
double val2 )
const
886 Q_ASSERT( !std::isnan( val1 ) );
887 Q_ASSERT( !std::isnan( val2 ) );
892 double QgsMeshCalcUtils::fsubtract(
double val1,
double val2 )
const
894 Q_ASSERT( !std::isnan( val1 ) );
895 Q_ASSERT( !std::isnan( val2 ) );
900 double QgsMeshCalcUtils::fmultiply(
double val1,
double val2 )
const
902 Q_ASSERT( !std::isnan( val1 ) );
903 Q_ASSERT( !std::isnan( val2 ) );
908 double QgsMeshCalcUtils::fdivide(
double val1,
double val2 )
const
910 Q_ASSERT( !std::isnan( val1 ) );
911 Q_ASSERT( !std::isnan( val2 ) );
919 double QgsMeshCalcUtils::fpower(
double val1,
double val2 )
const
921 Q_ASSERT( !std::isnan( val1 ) );
922 Q_ASSERT( !std::isnan( val2 ) );
923 return pow( val1, val2 );
927 double QgsMeshCalcUtils::fequal(
double val1,
double val2 )
const
929 Q_ASSERT( !std::isnan( val1 ) );
930 Q_ASSERT( !std::isnan( val2 ) );
942 double QgsMeshCalcUtils::fnotEqual(
double val1,
double val2 )
const
944 Q_ASSERT( !std::isnan( val1 ) );
945 Q_ASSERT( !std::isnan( val2 ) );
957 double QgsMeshCalcUtils::fgreaterThan(
double val1,
double val2 )
const
959 Q_ASSERT( !std::isnan( val1 ) );
960 Q_ASSERT( !std::isnan( val2 ) );
972 double QgsMeshCalcUtils::flesserThan(
double val1,
double val2 )
const
974 Q_ASSERT( !std::isnan( val1 ) );
975 Q_ASSERT( !std::isnan( val2 ) );
987 double QgsMeshCalcUtils::flesserEqual(
double val1,
double val2 )
const
989 Q_ASSERT( !std::isnan( val1 ) );
990 Q_ASSERT( !std::isnan( val2 ) );
1002 double QgsMeshCalcUtils::fgreaterEqual(
double val1,
double val2 )
const
1004 Q_ASSERT( !std::isnan( val1 ) );
1005 Q_ASSERT( !std::isnan( val2 ) );
1018 double QgsMeshCalcUtils::flogicalAnd(
double val1,
double val2 )
const
1020 Q_ASSERT( !std::isnan( val1 ) );
1021 Q_ASSERT( !std::isnan( val2 ) );
1024 if ( bval1 && bval2 )
1031 double QgsMeshCalcUtils::flogicalOr(
double val1,
double val2 )
const
1033 Q_ASSERT( !std::isnan( val1 ) );
1034 Q_ASSERT( !std::isnan( val2 ) );
1037 if ( bval1 || bval2 )
1044 double QgsMeshCalcUtils::flogicalNot(
double val1 )
const
1046 Q_ASSERT( !std::isnan( val1 ) );
1055 double QgsMeshCalcUtils::fchangeSign(
double val1 )
const
1057 Q_ASSERT( !std::isnan( val1 ) );
1061 double QgsMeshCalcUtils::fmin(
double val1,
double val2 )
const
1063 Q_ASSERT( !std::isnan( val1 ) );
1075 double QgsMeshCalcUtils::fmax(
double val1,
double val2 )
const
1077 Q_ASSERT( !std::isnan( val1 ) );
1078 Q_ASSERT( !std::isnan( val2 ) );
1090 double QgsMeshCalcUtils::fabs(
double val1 )
const
1092 Q_ASSERT( !std::isnan( val1 ) );
1104 double QgsMeshCalcUtils::fsumAggregated( QVector<double> &vals )
const
1106 Q_ASSERT( !vals.contains( D_NODATA ) );
1107 Q_ASSERT( !vals.isEmpty() );
1108 return std::accumulate( vals.begin(), vals.end(), 0.0 );
1111 double QgsMeshCalcUtils::fminimumAggregated( QVector<double> &vals )
const
1113 Q_ASSERT( !vals.contains( D_NODATA ) );
1114 Q_ASSERT( !vals.isEmpty() );
1115 return *std::min_element( vals.begin(), vals.end() );
1118 double QgsMeshCalcUtils::fmaximumAggregated( QVector<double> &vals )
const
1120 Q_ASSERT( !vals.contains( D_NODATA ) );
1121 Q_ASSERT( !vals.isEmpty() );
1122 return *std::max_element( vals.begin(), vals.end() );
1125 double QgsMeshCalcUtils::faverageAggregated( QVector<double> &vals )
const
1127 Q_ASSERT( !vals.contains( D_NODATA ) );
1128 Q_ASSERT( !vals.isEmpty() );
1129 return fsumAggregated( vals ) / vals.size();
1134 return func1( group1, std::bind( & QgsMeshCalcUtils::flogicalNot,
this, std::placeholders::_1 ) );
1139 return func1( group1, std::bind( & QgsMeshCalcUtils::fchangeSign,
this, std::placeholders::_1 ) );
1144 return func1( group1, std::bind( & QgsMeshCalcUtils::fabs,
this, std::placeholders::_1 ) );
1149 return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fadd,
this, std::placeholders::_1, std::placeholders::_2 ) );
1154 return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fsubtract,
this, std::placeholders::_1, std::placeholders::_2 ) );
1159 return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fmultiply,
this, std::placeholders::_1, std::placeholders::_2 ) );
1164 return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fdivide,
this, std::placeholders::_1, std::placeholders::_2 ) );
1169 return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fpower,
this, std::placeholders::_1, std::placeholders::_2 ) );
1174 return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fequal,
this, std::placeholders::_1, std::placeholders::_2 ) );
1179 return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fnotEqual,
this, std::placeholders::_1, std::placeholders::_2 ) );
1184 return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fgreaterThan,
this, std::placeholders::_1, std::placeholders::_2 ) );
1189 return func2( group1, group2, std::bind( & QgsMeshCalcUtils::flesserThan,
this, std::placeholders::_1, std::placeholders::_2 ) );
1194 return func2( group1, group2, std::bind( & QgsMeshCalcUtils::flesserEqual,
this, std::placeholders::_1, std::placeholders::_2 ) );
1199 return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fgreaterEqual,
this, std::placeholders::_1, std::placeholders::_2 ) );
1204 return func2( group1, group2, std::bind( & QgsMeshCalcUtils::flogicalAnd,
this, std::placeholders::_1, std::placeholders::_2 ) );
1209 return func2( group1, group2, std::bind( & QgsMeshCalcUtils::flogicalOr,
this, std::placeholders::_1, std::placeholders::_2 ) );
1214 return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fmin,
this, std::placeholders::_1, std::placeholders::_2 ) );
1219 return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fmax,
this, std::placeholders::_1, std::placeholders::_2 ) );
1224 QHash<QString, int> names;
1226 for (
int groupId : groupIndexes )
1229 const QString name = meta.
name();
1230 names[ name ] = groupId;
1232 for (
const QString &datasetGroupName : usedGroupNames )
1234 if ( names.contains( datasetGroupName ) )
1236 int groupId = names.value( datasetGroupName );
1254 populateSpatialFilter( filter, extent );
1255 return func2( group1, filter, std::bind( & QgsMeshCalcUtils::ffilter,
this, std::placeholders::_1, std::placeholders::_2 ) );
1261 populateMaskFilter( filter, mask );
1262 return func2( group1, filter, std::bind( & QgsMeshCalcUtils::ffilter,
this, std::placeholders::_1, std::placeholders::_2 ) );
1267 return funcAggr( group1, std::bind( & QgsMeshCalcUtils::fsumAggregated,
this, std::placeholders::_1 ) );
1272 return funcAggr( group1, std::bind( & QgsMeshCalcUtils::fminimumAggregated,
this, std::placeholders::_1 ) );
1277 return funcAggr( group1, std::bind( & QgsMeshCalcUtils::fmaximumAggregated,
this, std::placeholders::_1 ) );
1282 return funcAggr( group1, std::bind( & QgsMeshCalcUtils::faverageAggregated,
this, std::placeholders::_1 ) );