QGIS API Documentation  3.23.0-Master (dd0cd13a00)
qgsmeshvirtualdatasetgroup.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmeshvirtualdatasetgroup.cpp
3  ---------------------
4  begin : June 2020
5  copyright : (C) 2020 by Vincent Cloarec
6  email : vcloarec 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  ***************************************************************************/
17 
20 
22  const QString &name,
23  const QString &formulaString,
24  QgsMeshLayer *layer,
25  qint64 relativeStartTime,
26  qint64 relativeEndTime ):
27  QgsMeshDatasetGroup( name )
28  , mFormula( formulaString )
29  , mLayer( layer )
30  , mStartTime( relativeStartTime )
31  , mEndTime( relativeEndTime )
32 {
33 }
34 
36 {
37  QString errMessage;
38  mCalcNode.reset( QgsMeshCalcNode::parseMeshCalcString( mFormula, errMessage ) );
39 
40  if ( !mCalcNode || !mLayer )
41  return;
42 
43  mDatasetGroupNameUsed = mCalcNode->notAggregatedUsedDatasetGroupNames();
44  mDatasetGroupNameUsedForAggregate = mCalcNode->aggregatedUsedDatasetGroupNames();
45  setDataType( QgsMeshCalcUtils::determineResultDataType( mLayer,
46  mDatasetGroupNameUsed + mDatasetGroupNameUsedForAggregate ) );
47 
48  //populate used group indexes
49  QMap<QString, int> usedDatasetGroupindexes;
50  const QList<int> &indexes = mLayer->datasetGroupsIndexes();
51  for ( const int i : indexes )
52  {
53  const QString usedName = mLayer->datasetGroupMetadata( i ).name();
54  if ( mDatasetGroupNameUsed.contains( usedName ) )
55  usedDatasetGroupindexes[usedName] = i;
56  }
57 
58  QSet<qint64> times;
59  if ( !mCalcNode->isNonTemporal() )
60  {
61  //populate dataset index with time;
62  const QList<int> &usedIndexes = usedDatasetGroupindexes.values();
63  for ( const int groupIndex : usedIndexes )
64  {
65  const int dsCount = mLayer->datasetCount( groupIndex );
66  if ( dsCount == 0 )
67  return;
68 
69  if ( dsCount == 1 ) //non temporal dataset group
70  continue;
71  for ( int i = 0; i < dsCount; i++ )
72  {
73  const qint64 time = mLayer->datasetRelativeTimeInMilliseconds( QgsMeshDatasetIndex( groupIndex, i ) );
74  if ( time != INVALID_MESHLAYER_TIME )
75  times.insert( time );
76  }
77  }
78  }
79 
80  if ( times.isEmpty() )
81  times.insert( 0 );
82 
83  mDatasetTimes = qgis::setToList( times );
84  std::sort( mDatasetTimes.begin(), mDatasetTimes.end() );
85 
86  mDatasetMetaData = QVector<QgsMeshDatasetMetadata>( mDatasetTimes.count() );
87 
88  //to fill metadata, calculate all the datasets one time
89  int i = 0;
90  while ( i < mDatasetTimes.count() )
91  {
92  mCurrentDatasetIndex = i;
93  if ( calculateDataset() )
94  ++i; //calculation succeeds
95  else
96  mDatasetTimes.removeAt( i ); //calculation fails, remove this time step
97  }
98 
100 }
101 
103 {
104  return mDatasetTimes.count();
105 }
106 
108 {
109  if ( index < 0 || index >= mDatasetTimes.count() )
110  return nullptr;
111 
112  if ( index != mCurrentDatasetIndex )
113  {
114  mCurrentDatasetIndex = index;
115  calculateDataset();
116  }
117 
118  return mCacheDataset.get();
119 }
120 
122 {
123  if ( datasetIndex < 0 && datasetIndex >= mDatasetMetaData.count() )
124  return QgsMeshDatasetMetadata();
125 
126  return mDatasetMetaData.at( datasetIndex );
127 }
128 
130 {
131  return mDatasetGroupNameUsed;
132 }
133 
134 QDomElement QgsMeshVirtualDatasetGroup::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
135 {
136  Q_UNUSED( context )
137  QDomElement elemDataset = doc.createElement( QStringLiteral( "mesh-dataset" ) );
138  elemDataset.setAttribute( QStringLiteral( "source-type" ), QStringLiteral( "virtual" ) );
139  elemDataset.setAttribute( QStringLiteral( "name" ), name() );
140  elemDataset.setAttribute( QStringLiteral( "formula" ), mFormula );
141  elemDataset.setAttribute( QStringLiteral( "start-time" ), mStartTime );
142  elemDataset.setAttribute( QStringLiteral( "end-time" ), mEndTime );
143 
144  return elemDataset;
145 }
146 
148 {
149  return mFormula;
150 }
151 
152 bool QgsMeshVirtualDatasetGroup::calculateDataset() const
153 {
154  if ( !mLayer )
155  return false;
156 
157  const QgsMeshCalcUtils dsu( mLayer,
158  mDatasetGroupNameUsed,
159  mDatasetGroupNameUsedForAggregate,
160  QgsInterval( mDatasetTimes[mCurrentDatasetIndex] / 1000.0 ),
161  QgsInterval( mStartTime / 1000.0 ),
162  QgsInterval( mEndTime / 1000.0 ) );
163 
164  if ( !dsu.isValid() )
165  return false;
166 
167  //open output dataset
168  std::unique_ptr<QgsMeshMemoryDatasetGroup> outputGroup = std::make_unique<QgsMeshMemoryDatasetGroup> ( QString(), dsu.outputType() );
169  mCalcNode->calculate( dsu, *outputGroup );
170 
171  if ( outputGroup->memoryDatasets.isEmpty() )
172  return false;
173 
174  mCacheDataset = outputGroup->memoryDatasets[0];
175  if ( !mDatasetMetaData[mCurrentDatasetIndex].isValid() )
176  {
177  mCacheDataset->calculateMinMax();
178  mCacheDataset->time = mDatasetTimes[mCurrentDatasetIndex] / 3600.0 / 1000.0;
179  mDatasetMetaData[mCurrentDatasetIndex] = mCacheDataset->metadata();
180  }
181 
182  return true;
183 }
A representation of the interval between two datetime values.
Definition: qgsinterval.h:42
QString name() const
Returns name of the dataset group.
Abstract class that represents a dataset group.
void setDataType(const QgsMeshDatasetGroupMetadata::DataType &dataType)
Sets the data type of the dataset group.
QString name() const
Returns the name of the dataset group.
void calculateStatistic()
Calculates the statistics (minimum and maximum)
QgsMeshDatasetIndex is index that identifies the dataset group (e.g.
QgsMeshDatasetMetadata is a collection of mesh dataset metadata such as whether the data is valid or ...
Abstract class that represents a dataset.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:97
int datasetCount(const QgsMeshDatasetIndex &index) const
Returns the dataset count in the dataset groups.
QList< int > datasetGroupsIndexes() const
Returns the list of indexes of dataset groups handled by the layer.
qint64 datasetRelativeTimeInMilliseconds(const QgsMeshDatasetIndex &index)
Returns the relative time (in milliseconds) of the dataset from the reference time of its group.
QgsMeshDatasetGroupMetadata datasetGroupMetadata(const QgsMeshDatasetIndex &index) const
Returns the dataset groups metadata.
QgsMeshVirtualDatasetGroup(const QString &name, const QString &formulaString, QgsMeshLayer *layer, qint64 relativeStartTime, qint64 relativeEndTime)
Constructor.
QgsMeshDatasetMetadata datasetMetadata(int datasetIndex) const override
Returns the metadata of the dataset with index datasetIndex.
QStringList datasetGroupNamesDependentOn() const override
Returns the dataset group variable name which this dataset group depends on.
void initialize() override
Initialize the dataset group.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const override
Write dataset group information in a DOM element.
int datasetCount() const override
Returns the count of datasets in the group.
QgsMeshDataset * dataset(int index) const override
Returns the dataset with index.
QString description() const override
Returns some information about the dataset group.
The class is used as a container of context for various read/write operations on other objects.