QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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"
26 #include "qgis.h"
27 
28 QgsMeshCalculator::QgsMeshCalculator( const QString &formulaString, const QString &outputFile,
29  const QgsRectangle &outputExtent, double startTime, double endTime,
30  QgsMeshLayer *layer )
31  : mFormulaString( formulaString )
32  , mOutputFile( outputFile )
33  , mOutputExtent( outputExtent )
34  , mUseMask( false )
35  , mStartTime( startTime )
36  , mEndTime( endTime )
37  , mMeshLayer( layer )
38 {
39 }
40 
41 QgsMeshCalculator::QgsMeshCalculator( const QString &formulaString,
42  const QString &outputFile,
43  const QgsGeometry &outputMask,
44  double startTime,
45  double endTime,
46  QgsMeshLayer *layer )
47  : mFormulaString( formulaString )
48  , mOutputFile( outputFile )
49  , mOutputMask( outputMask )
50  , mUseMask( true )
51  , mStartTime( startTime )
52  , mEndTime( endTime )
53  , mMeshLayer( layer )
54 {
55 }
56 
58  QgsMeshLayer *layer )
59 {
60  QString errorString;
61  std::unique_ptr< QgsMeshCalcNode > calcNode( QgsMeshCalcNode::parseMeshCalcString( formulaString, errorString ) );
62  if ( !calcNode )
63  {
64  return ParserError;
65  }
66 
67  double startTime = -std::numeric_limits<double>::max();
68  double endTime = std::numeric_limits<double>::max();
69  QgsMeshCalcUtils dsu( layer, calcNode->usedDatasetGroupNames(), startTime, endTime );
70  if ( !dsu.isValid() )
71  {
72  return InvalidDatasets;
73  }
74 
75  return Success;
76 }
77 
79 {
80  Q_UNUSED( feedback )
81 
82  // check input
83  if ( mOutputFile.isEmpty() )
84  {
85  return CreateOutputError;
86  }
87 
88  if ( !mMeshLayer ||
89  !mMeshLayer->dataProvider() ||
90  mMeshLayer->dataProvider()->name() != QStringLiteral( "mdal" )
91  )
92  {
93  return CreateOutputError;
94  }
95 
96  //prepare search string / tree
97  QString errorString;
98  std::unique_ptr< QgsMeshCalcNode > calcNode( QgsMeshCalcNode::parseMeshCalcString( mFormulaString, errorString ) );
99  if ( !calcNode )
100  {
101  return ParserError;
102  }
103 
104  QgsMeshCalcUtils dsu( mMeshLayer, calcNode->usedDatasetGroupNames(), mStartTime, mEndTime );
105  if ( !dsu.isValid() )
106  {
107  return InvalidDatasets;
108  }
109 
110  //open output dataset
111  std::unique_ptr<QgsMeshMemoryDatasetGroup> outputGroup = qgis::make_unique<QgsMeshMemoryDatasetGroup> ( mOutputFile );
112 
113  // calculate
114  bool ok = calcNode->calculate( dsu, *outputGroup );
115  if ( !ok )
116  {
117  return EvaluateError;
118  }
119 
120  if ( feedback && feedback->isCanceled() )
121  {
122  return Canceled;
123  }
124  if ( feedback )
125  {
126  feedback->setProgress( 60.0 );
127  }
128 
129  // Finalize dataset
130  if ( mUseMask )
131  {
132  dsu.filter( *outputGroup, mOutputMask );
133  }
134  else
135  {
136  dsu.filter( *outputGroup, mOutputExtent );
137  }
138  outputGroup->isScalar = true;
139  outputGroup->name = QFileInfo( mOutputFile ).baseName();
140 
141  // before storing the file, find out if the process is not already canceled
142  if ( feedback && feedback->isCanceled() )
143  {
144  return Canceled;
145  }
146  if ( feedback )
147  {
148  feedback->setProgress( 80.0 );
149  }
150 
151  // store to file
152  QVector<QgsMeshDataBlock> datasetValues;
153  QVector<QgsMeshDataBlock> datasetActive;
154  QVector<double> times;
155 
156  const auto datasize = outputGroup->datasets.size();
157  datasetValues.reserve( datasize );
158  times.reserve( datasize );
159 
160  for ( int i = 0; i < datasize; ++i )
161  {
162  const std::shared_ptr<QgsMeshMemoryDataset> dataset = outputGroup->datasets.at( i );
163 
164  times.push_back( dataset->time );
165  datasetValues.push_back(
166  dataset->datasetValues( outputGroup->isScalar,
167  0,
168  dataset->values.size() )
169  );
170  if ( !dataset->active.isEmpty() )
171  {
172  datasetActive.push_back(
173  dataset->areFacesActive(
174  0,
175  dataset->active.size() )
176  );
177  }
178  }
179 
180  const QgsMeshDatasetGroupMetadata meta = outputGroup->groupMetadata();
181  bool err = mMeshLayer->dataProvider()->persistDatasetGroup(
182  mOutputFile,
183  meta,
184  datasetValues,
185  datasetActive,
186  times
187  );
188 
189  if ( err )
190  {
191  return CreateOutputError;
192  }
193 
194  if ( feedback )
195  {
196  feedback->setProgress( 100.0 );
197  }
198  return Success;
199 }
Result
Result of the calculation.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
Result processCalculation(QgsFeedback *feedback=nullptr)
Starts the calculation, writes new dataset group to file and adds it to the mesh layer.
virtual bool persistDatasetGroup(const QString &path, const QgsMeshDatasetGroupMetadata &meta, const QVector< QgsMeshDataBlock > &datasetValues, const QVector< QgsMeshDataBlock > &datasetActive, const QVector< double > &times)=0
Creates a new dataset group from a data and persists it into a destination path.
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:63
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:111
QgsMeshCalculator(const QString &formulaString, const QString &outputFile, const QgsRectangle &outputExtent, double startTime, double endTime, QgsMeshLayer *layer)
Creates calculator with bounding box (rectangular) mask.
Error during evaluation.
static Result expression_valid(const QString &formulaString, QgsMeshLayer *layer)
Returns whether formula is valid for particular mesh layer.
virtual QString name() const =0
Returns a provider name.
Base class for feedback objects to be used for cancellation of something running in a worker thread...
Definition: qgsfeedback.h:44
Error parsing formula.
Calculation successful.
Datasets with different time outputs or not part of the mesh.
QgsMeshDataProvider * dataProvider() override
Returns the layer&#39;s data provider, it may be nullptr.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
QgsMeshDatasetGroupMetadata is a collection of dataset group metadata such as whether the data is vec...
Error creating output data file.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:90
Calculation canceled.