QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsmeshcalcutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmeshcalcutils.cpp
3  --------------------
4  begin : December 18th, 2018
5  copyright : (C) 2018 by Peter Petrik
6  email : zilolv at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
18 
19 #include <QFileInfo>
20 
21 #include "qgsmeshcalcnode.h"
22 #include "qgsmeshcalcutils.h"
23 #include "qgsmeshmemorydataprovider.h"
24 #include "qgstriangularmesh.h"
25 #include "qgsmapsettings.h"
26 #include "qgsmeshlayerutils.h"
27 #include "qgsmeshlayerrenderer.h"
28 #include "qgsproject.h"
29 
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();
33 
34 std::shared_ptr<QgsMeshMemoryDatasetGroup> QgsMeshCalcUtils::createMemoryDatasetGroup( const QString &datasetGroupName, const QgsInterval &relativeTime ) const
35 {
36  std::shared_ptr<QgsMeshMemoryDatasetGroup> grp;
37  const QList<int> &indexes = mMeshLayer->datasetGroupsIndexes();
38  for ( int groupIndex : indexes )
39  {
40  const QgsMeshDatasetGroupMetadata meta = mMeshLayer->datasetGroupMetadata( groupIndex );
41  const QString name = meta.name();
42  if ( name == datasetGroupName )
43  {
44  // we need to convert the native type to the requested type
45  // only possibility that cannot happen is to convert vertex dataset to
46  // face dataset. This would suggest bug in determineResultDataType()
47  Q_ASSERT( !( ( meta.dataType() == QgsMeshDatasetGroupMetadata::DataOnVertices ) && ( mOutputType == QgsMeshDatasetGroupMetadata::DataOnFaces ) ) );
48 
49  grp = std::make_shared<QgsMeshMemoryDatasetGroup>();
50  grp->setIsScalar( meta.isScalar() );
51  grp->setDataType( mOutputType );
52  grp->setMinimumMaximum( meta.minimum(), meta.maximum() );
53  grp->setName( meta.name() );
54 
55  if ( !relativeTime.isValid() )
56  {
57  for ( int index = 0; index < mMeshLayer->datasetCount( groupIndex ); ++index )
58  grp->addDataset( createMemoryDataset( QgsMeshDatasetIndex( groupIndex, index ) ) );
59  }
60  else
61  {
62  QgsMeshDatasetIndex datasetIndex = mMeshLayer->datasetIndexAtRelativeTime( relativeTime, groupIndex );
63  if ( datasetIndex.isValid() )
64  grp->addDataset( createMemoryDataset( datasetIndex ) );
65  }
66 
67 
68  break;
69  }
70  }
71 
72  return grp;
73 }
74 
75 std::shared_ptr<QgsMeshMemoryDataset> QgsMeshCalcUtils::createMemoryDataset( const QgsMeshMemoryDatasetGroup &grp ) const
76 {
77  return createMemoryDataset( grp.dataType() );
78 }
79 
80 std::shared_ptr<QgsMeshMemoryDataset> QgsMeshCalcUtils::createMemoryDataset( const QgsMeshDatasetIndex &datasetIndex ) const
81 {
82  const QgsMeshDataProvider *dp = mMeshLayer->dataProvider();
83  int groupIndex = datasetIndex.group();
84  const auto meta = mMeshLayer->datasetGroupMetadata( groupIndex );
85 
86  int nativeCount = ( meta.dataType() == QgsMeshDatasetGroupMetadata::DataOnVertices ) ? dp->vertexCount() : dp->faceCount();
87  int resultCount = ( mOutputType == QgsMeshDatasetGroupMetadata::DataOnVertices ) ? dp->vertexCount() : dp->faceCount();
88 
89  const QgsMeshDatasetMetadata dsMeta = mMeshLayer->datasetMetadata( datasetIndex );
90  std::shared_ptr<QgsMeshMemoryDataset> ds = createMemoryDataset( mOutputType );
91  ds->maximum = dsMeta.maximum();
92  ds->minimum = dsMeta.minimum();
93  ds->time = dsMeta.time();
94  ds->valid = dsMeta.isValid();
95 
96  // the function already averages volume datasets to face dataset values
97  QgsMeshDataBlock block = QgsMeshLayerUtils::datasetValues( mMeshLayer, datasetIndex, 0, nativeCount );
98  // it is 2D memory datasets, so it shouldn't be invalid
99  Q_ASSERT( block.isValid() );
100  Q_ASSERT( block.count() == nativeCount );
101 
102  // for data on faces, there could be request to interpolate the data to vertices
104  {
105  if ( meta.isScalar() )
106  {
107  QVector<double> data =
108  QgsMeshLayerUtils::interpolateFromFacesData(
109  block.values(),
110  nativeMesh(),
111  triangularMesh(),
112  nullptr,
114  );
115  Q_ASSERT( data.size() == resultCount );
116  for ( int valueIndex = 0; valueIndex < resultCount; ++valueIndex )
117  ds->values[valueIndex] = QgsMeshDatasetValue( data[valueIndex] );
118  }
119  else
120  {
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 )
125  {
126  x[value_i] = buf[2 * value_i];
127  y[value_i] = buf[2 * value_i + 1];
128  }
129 
130  QVector<double> dataX =
131  QgsMeshLayerUtils::interpolateFromFacesData(
132  x,
133  mMeshLayer->nativeMesh(),
134  mMeshLayer->triangularMesh(),
135  nullptr,
136  mMeshLayer->rendererSettings().scalarSettings( groupIndex ).dataResamplingMethod()
137  );
138  Q_ASSERT( dataX.size() == resultCount );
139  QVector<double> dataY =
140  QgsMeshLayerUtils::interpolateFromFacesData(
141  y,
142  mMeshLayer->nativeMesh(),
143  mMeshLayer->triangularMesh(),
144  nullptr,
145  mMeshLayer->rendererSettings().scalarSettings( groupIndex ).dataResamplingMethod()
146  );
147 
148  Q_ASSERT( dataY.size() == resultCount );
149 
150  for ( int value_i = 0; value_i < resultCount; ++value_i )
151  {
152  ds->values[value_i] = QgsMeshDatasetValue( dataX[value_i], dataY[value_i] );
153  }
154  }
155  }
156  else
157  {
158  for ( int value_i = 0; value_i < resultCount; ++value_i )
159  ds->values[value_i] = block.value( value_i );
160  }
161 
162  if ( mOutputType == QgsMeshDatasetGroupMetadata::DataOnVertices )
163  {
164  const QgsMeshDataBlock active = mMeshLayer->areFacesActive( datasetIndex, 0, dp->faceCount() );
165  Q_ASSERT( active.count() == dp->faceCount() );
166  for ( int value_i = 0; value_i < dp->faceCount(); ++value_i )
167  ds->active[value_i] = active.active( value_i );
168  }
169 
170  return ds;
171 }
172 
173 std::shared_ptr<QgsMeshMemoryDataset> QgsMeshCalcUtils::createMemoryDataset( const QgsMeshDatasetGroupMetadata::DataType type ) const
174 {
175  Q_ASSERT( type != QgsMeshDatasetGroupMetadata::DataOnVolumes );
176 
177  std::shared_ptr<QgsMeshMemoryDataset> ds = std::make_shared<QgsMeshMemoryDataset>();
179  {
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 ) );
183  }
184  else
185  {
186  ds->values.resize( mMeshLayer->dataProvider()->faceCount() );
187  }
188  ds->valid = true;
189  return ds;
190 }
191 
192 QgsMeshCalcUtils:: QgsMeshCalcUtils( QgsMeshLayer *layer,
193  const QStringList &usedGroupNames,
194  double startTime,
195  double endTime )
196  : mMeshLayer( layer )
197  , mIsValid( false )
198 {
199  // Layer must be valid
200  if ( !mMeshLayer || !mMeshLayer->dataProvider() )
201  return;
202 
203  // Resolve output type of the calculation
204  mOutputType = determineResultDataType( layer, usedGroupNames );
205 
206  // Data on edges are not implemented
207  if ( mOutputType == QgsMeshDatasetGroupMetadata::DataOnEdges )
208  return;
209 
210  // Support for meshes with edges are not implemented
211  if ( mMeshLayer->dataProvider()->contains( QgsMesh::ElementType::Edge ) )
212  return;
213 
214  // First populate group's names map and see if we have all groups present
215  // And basically fetch all data from any mesh provider to memory
216  for ( const QString &groupName : usedGroupNames )
217  {
218  std::shared_ptr<QgsMeshMemoryDatasetGroup> ds = createMemoryDatasetGroup( groupName );
219  if ( !ds )
220  return;
221 
222  mDatasetGroupMap.insert( groupName, ds );
223  }
224 
225  // Now populate used times and check that all datasets do have some times
226  // OR just one time (== one output)
227  bool timesPopulated = false;
228  const QList<std::shared_ptr<QgsMeshMemoryDatasetGroup>> vals = mDatasetGroupMap.values();
229  for ( const std::shared_ptr<QgsMeshMemoryDatasetGroup> &ds : vals )
230  {
231  if ( ds->datasetCount() == 0 )
232  {
233  // dataset must have at least 1 output
234  return;
235  }
236 
237  if ( ds->datasetCount() > 1 )
238  {
239  if ( timesPopulated )
240  {
241  if ( ds->datasetCount() != mTimes.size() )
242  {
243  // different number of datasets in the groups
244  return;
245  }
246  }
247 
248  for ( int datasetIndex = 0; datasetIndex < ds->datasetCount(); ++datasetIndex )
249  {
250  std::shared_ptr<const QgsMeshMemoryDataset> o = ds->constDataset( datasetIndex );
251  if ( timesPopulated )
252  {
253  if ( !qgsDoubleNear( mTimes[datasetIndex], o->time ) )
254  {
255  // error, the times in different datasets differ
256  return;
257  }
258  }
259  else
260  {
261  mTimes.append( o->time );
262  }
263  }
264 
265  timesPopulated = true;
266  }
267  }
268 
269  // case of all group are not time varying or usedGroupNames is empty
270  if ( mTimes.isEmpty() )
271  {
272  mTimes.push_back( 0.0 );
273  }
274  else
275  {
276  // filter out times we do not need to speed up calculations
277  for ( QVector<double>::iterator it = mTimes.begin(); it != mTimes.end(); )
278  {
279  if ( qgsDoubleNear( *it, startTime ) ||
280  qgsDoubleNear( *it, endTime ) ||
281  ( ( *it >= startTime ) && ( *it <= endTime ) ) )
282  ++it;
283  else
284  it = mTimes.erase( it );
285  }
286  }
287 
288  // check that all datasets are of the same type
289  for ( const std::shared_ptr<QgsMeshMemoryDatasetGroup> &ds : vals )
290  {
291  if ( ds->dataType() != mOutputType )
292  return;
293  }
294 
295  // All is valid!
296  mIsValid = true;
297 }
298 
299 QgsMeshCalcUtils::QgsMeshCalcUtils( QgsMeshLayer *layer, const QStringList &usedGroupNames, const QgsInterval &relativeTime )
300  : mMeshLayer( layer )
301  , mIsValid( false )
302 {
303  // Layer must be valid
304  if ( !mMeshLayer || !mMeshLayer->dataProvider() )
305  return;
306 
307  // Resolve output type of the calculation
308  mOutputType = determineResultDataType( layer, usedGroupNames );
309 
310  // Data on edges are not implemented
311  if ( mOutputType == QgsMeshDatasetGroupMetadata::DataOnEdges )
312  return;
313 
314  // Support for meshes with edges are not implemented
315  if ( mMeshLayer->dataProvider()->contains( QgsMesh::ElementType::Edge ) )
316  return;
317 
318  QgsInterval usedInterval = relativeTime;
319  if ( !usedInterval.isValid() )
320  usedInterval = QgsInterval( 0 );
321 
322  for ( const QString &groupName : usedGroupNames )
323  {
324  std::shared_ptr<QgsMeshMemoryDatasetGroup> ds = createMemoryDatasetGroup( groupName, relativeTime );
325  if ( !ds || ds->memoryDatasets.isEmpty() )
326  return;
327 
328  mDatasetGroupMap.insert( groupName, ds );
329  }
330 
331  mTimes.push_back( usedInterval.hours() );
332 
333  mIsValid = true;
334 }
335 
336 bool QgsMeshCalcUtils::isValid() const
337 {
338  return mIsValid;
339 }
340 
341 const QgsMeshLayer *QgsMeshCalcUtils::layer() const
342 {
343  return mMeshLayer;
344 }
345 
346 std::shared_ptr<const QgsMeshMemoryDatasetGroup> QgsMeshCalcUtils::group( const QString &datasetName ) const
347 {
348  return mDatasetGroupMap[datasetName];
349 }
350 
351 void QgsMeshCalcUtils::populateSpatialFilter( QgsMeshMemoryDatasetGroup &filter, const QgsRectangle &extent ) const
352 {
353  Q_ASSERT( mOutputType != QgsMeshDatasetGroupMetadata::DataOnVolumes );
354 
355  filter.clearDatasets();
356 
357  std::shared_ptr<QgsMeshMemoryDataset> output = createMemoryDataset( filter );
358  output->time = mTimes[0];
359 
360  const QList<int> faceIndexesForRectangle = triangularMesh()->faceIndexesForRectangle( extent );
361  const QVector<int> trianglesToNativeFaces = triangularMesh()->trianglesToNativeFaces();
362 
363  if ( mOutputType == QgsMeshDatasetGroupMetadata::DataOnVertices )
364  {
365  for ( const int faceIndex : faceIndexesForRectangle )
366  {
367  const int nativeIndex = trianglesToNativeFaces[faceIndex];
368  const QgsMeshFace face = nativeMesh()->face( nativeIndex );
369  for ( const int vertexIndex : face )
370  {
371  output->values[vertexIndex].set( D_TRUE );
372  }
373  }
374  }
375  else
376  {
377  for ( const int faceIndex : faceIndexesForRectangle )
378  {
379  const int nativeIndex = trianglesToNativeFaces[faceIndex];
380  output->values[nativeIndex].set( D_TRUE );
381  }
382  }
383  filter.addDataset( output );
384 }
385 
386 
387 void QgsMeshCalcUtils::populateMaskFilter( QgsMeshMemoryDatasetGroup &filter, const QgsGeometry &mask ) const
388 {
389  Q_ASSERT( mOutputType != QgsMeshDatasetGroupMetadata::DataOnVolumes );
390 
391  filter.clearDatasets();
392  std::shared_ptr<QgsMeshMemoryDataset> output = createMemoryDataset( filter );
393  output->time = mTimes[0];
394 
395  const QVector<QgsMeshVertex> &vertices = triangularMesh()->vertices();
396 
397  if ( mOutputType == QgsMeshDatasetGroupMetadata::DataOnVertices )
398  {
399  int nativeVertexCount = mMeshLayer->dataProvider()->vertexCount();
400 
401  for ( int i = 0; i < nativeVertexCount; ++i )
402  {
403  const QgsPointXY point( vertices[i] );
404  if ( mask.contains( &point ) )
405  {
406  output->values[i].set( D_TRUE );
407  }
408  else
409  {
410  output->values[i].set( D_FALSE );
411  }
412  }
413  }
414  else
415  {
416  const QVector<QgsMeshFace> &triangles = triangularMesh()->triangles();
417  for ( int i = 0; i < triangles.size(); ++i )
418  {
419  const QgsMeshFace face = triangles[i];
420  const QgsGeometry geom = QgsMeshUtils::toGeometry( face, vertices );
421  const QgsRectangle bbox = geom.boundingBox();
422  if ( mask.intersects( bbox ) )
423  {
424  output->values[i].set( D_TRUE );
425  }
426  else
427  {
428  output->values[i].set( D_FALSE );
429  }
430  }
431  }
432  filter.addDataset( output );
433 }
434 
435 std::shared_ptr<QgsMeshMemoryDataset> QgsMeshCalcUtils::number( double val, double time ) const
436 {
437  Q_ASSERT( isValid() );
438 
439  std::shared_ptr<QgsMeshMemoryDataset> output = createMemoryDataset( mOutputType );
440  output->time = time;
441 
442  // by default it is initialized to 1
443  if ( std::isnan( val ) )
444  {
445  if ( mOutputType == QgsMeshDatasetGroupMetadata::DataOnVertices )
446  memset( output->active.data(), 0, static_cast<size_t>( output->active.size() ) * sizeof( int ) );
447  }
448  else
449  {
450  for ( int i = 0; i < output->values.size(); ++i ) // Using for loop we are initializing
451  {
452  output->values[i].set( val );
453  }
454  }
455 
456  return output;
457 }
458 
459 void QgsMeshCalcUtils::number( QgsMeshMemoryDatasetGroup &group1, double val ) const
460 {
461  Q_ASSERT( isValid() );
462 
463  group1.clearDatasets();
464  std::shared_ptr<QgsMeshMemoryDataset> output = number( val, mTimes[0] );
465  group1.addDataset( output );
466 }
467 
468 
469 void QgsMeshCalcUtils::ones( QgsMeshMemoryDatasetGroup &group1 ) const
470 {
471  Q_ASSERT( isValid() );
472  number( group1, 1.0 );
473 }
474 
475 void QgsMeshCalcUtils::nodata( QgsMeshMemoryDatasetGroup &group1 ) const
476 {
477  Q_ASSERT( isValid() );
478  number( group1, D_NODATA );
479 }
480 
481 
482 std::shared_ptr<QgsMeshMemoryDataset> QgsMeshCalcUtils::copy(
483  std::shared_ptr<const QgsMeshMemoryDataset> dataset0
484 ) const
485 {
486  Q_ASSERT( isValid() );
487  Q_ASSERT( dataset0 );
488 
489  std::shared_ptr<QgsMeshMemoryDataset> output = std::make_shared<QgsMeshMemoryDataset>();
490  output->values = dataset0->values; //deep copy
491  output->active = dataset0->active; //deep copy
492  output->time = dataset0->time;
493  output->valid = dataset0->valid;
494  return output;
495 }
496 
497 void QgsMeshCalcUtils::copy( QgsMeshMemoryDatasetGroup &group1, const QString &groupName ) const
498 {
499  Q_ASSERT( isValid() );
500 
501  std::shared_ptr<const QgsMeshMemoryDatasetGroup> group2 = group( groupName );
502  Q_ASSERT( group2 );
503 
504  if ( group2->datasetCount() == 1 )
505  {
506  // Always copy
507  std::shared_ptr<const QgsMeshMemoryDataset> o0 = group2->constDataset( 0 );
508  std::shared_ptr<QgsMeshMemoryDataset> output = copy( o0 );
509  group1.addDataset( output );
510  }
511  else
512  {
513  for ( int output_index = 0; output_index < group2->datasetCount(); ++output_index )
514  {
515  std::shared_ptr<const QgsMeshMemoryDataset> o0 = group2->constDataset( output_index );
516  if ( qgsDoubleNear( o0->time, mTimes.first() ) ||
517  qgsDoubleNear( o0->time, mTimes.last() ) ||
518  ( ( o0->time >= mTimes.first() ) && ( o0->time <= mTimes.last() ) )
519  )
520  {
521  std::shared_ptr<QgsMeshMemoryDataset> output = copy( o0 );
522  group1.addDataset( output );
523  }
524  }
525  }
526 }
527 
528 void QgsMeshCalcUtils::transferDatasets( QgsMeshMemoryDatasetGroup &group1, QgsMeshMemoryDatasetGroup &group2 ) const
529 {
530  Q_ASSERT( isValid() );
531 
532  group1.clearDatasets();
533  for ( int i = 0; i < group2.datasetCount(); ++i )
534  {
535  std::shared_ptr<QgsMeshMemoryDataset> o = group2.memoryDatasets[i];
536  Q_ASSERT( o );
537  group1.addDataset( o );
538  }
539  group2.clearDatasets();
540 }
541 
542 void QgsMeshCalcUtils::expand( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const
543 {
544  Q_ASSERT( isValid() );
545 
546  if ( group2.datasetCount() > 1 )
547  {
548  if ( group1.datasetCount() == 1 )
549  {
550  const std::shared_ptr<QgsMeshMemoryDataset> o0 = group1.memoryDatasets[0];
551  Q_ASSERT( o0 );
552  for ( int i = 1; i < group2.datasetCount(); ++i )
553  {
554  std::shared_ptr<QgsMeshMemoryDataset> o = copy( o0 );
555  o->time = mTimes[i];
556  group1.addDataset( o );
557  }
558  }
559  }
560 }
561 
562 
563 std::shared_ptr<QgsMeshMemoryDataset> QgsMeshCalcUtils::canditateDataset(
565  int datasetIndex ) const
566 {
567  Q_ASSERT( isValid() );
568 
569  if ( group.datasetCount() > 1 )
570  {
571  Q_ASSERT( group.datasetCount() > datasetIndex );
572  return group.memoryDatasets[datasetIndex];
573  }
574  else
575  {
576  Q_ASSERT( group.datasetCount() == 1 );
577  return group.memoryDatasets[0];
578  }
579 }
580 
581 std::shared_ptr<const QgsMeshMemoryDataset> QgsMeshCalcUtils::constCandidateDataset(
582  const QgsMeshMemoryDatasetGroup &group,
583  int datasetIndex ) const
584 {
585  Q_ASSERT( isValid() );
586 
587  if ( group.datasetCount() > 1 )
588  {
589  Q_ASSERT( group.datasetCount() > datasetIndex );
590  return group.constDataset( datasetIndex );
591  }
592  else
593  {
594  Q_ASSERT( group.datasetCount() == 1 );
595  return group.constDataset( 0 );
596  }
597 }
598 
599 int QgsMeshCalcUtils::datasetCount(
600  const QgsMeshMemoryDatasetGroup &group1,
601  const QgsMeshMemoryDatasetGroup &group2 ) const
602 {
603  Q_ASSERT( isValid() );
604 
605  if ( ( group1.datasetCount() > 1 ) || ( group2.datasetCount() > 1 ) )
606  {
607  return mTimes.size();
608  }
609  else
610  {
611  return 1;
612  }
613 }
614 
615 void QgsMeshCalcUtils::func1( QgsMeshMemoryDatasetGroup &group,
616  std::function<double( double )> func ) const
617 {
618  Q_ASSERT( isValid() );
619 
620  for ( int time_index = 0; time_index < group.datasetCount(); ++time_index )
621  {
622  std::shared_ptr<QgsMeshMemoryDataset> output = canditateDataset( group, time_index );
623 
624  for ( int n = 0; n < output->values.size(); ++n )
625  {
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;
631  }
632 
634  activate( output );
635  }
636 }
637 
638 
639 void QgsMeshCalcUtils::func2( QgsMeshMemoryDatasetGroup &group1,
640  const QgsMeshMemoryDatasetGroup &group2,
641  std::function<double( double, double )> func ) const
642 {
643  Q_ASSERT( isValid() );
644  Q_ASSERT( group1.dataType() == group2.dataType() ); // we do not support mixed output types
645 
646  expand( group1, group2 );
647 
648  for ( int time_index = 0; time_index < datasetCount( group1, group2 ); ++time_index )
649  {
650  std::shared_ptr<QgsMeshMemoryDataset> o1 = canditateDataset( group1, time_index );
651  std::shared_ptr<const QgsMeshMemoryDataset> o2 = constCandidateDataset( group2, time_index );
652 
653  for ( int n = 0; n < o2->values.size(); ++n )
654  {
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;
661  }
662 
664  {
665  activate( o1, o2 );
666  }
667 
668  }
669 }
670 
671 void QgsMeshCalcUtils::funcAggr(
673  std::function<double( QVector<double>& )> func
674 ) const
675 {
676  Q_ASSERT( isValid() );
677 
679  {
680  std::shared_ptr<QgsMeshMemoryDataset> output = QgsMeshCalcUtils::createMemoryDataset( QgsMeshDatasetGroupMetadata::DataOnVertices );
681  output->time = mTimes[0];
682  for ( int n = 0; n < mMeshLayer->dataProvider()->vertexCount(); ++n )
683  {
684  QVector < double > vals;
685  for ( int datasetIndex = 0; datasetIndex < group1.datasetCount(); ++datasetIndex )
686  {
687  const std::shared_ptr<QgsMeshMemoryDataset> o1 = canditateDataset( group1, datasetIndex );
688 
689  double val1 = o1->values[n].scalar();
690  // ideally we should take only values from cells that are active.
691  // but the problem is that the node can be part of multiple cells,
692  // few active and few not, ...
693  if ( !std::isnan( val1 ) )
694  {
695  vals.push_back( val1 );
696  }
697  }
698 
699  double res_val = D_NODATA;
700  if ( !vals.isEmpty() )
701  {
702  res_val = func( vals );
703  }
704 
705  output->values[n] = res_val;
706  }
707 
708  // lets do activation purely on NODATA values as we did aggregation here
709  activate( output );
710 
711  group1.clearDatasets();
712  group1.addDataset( output );
713 
714  }
715  else
716  {
717  std::shared_ptr<QgsMeshMemoryDataset> output = QgsMeshCalcUtils::createMemoryDataset( QgsMeshDatasetGroupMetadata::DataOnFaces );
718  output->time = mTimes[0];
719 
720  int facesCount = mMeshLayer->dataProvider()->faceCount();
721  output->values.resize( facesCount );
722 
723  for ( int n = 0; n < mMeshLayer->dataProvider()->faceCount(); ++n )
724  {
725  QVector < double > vals;
726  for ( int datasetIndex = 0; datasetIndex < group1.datasetCount(); ++datasetIndex )
727  {
728  const std::shared_ptr<QgsMeshMemoryDataset> o1 = canditateDataset( group1, datasetIndex );
729  double val1 = o1->values[n].scalar();
730  if ( !std::isnan( val1 ) )
731  {
732  vals.push_back( val1 );
733  }
734  }
735 
736  double res_val = D_NODATA;
737  if ( !vals.isEmpty() )
738  {
739  res_val = func( vals );
740  }
741 
742  output->values[n] = res_val;
743  }
744 
745  group1.clearDatasets();
746  group1.addDataset( output );
747  }
748 }
749 
750 const QgsTriangularMesh *QgsMeshCalcUtils::triangularMesh() const
751 {
752  updateMesh();
753  Q_ASSERT( mMeshLayer->triangularMesh() );
754  return mMeshLayer->triangularMesh();
755 }
756 
757 const QgsMesh *QgsMeshCalcUtils::nativeMesh() const
758 {
759  updateMesh();
760  Q_ASSERT( mMeshLayer->nativeMesh() );
761  return mMeshLayer->nativeMesh();
762 }
763 
764 void QgsMeshCalcUtils::updateMesh() const
765 {
766  if ( ! mMeshLayer->nativeMesh() )
767  {
768  //calling this method creates the triangular mesh if it doesn't exist
769  mMeshLayer->updateTriangularMesh();
770  }
771 }
772 
773 QgsMeshDatasetGroupMetadata::DataType QgsMeshCalcUtils::outputType() const
774 {
775  return mOutputType;
776 }
777 
778 void QgsMeshCalcUtils::addIf( QgsMeshMemoryDatasetGroup &trueGroup,
779  const QgsMeshMemoryDatasetGroup &falseGroup,
780  const QgsMeshMemoryDatasetGroup &condition ) const
781 {
782  Q_ASSERT( isValid() );
783 
784  // Make sure we have enough outputs in the resulting dataset
785  expand( trueGroup, condition );
786  expand( trueGroup, falseGroup );
787 
788  Q_ASSERT( trueGroup.dataType() == falseGroup.dataType() ); // we do not support mixed output types
789  Q_ASSERT( trueGroup.dataType() == condition.dataType() ); // we do not support mixed output types
790 
791  for ( int time_index = 0; time_index < trueGroup.datasetCount(); ++time_index )
792  {
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 )
797  {
798  double conditionValue = condition_o->values[n].scalar();
799  double resultValue = D_NODATA;
800  if ( !std::isnan( conditionValue ) )
801  {
802  if ( qgsDoubleNear( conditionValue, D_TRUE ) )
803  resultValue = true_o->values[n].scalar();
804  else
805  resultValue = false_o->values[n].scalar();
806  }
807  true_o->values[n] = resultValue;
808  }
809 
811  {
812  // This is not ideal, as we do not check for true/false branch here in activate
813  // problem is that activate is on elements, but condition is on nodes...
814  activate( true_o, condition_o );
815  }
816  }
817 }
818 
819 
820 void QgsMeshCalcUtils::activate( QgsMeshMemoryDatasetGroup &group ) const
821 {
822  Q_ASSERT( isValid() );
823 
824  if ( mOutputType == QgsMeshDatasetGroupMetadata::DataOnVertices )
825  {
826  for ( int datasetIndex = 0; datasetIndex < group.datasetCount(); ++datasetIndex )
827  {
828  std::shared_ptr<QgsMeshMemoryDataset> o1 = canditateDataset( group, datasetIndex );
830  activate( o1 );
831  }
832  }
833  // Groups with data on faces do not have activate flags
834 }
835 
836 void QgsMeshCalcUtils::activate(
837  std::shared_ptr<QgsMeshMemoryDataset> dataset,
838  std::shared_ptr<const QgsMeshMemoryDataset> refDataset /*=0*/
839 ) const
840 {
841 
842  Q_ASSERT( isValid() );
843  Q_ASSERT( dataset );
844 
845  // Activate only faces that has some data and all vertices
846  for ( int idx = 0; idx < mMeshLayer->dataProvider()->faceCount(); ++idx )
847  {
848  if ( refDataset && !refDataset->active.isEmpty() && ( !refDataset->active[idx] ) )
849  {
850  dataset->active[idx] = false;
851  continue;
852  }
853 
854  if ( !dataset->active[idx] )
855  {
856  continue;
857  }
858 
859  QgsMeshFace face = nativeMesh()->face( idx );
860 
861  bool isActive = true; //ACTIVE
862  for ( int j = 0; j < face.size(); ++j )
863  {
864  if ( std::isnan( dataset->values[face[j]].scalar() ) )
865  {
866  isActive = false; //NOT ACTIVE
867  break;
868  }
869  }
870  dataset->active[idx] = isActive;
871  }
872 }
873 
874 double QgsMeshCalcUtils::ffilter( double val1, double filter ) const
875 {
876  Q_ASSERT( !std::isnan( val1 ) );
877 
878  if ( qgsDoubleNear( filter, D_TRUE ) )
879  return val1;
880  else
881  return D_NODATA;
882 }
883 
884 double QgsMeshCalcUtils::fadd( double val1, double val2 ) const
885 {
886  Q_ASSERT( !std::isnan( val1 ) );
887  Q_ASSERT( !std::isnan( val2 ) );
888  return val1 + val2;
889 
890 }
891 
892 double QgsMeshCalcUtils::fsubtract( double val1, double val2 ) const
893 {
894  Q_ASSERT( !std::isnan( val1 ) );
895  Q_ASSERT( !std::isnan( val2 ) );
896  return val1 - val2;
897 
898 }
899 
900 double QgsMeshCalcUtils::fmultiply( double val1, double val2 ) const
901 {
902  Q_ASSERT( !std::isnan( val1 ) );
903  Q_ASSERT( !std::isnan( val2 ) );
904  return val1 * val2;
905 
906 }
907 
908 double QgsMeshCalcUtils::fdivide( double val1, double val2 ) const
909 {
910  Q_ASSERT( !std::isnan( val1 ) );
911  Q_ASSERT( !std::isnan( val2 ) );
912  if ( qgsDoubleNear( val2, 0.0 ) )
913  return D_NODATA;
914  else
915  return val1 / val2;
916 
917 }
918 
919 double QgsMeshCalcUtils::fpower( double val1, double val2 ) const
920 {
921  Q_ASSERT( !std::isnan( val1 ) );
922  Q_ASSERT( !std::isnan( val2 ) );
923  return pow( val1, val2 );
924 
925 }
926 
927 double QgsMeshCalcUtils::fequal( double val1, double val2 ) const
928 {
929  Q_ASSERT( !std::isnan( val1 ) );
930  Q_ASSERT( !std::isnan( val2 ) );
931  if ( qgsDoubleNear( val1, val2 ) )
932  {
933  return D_TRUE;
934  }
935  else
936  {
937  return D_FALSE;
938  }
939 
940 }
941 
942 double QgsMeshCalcUtils::fnotEqual( double val1, double val2 ) const
943 {
944  Q_ASSERT( !std::isnan( val1 ) );
945  Q_ASSERT( !std::isnan( val2 ) );
946  if ( qgsDoubleNear( val1, val2 ) )
947  {
948  return D_FALSE;
949  }
950  else
951  {
952  return D_TRUE;
953  }
954 
955 }
956 
957 double QgsMeshCalcUtils::fgreaterThan( double val1, double val2 ) const
958 {
959  Q_ASSERT( !std::isnan( val1 ) );
960  Q_ASSERT( !std::isnan( val2 ) );
961  if ( val1 > val2 )
962  {
963  return D_TRUE;
964  }
965  else
966  {
967  return D_FALSE;
968  }
969 
970 }
971 
972 double QgsMeshCalcUtils::flesserThan( double val1, double val2 ) const
973 {
974  Q_ASSERT( !std::isnan( val1 ) );
975  Q_ASSERT( !std::isnan( val2 ) );
976  if ( val1 < val2 )
977  {
978  return D_TRUE;
979  }
980  else
981  {
982  return D_FALSE;
983  }
984 
985 }
986 
987 double QgsMeshCalcUtils::flesserEqual( double val1, double val2 ) const
988 {
989  Q_ASSERT( !std::isnan( val1 ) );
990  Q_ASSERT( !std::isnan( val2 ) );
991  if ( val1 <= val2 )
992  {
993  return D_TRUE;
994  }
995  else
996  {
997  return D_FALSE;
998  }
999 
1000 }
1001 
1002 double QgsMeshCalcUtils::fgreaterEqual( double val1, double val2 ) const
1003 {
1004  Q_ASSERT( !std::isnan( val1 ) );
1005  Q_ASSERT( !std::isnan( val2 ) );
1006  if ( val1 >= val2 )
1007  {
1008  return D_TRUE;
1009  }
1010  else
1011  {
1012  return D_FALSE;
1013  }
1014 
1015 }
1016 
1017 
1018 double QgsMeshCalcUtils::flogicalAnd( double val1, double val2 ) const
1019 {
1020  Q_ASSERT( !std::isnan( val1 ) );
1021  Q_ASSERT( !std::isnan( val2 ) );
1022  bool bval1 = qgsDoubleNear( val1, D_TRUE );
1023  bool bval2 = qgsDoubleNear( val2, D_TRUE );
1024  if ( bval1 && bval2 )
1025  return D_TRUE;
1026  else
1027  return D_FALSE;
1028 
1029 }
1030 
1031 double QgsMeshCalcUtils::flogicalOr( double val1, double val2 ) const
1032 {
1033  Q_ASSERT( !std::isnan( val1 ) );
1034  Q_ASSERT( !std::isnan( val2 ) );
1035  bool bval1 = qgsDoubleNear( val1, D_TRUE );
1036  bool bval2 = qgsDoubleNear( val2, D_TRUE );
1037  if ( bval1 || bval2 )
1038  return D_TRUE;
1039  else
1040  return D_FALSE;
1041 
1042 }
1043 
1044 double QgsMeshCalcUtils::flogicalNot( double val1 ) const
1045 {
1046  Q_ASSERT( !std::isnan( val1 ) );
1047  bool bval1 = qgsDoubleNear( val1, D_TRUE );
1048  if ( bval1 )
1049  return D_FALSE;
1050  else
1051  return D_TRUE;
1052 
1053 }
1054 
1055 double QgsMeshCalcUtils::fchangeSign( double val1 ) const
1056 {
1057  Q_ASSERT( !std::isnan( val1 ) );
1058  return -val1;
1059 }
1060 
1061 double QgsMeshCalcUtils::fmin( double val1, double val2 ) const
1062 {
1063  Q_ASSERT( !std::isnan( val1 ) );
1064  if ( val1 > val2 )
1065  {
1066  return val2;
1067  }
1068  else
1069  {
1070  return val1;
1071  }
1072 }
1073 
1074 
1075 double QgsMeshCalcUtils::fmax( double val1, double val2 ) const
1076 {
1077  Q_ASSERT( !std::isnan( val1 ) );
1078  Q_ASSERT( !std::isnan( val2 ) );
1079  if ( val1 < val2 )
1080  {
1081  return val2;
1082  }
1083  else
1084  {
1085  return val1;
1086  }
1087 
1088 }
1089 
1090 double QgsMeshCalcUtils::fabs( double val1 ) const
1091 {
1092  Q_ASSERT( !std::isnan( val1 ) );
1093  if ( val1 > 0 )
1094  {
1095  return val1;
1096  }
1097  else
1098  {
1099  return -val1;
1100  }
1101 
1102 }
1103 
1104 double QgsMeshCalcUtils::fsumAggregated( QVector<double> &vals ) const
1105 {
1106  Q_ASSERT( !vals.contains( D_NODATA ) );
1107  Q_ASSERT( !vals.isEmpty() );
1108  return std::accumulate( vals.begin(), vals.end(), 0.0 );
1109 }
1110 
1111 double QgsMeshCalcUtils::fminimumAggregated( QVector<double> &vals ) const
1112 {
1113  Q_ASSERT( !vals.contains( D_NODATA ) );
1114  Q_ASSERT( !vals.isEmpty() );
1115  return *std::min_element( vals.begin(), vals.end() );
1116 }
1117 
1118 double QgsMeshCalcUtils::fmaximumAggregated( QVector<double> &vals ) const
1119 {
1120  Q_ASSERT( !vals.contains( D_NODATA ) );
1121  Q_ASSERT( !vals.isEmpty() );
1122  return *std::max_element( vals.begin(), vals.end() );
1123 }
1124 
1125 double QgsMeshCalcUtils::faverageAggregated( QVector<double> &vals ) const
1126 {
1127  Q_ASSERT( !vals.contains( D_NODATA ) );
1128  Q_ASSERT( !vals.isEmpty() );
1129  return fsumAggregated( vals ) / vals.size();
1130 }
1131 
1132 void QgsMeshCalcUtils::logicalNot( QgsMeshMemoryDatasetGroup &group1 ) const
1133 {
1134  return func1( group1, std::bind( & QgsMeshCalcUtils::flogicalNot, this, std::placeholders::_1 ) );
1135 }
1136 
1137 void QgsMeshCalcUtils::changeSign( QgsMeshMemoryDatasetGroup &group1 ) const
1138 {
1139  return func1( group1, std::bind( & QgsMeshCalcUtils::fchangeSign, this, std::placeholders::_1 ) );
1140 }
1141 
1142 void QgsMeshCalcUtils::abs( QgsMeshMemoryDatasetGroup &group1 ) const
1143 {
1144  return func1( group1, std::bind( & QgsMeshCalcUtils::fabs, this, std::placeholders::_1 ) );
1145 }
1146 
1147 void QgsMeshCalcUtils::add( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const
1148 {
1149  return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fadd, this, std::placeholders::_1, std::placeholders::_2 ) );
1150 }
1151 
1152 void QgsMeshCalcUtils::subtract( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const
1153 {
1154  return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fsubtract, this, std::placeholders::_1, std::placeholders::_2 ) );
1155 }
1156 
1157 void QgsMeshCalcUtils::multiply( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const
1158 {
1159  return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fmultiply, this, std::placeholders::_1, std::placeholders::_2 ) );
1160 }
1161 
1162 void QgsMeshCalcUtils::divide( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const
1163 {
1164  return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fdivide, this, std::placeholders::_1, std::placeholders::_2 ) );
1165 }
1166 
1167 void QgsMeshCalcUtils::power( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const
1168 {
1169  return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fpower, this, std::placeholders::_1, std::placeholders::_2 ) );
1170 }
1171 
1172 void QgsMeshCalcUtils::equal( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const
1173 {
1174  return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fequal, this, std::placeholders::_1, std::placeholders::_2 ) );
1175 }
1176 
1177 void QgsMeshCalcUtils::notEqual( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const
1178 {
1179  return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fnotEqual, this, std::placeholders::_1, std::placeholders::_2 ) );
1180 }
1181 
1182 void QgsMeshCalcUtils::greaterThan( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const
1183 {
1184  return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fgreaterThan, this, std::placeholders::_1, std::placeholders::_2 ) );
1185 }
1186 
1187 void QgsMeshCalcUtils::lesserThan( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const
1188 {
1189  return func2( group1, group2, std::bind( & QgsMeshCalcUtils::flesserThan, this, std::placeholders::_1, std::placeholders::_2 ) );
1190 }
1191 
1192 void QgsMeshCalcUtils::lesserEqual( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const
1193 {
1194  return func2( group1, group2, std::bind( & QgsMeshCalcUtils::flesserEqual, this, std::placeholders::_1, std::placeholders::_2 ) );
1195 }
1196 
1197 void QgsMeshCalcUtils::greaterEqual( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const
1198 {
1199  return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fgreaterEqual, this, std::placeholders::_1, std::placeholders::_2 ) );
1200 }
1201 
1202 void QgsMeshCalcUtils::logicalAnd( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const
1203 {
1204  return func2( group1, group2, std::bind( & QgsMeshCalcUtils::flogicalAnd, this, std::placeholders::_1, std::placeholders::_2 ) );
1205 }
1206 
1207 void QgsMeshCalcUtils::logicalOr( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const
1208 {
1209  return func2( group1, group2, std::bind( & QgsMeshCalcUtils::flogicalOr, this, std::placeholders::_1, std::placeholders::_2 ) );
1210 }
1211 
1212 void QgsMeshCalcUtils::minimum( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const
1213 {
1214  return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fmin, this, std::placeholders::_1, std::placeholders::_2 ) );
1215 }
1216 
1217 void QgsMeshCalcUtils::maximum( QgsMeshMemoryDatasetGroup &group1, const QgsMeshMemoryDatasetGroup &group2 ) const
1218 {
1219  return func2( group1, group2, std::bind( & QgsMeshCalcUtils::fmax, this, std::placeholders::_1, std::placeholders::_2 ) );
1220 }
1221 
1222 QgsMeshDatasetGroupMetadata::DataType QgsMeshCalcUtils::determineResultDataType( QgsMeshLayer *layer, const QStringList &usedGroupNames )
1223 {
1224  QHash<QString, int> names;
1225  const QList<int> &groupIndexes = layer->datasetGroupsIndexes();
1226  for ( int groupId : groupIndexes )
1227  {
1228  const QgsMeshDatasetGroupMetadata meta = layer->datasetGroupMetadata( groupId );
1229  const QString name = meta.name();
1230  names[ name ] = groupId;
1231  }
1232  for ( const QString &datasetGroupName : usedGroupNames )
1233  {
1234  if ( names.contains( datasetGroupName ) )
1235  {
1236  int groupId = names.value( datasetGroupName );
1237  const QgsMeshDatasetGroupMetadata meta = layer->datasetGroupMetadata( groupId );
1239  {
1241  }
1243  {
1245  }
1246  }
1247  }
1249 }
1250 
1251 void QgsMeshCalcUtils::filter( QgsMeshMemoryDatasetGroup &group1, const QgsRectangle &extent ) const
1252 {
1253  QgsMeshMemoryDatasetGroup filter( "filter", outputType() );
1254  populateSpatialFilter( filter, extent );
1255  return func2( group1, filter, std::bind( & QgsMeshCalcUtils::ffilter, this, std::placeholders::_1, std::placeholders::_2 ) );
1256 }
1257 
1258 void QgsMeshCalcUtils::filter( QgsMeshMemoryDatasetGroup &group1, const QgsGeometry &mask ) const
1259 {
1260  QgsMeshMemoryDatasetGroup filter( "filter", outputType() );
1261  populateMaskFilter( filter, mask );
1262  return func2( group1, filter, std::bind( & QgsMeshCalcUtils::ffilter, this, std::placeholders::_1, std::placeholders::_2 ) );
1263 }
1264 
1265 void QgsMeshCalcUtils::sumAggregated( QgsMeshMemoryDatasetGroup &group1 ) const
1266 {
1267  return funcAggr( group1, std::bind( & QgsMeshCalcUtils::fsumAggregated, this, std::placeholders::_1 ) );
1268 }
1269 
1270 void QgsMeshCalcUtils::minimumAggregated( QgsMeshMemoryDatasetGroup &group1 ) const
1271 {
1272  return funcAggr( group1, std::bind( & QgsMeshCalcUtils::fminimumAggregated, this, std::placeholders::_1 ) );
1273 }
1274 
1275 void QgsMeshCalcUtils::maximumAggregated( QgsMeshMemoryDatasetGroup &group1 ) const
1276 {
1277  return funcAggr( group1, std::bind( & QgsMeshCalcUtils::fmaximumAggregated, this, std::placeholders::_1 ) );
1278 }
1279 
1280 void QgsMeshCalcUtils::averageAggregated( QgsMeshMemoryDatasetGroup &group1 ) const
1281 {
1282  return funcAggr( group1, std::bind( & QgsMeshCalcUtils::faverageAggregated, this, std::placeholders::_1 ) );
1283 }
1284 
QgsMeshLayer::datasetGroupsIndexes
QList< int > datasetGroupsIndexes() const
Returns the list of indexes of dataset groups count handled by the layer.
Definition: qgsmeshlayer.cpp:337
QgsMeshDatasetGroupMetadata::minimum
double minimum() const
Returns minimum scalar value/vector magnitude present for whole dataset group.
Definition: qgsmeshdataset.cpp:176
qgsmeshlayerutils.h
QgsMeshDatasetMetadata::minimum
double minimum() const
Returns minimum scalar value/vector magnitude present for the dataset.
Definition: qgsmeshdataset.cpp:225
qgsmeshcalcnode.h
QgsMeshDatasetGroupMetadata::DataOnVolumes
@ DataOnVolumes
Data is defined on volumes.
Definition: qgsmeshdataset.h:358
QgsMeshDatasetValue
QgsMeshDatasetValue represents single dataset value.
Definition: qgsmeshdataset.h:78
QgsMesh
Mesh - vertices, edges and faces.
Definition: qgsmeshdataprovider.h:58
QgsMeshDataSourceInterface::contains
bool contains(const QgsMesh::ElementType &type) const
Returns whether the mesh contains at mesh elements of given type.
Definition: qgsmeshdataprovider.cpp:184
QgsMeshDatasetMetadata::isValid
bool isValid() const
Returns whether dataset is valid.
Definition: qgsmeshdataset.cpp:220
qgsmapsettings.h
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QgsMeshDatasetMetadata
QgsMeshDatasetMetadata is a collection of mesh dataset metadata such as whether the data is valid or ...
Definition: qgsmeshdataset.h:476
QgsMeshDatasetMetadata::time
double time() const
Returns the time value for this dataset.
Definition: qgsmeshdataset.cpp:215
QgsMeshRendererScalarSettings::NeighbourAverage
@ NeighbourAverage
Does a simple average of values defined for all surrounding faces/vertices.
Definition: qgsmeshrenderersettings.h:116
qgstriangularmesh.h
QgsMeshMemoryDatasetGroup::addDataset
void addDataset(std::shared_ptr< QgsMeshMemoryDataset > dataset)
Adds a memory dataset to the group.
Definition: qgsmeshdataset.cpp:931
QgsMeshDatasetGroupMetadata::DataOnFaces
@ DataOnFaces
Data is defined on faces.
Definition: qgsmeshdataset.h:356
QgsMeshDatasetGroupMetadata::DataOnVertices
@ DataOnVertices
Data is defined on vertices.
Definition: qgsmeshdataset.h:357
QgsMeshLayer::dataProvider
QgsMeshDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
Definition: qgsmeshlayer.cpp:156
QgsGeometry::intersects
bool intersects(const QgsRectangle &rectangle) const
Returns true if this geometry exactly intersects with a rectangle.
Definition: qgsgeometry.cpp:1129
QgsMeshDatasetIndex::group
int group() const
Returns a group index.
Definition: qgsmeshdataset.cpp:26
QgsMeshDatasetIndex
QgsMeshDatasetIndex is index that identifies the dataset group (e.g.
Definition: qgsmeshdataset.h:47
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:315
QgsMeshLayer
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:95
QgsMeshDataBlock::active
bool active(int index) const
Returns a value for active flag by the index For scalar and vector 2d the behavior is undefined.
Definition: qgsmeshdataset.cpp:282
QgsMeshDatasetIndex::isValid
bool isValid() const
Returns whether index is valid, ie at least groups is set.
Definition: qgsmeshdataset.cpp:36
QgsMeshDataProvider
Base class for providing data for QgsMeshLayer.
Definition: qgsmeshdataprovider.h:398
QgsMeshMemoryDatasetGroup::constDataset
std::shared_ptr< const QgsMeshMemoryDataset > constDataset(int index) const
Returns the dataset with index.
Definition: qgsmeshdataset.cpp:947
QgsMeshDataSourceInterface::vertexCount
virtual int vertexCount() const =0
Returns number of vertices in the native mesh.
QgsMeshDatasetGroupMetadata::DataOnEdges
@ DataOnEdges
Data is defined on edges.
Definition: qgsmeshdataset.h:359
QgsMeshFace
QVector< int > QgsMeshFace
List of vertex indexes.
Definition: qgsmeshdataprovider.h:41
QgsMeshDatasetGroupMetadata::name
QString name() const
Returns name of the dataset group.
Definition: qgsmeshdataset.cpp:166
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:44
QgsMeshDatasetGroupMetadata::dataType
DataType dataType() const
Returns whether dataset group data is defined on vertices or faces or volumes.
Definition: qgsmeshdataset.cpp:171
QgsMeshDataSourceInterface::faceCount
virtual int faceCount() const =0
Returns number of faces in the native mesh.
QgsMeshDatasetGroupMetadata
QgsMeshDatasetGroupMetadata is a collection of dataset group metadata such as whether the data is vec...
Definition: qgsmeshdataset.h:350
qgsmeshlayerrenderer.h
QgsMeshDataBlock::values
QVector< double > values() const
Returns buffer to the array with values For vector it is pairs (x1, y1, x2, y2, .....
Definition: qgsmeshdataset.cpp:310
QgsMeshDatasetGroupMetadata::isScalar
bool isScalar() const
Returns whether dataset group has scalar data.
Definition: qgsmeshdataset.cpp:156
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsMeshDatasetGroupMetadata::maximum
double maximum() const
Returns maximum scalar value/vector magnitude present for whole dataset group.
Definition: qgsmeshdataset.cpp:181
QgsMeshDatasetGroupMetadata::DataType
DataType
Location of where data is specified for datasets in the dataset group.
Definition: qgsmeshdataset.h:355
QgsRectangle::set
void set(const QgsPointXY &p1, const QgsPointXY &p2)
Sets the rectangle from two QgsPoints.
Definition: qgsrectangle.h:105
QgsMeshDatasetGroup::dataType
QgsMeshDatasetGroupMetadata::DataType dataType() const
Returns the data type of the dataset group.
Definition: qgsmeshdataset.cpp:1029
QgsMeshMemoryDatasetGroup::datasetCount
int datasetCount() const override
Returns the count of datasets in the group.
Definition: qgsmeshdataset.cpp:913
QgsInterval
A representation of the interval between two datetime values.
Definition: qgsinterval.h:41
QgsMeshMemoryDatasetGroup::memoryDatasets
QVector< std::shared_ptr< QgsMeshMemoryDataset > > memoryDatasets
Contains all the memory datasets.
Definition: qgsmeshdataset.h:755
QgsMeshDataBlock
QgsMeshDataBlock is a block of integers/doubles that can be used to retrieve: active flags (e....
Definition: qgsmeshdataset.h:136
QgsMeshLayer::datasetGroupMetadata
QgsMeshDatasetGroupMetadata datasetGroupMetadata(const QgsMeshDatasetIndex &index) const
Returns the dataset groups metadata.
Definition: qgsmeshlayer.cpp:342
QgsGeometry::boundingBox
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Definition: qgsgeometry.cpp:996
QgsMeshDatasetMetadata::maximum
double maximum() const
Returns maximum scalar value/vector magnitude present for the dataset.
Definition: qgsmeshdataset.cpp:230
QgsInterval::hours
double hours() const
Returns the interval duration in hours.
Definition: qgsinterval.h:142
QgsTriangularMesh
Triangular/Derived Mesh is mesh with vertices in map coordinates.
Definition: qgstriangularmesh.h:50
qgsmeshcalcutils.h
QgsGeometry::contains
bool contains(const QgsPointXY *p) const
Returns true if the geometry contains the point p.
Definition: qgsgeometry.cpp:1184
QgsMeshUtils::toGeometry
CORE_EXPORT QgsGeometry toGeometry(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns face as polygon geometry.
Definition: qgstriangularmesh.cpp:524
QgsMeshDataBlock::value
QgsMeshDatasetValue value(int index) const
Returns a value represented by the index For active flag the behavior is undefined.
Definition: qgsmeshdataset.cpp:266
QgsInterval::isValid
bool isValid() const
Returns true if the interval is valid.
Definition: qgsinterval.h:181
QgsMeshMemoryDatasetGroup
Class that represents a dataset group stored in memory The QgsMeshMemoryDataset objects stores in a Q...
Definition: qgsmeshdataset.h:727
qgsproject.h
QgsMeshMemoryDatasetGroup::clearDatasets
void clearDatasets()
Removes all the datasets from the group.
Definition: qgsmeshdataset.cpp:937
QgsMeshDataBlock::isValid
bool isValid() const
Whether the block is valid.
Definition: qgsmeshdataset.cpp:261
QgsMeshDataBlock::count
int count() const
Number of items stored in the block.
Definition: qgsmeshdataset.cpp:256