QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
Loading...
Searching...
No Matches
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 "qgsmeshcalculator.h"
19
20#include <limits>
21#include <memory>
22
23#include "qgis.h"
24#include "qgsfeedback.h"
25#include "qgsmeshcalcnode.h"
26#include "qgsmeshcalcutils.h"
27#include "qgsmeshlayer.h"
28#include "qgsmeshmemorydataprovider.h"
30
31#include <QFileInfo>
32#include <QString>
33
34using namespace Qt::StringLiterals;
35
36QgsMeshCalculator::QgsMeshCalculator( const QString &formulaString, const QString &outputFile, const QgsRectangle &outputExtent, double startTime, double endTime, QgsMeshLayer *layer )
37 : mFormulaString( formulaString )
38 , mOutputDriver( u"DAT"_s )
39 , mOutputFile( outputFile )
40 , mOutputExtent( outputExtent )
41 , mStartTime( startTime )
42 , mEndTime( endTime )
43 , mMeshLayer( layer )
44{
45 if ( !mOutputFile.isEmpty() )
46 mOutputGroupName = QFileInfo( mOutputFile ).baseName();
47}
48
49QgsMeshCalculator::QgsMeshCalculator( const QString &formulaString, const QString &outputFile, const QgsGeometry &outputMask, double startTime, double endTime, QgsMeshLayer *layer )
50 : mFormulaString( formulaString )
51 , mOutputDriver( u"DAT"_s )
52 , mOutputFile( outputFile )
53 , mOutputMask( outputMask )
54 , mUseMask( true )
55 , mStartTime( startTime )
56 , mEndTime( endTime )
57 , mMeshLayer( layer )
58{
59 if ( !mOutputFile.isEmpty() )
60 mOutputGroupName = QFileInfo( mOutputFile ).baseName();
61}
62
63
65 const QString &formulaString, const QString &outputDriver, const QString &outputGroupName, const QString &outputFile, const QgsRectangle &outputExtent, double startTime, double endTime, QgsMeshLayer *layer
66)
67 : mFormulaString( formulaString )
68 , mOutputDriver( outputDriver )
69 , mOutputGroupName( outputGroupName )
70 , mOutputFile( outputFile )
71 , mOutputExtent( outputExtent )
72 , mStartTime( startTime )
73 , mEndTime( endTime )
74 , mMeshLayer( layer )
75{}
76
78 const QString &formulaString, const QString &outputDriver, const QString &outputGroupName, const QString &outputFile, const QgsGeometry &outputMask, double startTime, double endTime, QgsMeshLayer *layer
79)
80 : mFormulaString( formulaString )
81 , mOutputDriver( outputDriver )
82 , mOutputGroupName( outputGroupName )
83 , mOutputFile( outputFile )
84 , mOutputMask( outputMask )
85 , mUseMask( true )
86 , mStartTime( startTime )
87 , mEndTime( endTime )
88 , mMeshLayer( layer )
89{}
90
92 const QString &formulaString, const QString &outputGroupName, const QgsRectangle &outputExtent, const QgsMeshDatasetGroup::Type &destination, QgsMeshLayer *layer, double startTime, double endTime
93)
94 : mFormulaString( formulaString )
95 , mOutputGroupName( outputGroupName )
96 , mOutputExtent( outputExtent )
97 , mDestination( destination )
98 , mStartTime( startTime )
99 , mEndTime( endTime )
100 , mMeshLayer( layer )
101{}
102
104 const QString &formulaString, const QString &outputGroupName, const QgsGeometry &outputMask, const QgsMeshDatasetGroup::Type &destination, QgsMeshLayer *layer, double startTime, double endTime
105)
106 : mFormulaString( formulaString )
107 , mOutputGroupName( outputGroupName )
108 , mOutputMask( outputMask )
109 , mUseMask( true )
110 , mDestination( destination )
111 , mStartTime( startTime )
112 , mEndTime( endTime )
113 , mMeshLayer( layer )
114{}
115
117{
119 return QgsMeshCalculator::expressionIsValid( formulaString, layer, cap );
120}
121
123{
124 QString errorString;
125 std::unique_ptr< QgsMeshCalcNode > calcNode( QgsMeshCalcNode::parseMeshCalcString( formulaString, errorString ) );
126 if ( !calcNode )
127 return ParserError;
128
129 if ( !layer || !layer->dataProvider() )
130 return InputLayerError;
131
132 const QgsMeshDatasetGroupMetadata::DataType dataType = QgsMeshCalcUtils::determineResultDataType( layer, calcNode->usedDatasetGroupNames() );
133
136
137 return Success;
138}
139
141{
142 // check input
143 if ( mOutputFile.isEmpty() && mDestination == QgsMeshDatasetGroup::Persistent )
144 {
145 return CreateOutputError;
146 }
147
148 if ( !mMeshLayer || !mMeshLayer->dataProvider() || mMeshLayer->providerType() != "mdal"_L1 )
149 {
150 return CreateOutputError;
151 }
152
153 //prepare search string / tree
154 QString errorString;
155 std::unique_ptr< QgsMeshCalcNode > calcNode( QgsMeshCalcNode::parseMeshCalcString( mFormulaString, errorString ) );
156 if ( !calcNode )
157 {
158 return ParserError;
159 }
160
161 // proceed eventually on the fly
162 bool err;
163 if ( mDestination == QgsMeshDatasetGroup::Virtual )
164 {
165 std::unique_ptr<QgsMeshDatasetGroup> virtualDatasetGroup = std::make_unique<QgsMeshVirtualDatasetGroup>( mOutputGroupName, mFormulaString, mMeshLayer, mStartTime * 3600 * 1000, mEndTime * 3600 * 1000 );
166 virtualDatasetGroup->initialize();
167 virtualDatasetGroup->setReferenceTime( static_cast<QgsMeshLayerTemporalProperties *>( mMeshLayer->temporalProperties() )->referenceTime() );
168 err = !mMeshLayer->addDatasets( virtualDatasetGroup.release() );
169 if ( err )
170 {
171 return CreateOutputError;
172 }
173
174 if ( feedback )
175 {
176 feedback->setProgress( 100.0 );
177 }
178 return Success;
179 }
180
181 //open output dataset
182 const QgsMeshCalcUtils dsu( mMeshLayer, calcNode->usedDatasetGroupNames(), mStartTime, mEndTime );
183 if ( !dsu.isValid() )
184 {
185 return InvalidDatasets;
186 }
187
188 auto outputGroup = std::make_unique<QgsMeshMemoryDatasetGroup>( mOutputGroupName, dsu.outputType() );
189
190 // calculate
191 const bool ok = calcNode->calculate( dsu, *outputGroup );
192 if ( !ok )
193 {
194 return EvaluateError;
195 }
196
197 if ( feedback && feedback->isCanceled() )
198 {
199 return Canceled;
200 }
201 if ( feedback )
202 {
203 feedback->setProgress( 60.0 );
204 }
205
206 // Finalize dataset
207 if ( mUseMask )
208 {
209 dsu.filter( *outputGroup, mOutputMask );
210 }
211 else
212 {
213 dsu.filter( *outputGroup, mOutputExtent );
214 }
215 outputGroup->setIsScalar( true );
216
217 // before storing the file, find out if the process is not already canceled
218 if ( feedback && feedback->isCanceled() )
219 {
220 return Canceled;
221 }
222 if ( feedback )
223 {
224 feedback->setProgress( 80.0 );
225 }
226
227 // store to file or in memory
228 QVector<QgsMeshDataBlock> datasetValues;
229 QVector<QgsMeshDataBlock> datasetActive;
230 QVector<double> times;
231
232 const auto datasize = outputGroup->datasetCount();
233 datasetValues.reserve( datasize );
234 times.reserve( datasize );
235
236 for ( int i = 0; i < datasize; ++i )
237 {
238 const std::shared_ptr<QgsMeshMemoryDataset> dataset = outputGroup->memoryDatasets.at( i );
239
240 times.push_back( dataset->time );
241 datasetValues.push_back( dataset->datasetValues( outputGroup->isScalar(), 0, dataset->values.size() ) );
242 if ( !dataset->active.isEmpty() )
243 {
244 datasetActive.push_back( dataset->areFacesActive( 0, dataset->active.size() ) );
245 }
246 }
247
248 // calculate statistics
249 outputGroup->initialize();
250 outputGroup->setReferenceTime( static_cast<QgsMeshLayerTemporalProperties *>( mMeshLayer->temporalProperties() )->referenceTime() );
251
252 const QgsMeshDatasetGroupMetadata meta = outputGroup->groupMetadata();
253
254 if ( mDestination == QgsMeshDatasetGroup::Memory )
255 {
256 err = !mMeshLayer->addDatasets( outputGroup.release() );
257 }
258 else
259 {
260 err = mMeshLayer->dataProvider()->persistDatasetGroup( mOutputFile, mOutputDriver, meta, datasetValues, datasetActive, times );
261 }
262
263
264 if ( err )
265 {
266 return CreateOutputError;
267 }
268
269 if ( feedback )
270 {
271 feedback->setProgress( 100.0 );
272 }
273 return Success;
274}
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition qgsfeedback.h:44
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:56
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition qgsfeedback.h:65
A geometry is the spatial representation of a feature.
Result
Result of the calculation.
@ InvalidDatasets
Datasets with different time outputs or not part of the mesh.
@ CreateOutputError
Error creating output data file.
@ Success
Calculation successful.
@ EvaluateError
Error during evaluation.
@ ParserError
Error parsing formula.
@ Canceled
Calculation canceled.
@ InputLayerError
Error reading input layer.
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.
static Q_DECL_DEPRECATED Result expression_valid(const QString &formulaString, QgsMeshLayer *layer)
Returns whether formula is valid for particular mesh layer.
Result processCalculation(QgsFeedback *feedback=nullptr)
Starts the calculation, creates new dataset group and adds it to the mesh layer.
static Result expressionIsValid(const QString &formulaString, QgsMeshLayer *layer, QgsMeshDriverMetadata::MeshDriverCapability &requiredCapability)
Returns whether formula is valid for particular mesh layer.
A collection of dataset group metadata such as whether the data is vector or scalar,...
DataType
Location of where data is specified for datasets in the dataset group.
@ DataOnFaces
Data is defined on faces.
Type
Type of the dataset group.
@ Virtual
Virtual Dataset group defined by a formula.
@ Memory
Temporary dataset group in memory.
@ Persistent
Dataset group store in a file.
MeshDriverCapability
Flags for the capabilities of the driver.
@ CanWriteVertexDatasets
If the driver can persist datasets defined on vertices.
@ CanWriteFaceDatasets
If the driver can persist datasets defined on faces.
Implementation of map layer temporal properties for mesh layers.
QDateTime referenceTime() const
Returns the reference time.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
QgsMeshDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
A rectangle specified with double values.