QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgsmeshcalculator.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmeshcalculator.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  ***************************************************************************/
17 
18 #include <QFileInfo>
19 #include <limits>
20 #include <memory>
21 
22 #include "qgsmeshcalcnode.h"
23 #include "qgsmeshcalculator.h"
24 #include "qgsmeshcalcutils.h"
25 #include "qgsmeshmemorydataprovider.h"
26 #include "qgis.h"
27 
28 QgsMeshCalculator::QgsMeshCalculator( const QString &formulaString,
29  const QString &outputFile,
30  const QgsRectangle &outputExtent,
31  double startTime,
32  double endTime,
33  QgsMeshLayer *layer )
34  : mFormulaString( formulaString )
35  , mOutputDriver( QStringLiteral( "DAT" ) )
36  , mOutputFile( outputFile )
37  , mOutputExtent( outputExtent )
38  , mUseMask( false )
39  , mStartTime( startTime )
40  , mEndTime( endTime )
41  , mMeshLayer( layer )
42 {
43  if ( !mOutputFile.isEmpty() )
44  mOutputGroupName = QFileInfo( mOutputFile ).baseName();
45 }
46 
47 QgsMeshCalculator::QgsMeshCalculator( const QString &formulaString,
48  const QString &outputFile,
49  const QgsGeometry &outputMask,
50  double startTime,
51  double endTime,
52  QgsMeshLayer *layer )
53  : mFormulaString( formulaString )
54  , mOutputDriver( QStringLiteral( "DAT" ) )
55  , mOutputFile( outputFile )
56  , mOutputMask( outputMask )
57  , mUseMask( true )
58  , mStartTime( startTime )
59  , mEndTime( endTime )
60  , mMeshLayer( layer )
61 {
62  if ( !mOutputFile.isEmpty() )
63  mOutputGroupName = QFileInfo( mOutputFile ).baseName();
64 }
65 
66 
67 QgsMeshCalculator::QgsMeshCalculator( const QString &formulaString,
68  const QString &outputDriver,
69  const QString &outputGroupName,
70  const QString &outputFile,
71  const QgsRectangle &outputExtent,
72  double startTime,
73  double endTime,
74  QgsMeshLayer *layer )
75  : mFormulaString( formulaString )
76  , mOutputDriver( outputDriver )
77  , mOutputGroupName( outputGroupName )
78  , mOutputFile( outputFile )
79  , mOutputExtent( outputExtent )
80  , mUseMask( false )
81  , mStartTime( startTime )
82  , mEndTime( endTime )
83  , mMeshLayer( layer )
84 {
85 }
86 
87 QgsMeshCalculator::QgsMeshCalculator( const QString &formulaString,
88  const QString &outputDriver,
89  const QString &outputGroupName,
90  const QString &outputFile,
91  const QgsGeometry &outputMask,
92  double startTime,
93  double endTime,
94  QgsMeshLayer *layer )
95  : mFormulaString( formulaString )
96  , mOutputDriver( outputDriver )
97  , mOutputGroupName( outputGroupName )
98  , mOutputFile( outputFile )
99  , mOutputMask( outputMask )
100  , mUseMask( true )
101  , mStartTime( startTime )
102  , mEndTime( endTime )
103  , mMeshLayer( layer )
104 {
105 }
106 
108  const QString &formulaString,
109  QgsMeshLayer *layer )
110 {
112  return QgsMeshCalculator::expressionIsValid( formulaString, layer, cap );
113 }
114 
116  const QString &formulaString,
117  QgsMeshLayer *layer,
118  QgsMeshDriverMetadata::MeshDriverCapability &requiredCapability )
119 {
120  QString errorString;
121  std::unique_ptr< QgsMeshCalcNode > calcNode( QgsMeshCalcNode::parseMeshCalcString( formulaString, errorString ) );
122  if ( !calcNode )
123  return ParserError;
124 
125  if ( !layer || !layer->dataProvider() )
126  return InputLayerError;
127 
128  QgsMeshDatasetGroupMetadata::DataType dataType = QgsMeshCalcUtils::determineResultDataType( layer, calcNode->usedDatasetGroupNames() );
129 
130  requiredCapability = dataType == QgsMeshDatasetGroupMetadata::DataOnFaces ? QgsMeshDriverMetadata::MeshDriverCapability::CanWriteFaceDatasets :
131  QgsMeshDriverMetadata::MeshDriverCapability::CanWriteVertexDatasets;
132 
133  return Success;
134 }
135 
137 {
138  // check input
139  if ( mOutputFile.isEmpty() )
140  {
141  return CreateOutputError;
142  }
143 
144  if ( !mMeshLayer ||
145  !mMeshLayer->dataProvider() ||
146  mMeshLayer->providerType() != QStringLiteral( "mdal" )
147  )
148  {
149  return CreateOutputError;
150  }
151 
152  //prepare search string / tree
153  QString errorString;
154  std::unique_ptr< QgsMeshCalcNode > calcNode( QgsMeshCalcNode::parseMeshCalcString( mFormulaString, errorString ) );
155  if ( !calcNode )
156  {
157  return ParserError;
158  }
159 
160  QgsMeshCalcUtils dsu( mMeshLayer, calcNode->usedDatasetGroupNames(), mStartTime, mEndTime );
161  if ( !dsu.isValid() )
162  {
163  return InvalidDatasets;
164  }
165 
166  //open output dataset
167  std::unique_ptr<QgsMeshMemoryDatasetGroup> outputGroup = qgis::make_unique<QgsMeshMemoryDatasetGroup> ( mOutputFile, dsu.outputType() );
168 
169  // calculate
170  bool ok = calcNode->calculate( dsu, *outputGroup );
171  if ( !ok )
172  {
173  return EvaluateError;
174  }
175 
176  if ( feedback && feedback->isCanceled() )
177  {
178  return Canceled;
179  }
180  if ( feedback )
181  {
182  feedback->setProgress( 60.0 );
183  }
184 
185  // Finalize dataset
186  if ( mUseMask )
187  {
188  dsu.filter( *outputGroup, mOutputMask );
189  }
190  else
191  {
192  dsu.filter( *outputGroup, mOutputExtent );
193  }
194  outputGroup->isScalar = true;
195  outputGroup->name = mOutputGroupName;
196 
197  // before storing the file, find out if the process is not already canceled
198  if ( feedback && feedback->isCanceled() )
199  {
200  return Canceled;
201  }
202  if ( feedback )
203  {
204  feedback->setProgress( 80.0 );
205  }
206 
207  // store to file
208  QVector<QgsMeshDataBlock> datasetValues;
209  QVector<QgsMeshDataBlock> datasetActive;
210  QVector<double> times;
211 
212  const auto datasize = outputGroup->datasets.size();
213  datasetValues.reserve( datasize );
214  times.reserve( datasize );
215 
216  for ( int i = 0; i < datasize; ++i )
217  {
218  const std::shared_ptr<QgsMeshMemoryDataset> dataset = outputGroup->datasets.at( i );
219 
220  times.push_back( dataset->time );
221  datasetValues.push_back(
222  dataset->datasetValues( outputGroup->isScalar,
223  0,
224  dataset->values.size() )
225  );
226  if ( !dataset->active.isEmpty() )
227  {
228  datasetActive.push_back(
229  dataset->areFacesActive(
230  0,
231  dataset->active.size() )
232  );
233  }
234  }
235 
236  const QgsMeshDatasetGroupMetadata meta = outputGroup->groupMetadata();
237  bool err = mMeshLayer->dataProvider()->persistDatasetGroup(
238  mOutputFile,
239  mOutputDriver,
240  meta,
241  datasetValues,
242  datasetActive,
243  times
244  );
245 
246  if ( err )
247  {
248  return CreateOutputError;
249  }
250 
251  if ( feedback )
252  {
253  feedback->setProgress( 100.0 );
254  }
255  return Success;
256 }
QgsMeshCalculator::ParserError
@ ParserError
Error parsing formula.
Definition: qgsmeshcalculator.h:62
QgsFeedback::setProgress
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:75
qgsmeshcalcnode.h
QgsMeshCalculator::processCalculation
Result processCalculation(QgsFeedback *feedback=nullptr)
Starts the calculation, writes new dataset group to file and adds it to the mesh layer.
Definition: qgsmeshcalculator.cpp:136
qgis.h
QgsRectangle
Definition: qgsrectangle.h:41
QgsMeshDatasetGroupMetadata::DataOnFaces
@ DataOnFaces
Data is defined on faces.
Definition: qgsmeshdataset.h:355
QgsMeshCalculator::QgsMeshCalculator
Q_DECL_DEPRECATED QgsMeshCalculator(const QString &formulaString, const QString &outputFile, const QgsRectangle &outputExtent, double startTime, double endTime, QgsMeshLayer *layer)
Creates calculator with bounding box (rectangular) mask.
Definition: qgsmeshcalculator.cpp:28
QgsMeshCalculator::expression_valid
static Q_DECL_DEPRECATED Result expression_valid(const QString &formulaString, QgsMeshLayer *layer)
Returns whether formula is valid for particular mesh layer.
Definition: qgsmeshcalculator.cpp:107
qgsmeshcalculator.h
QgsFeedback
Definition: qgsfeedback.h:43
QgsMeshLayer
Definition: qgsmeshlayer.h:94
QgsMeshDatasetSourceInterface::persistDatasetGroup
virtual Q_DECL_DEPRECATED bool persistDatasetGroup(const QString &path, const QgsMeshDatasetGroupMetadata &meta, const QVector< QgsMeshDataBlock > &datasetValues, const QVector< QgsMeshDataBlock > &datasetActive, const QVector< double > &times)
Creates a new dataset group from a data and persists it into a destination path.
Definition: qgsmeshdataprovider.cpp:56
QgsMeshCalculator::Success
@ Success
Calculation successful.
Definition: qgsmeshcalculator.h:58
QgsMeshCalculator::Canceled
@ Canceled
Calculation canceled.
Definition: qgsmeshcalculator.h:59
QgsMeshCalculator::CreateOutputError
@ CreateOutputError
Error creating output data file.
Definition: qgsmeshcalculator.h:60
QgsFeedback::isCanceled
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:66
QgsMeshCalculator::expressionIsValid
static Result expressionIsValid(const QString &formulaString, QgsMeshLayer *layer, QgsMeshDriverMetadata::MeshDriverCapability &requiredCapability)
Returns whether formula is valid for particular mesh layer.
Definition: qgsmeshcalculator.cpp:115
QgsMeshDatasetGroupMetadata
Definition: qgsmeshdataset.h:348
QgsMeshCalculator::InputLayerError
@ InputLayerError
Error reading input layer.
Definition: qgsmeshcalculator.h:61
QgsGeometry
Definition: qgsgeometry.h:122
QgsMeshDatasetGroupMetadata::DataType
DataType
Location of where data is specified for datasets in the dataset group.
Definition: qgsmeshdataset.h:353
QgsMeshCalculator::InvalidDatasets
@ InvalidDatasets
Datasets with different time outputs or not part of the mesh.
Definition: qgsmeshcalculator.h:63
qgsmeshcalcutils.h
QgsMeshLayer::providerType
QString providerType() const
Returns the provider type for this layer.
Definition: qgsmeshlayer.cpp:181
QgsMeshLayer::dataProvider
QgsMeshDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
Definition: qgsmeshlayer.cpp:147
QgsMeshCalculator::EvaluateError
@ EvaluateError
Error during evaluation.
Definition: qgsmeshcalculator.h:64
QgsMeshCalculator::Result
Result
Result of the calculation.
Definition: qgsmeshcalculator.h:56
QgsMeshDriverMetadata::MeshDriverCapability
MeshDriverCapability
Flags for the capabilities of the driver.
Definition: qgsprovidermetadata.h:61