22using namespace Qt::StringLiterals;
45 , mFunctionName( functionName )
46 , mFunctionArgs( functionArgs )
52 , mRasterName( rasterName )
54 if ( mRasterName.startsWith(
'"' ) && mRasterName.endsWith(
'"' ) )
55 mRasterName = mRasterName.mid( 1, mRasterName.size() - 2 );
62 for (
int i = 0; i < mFunctionArgs.size(); ++i )
64 if ( mFunctionArgs.at( i ) )
65 delete mFunctionArgs.at( i );
76 const QMap<QString, QgsRasterBlock *>::iterator it = rasterData.find( mRasterName );
77 if ( it == rasterData.end() )
79 QgsDebugError( u
"Error: could not find raster data for \"%1\""_s.arg( mRasterName ) );
83 const int nRows = ( row >= 0 ? 1 : ( *it )->height() );
84 const int startRow = ( row >= 0 ? row : 0 );
85 const int endRow = startRow + nRows;
86 const int nCols = ( *it )->width();
87 const int nEntries = nCols * nRows;
88 double *data =
new double[nEntries];
93 bool isNoData =
false;
94 for (
int dataRow = startRow; dataRow < endRow; ++dataRow, ++outRow )
96 for (
int dataCol = 0; dataCol < nCols; ++dataCol )
98 const double value = ( *it )->valueAndNoData( dataRow, dataCol, isNoData );
99 data[dataCol + nCols * outRow] = isNoData ? result.
nodataValue() : value;
110 if ( !mLeft || !mLeft->calculate( rasterData, leftMatrix, row ) )
114 if ( mRight && !mRight->calculate( rasterData, rightMatrix, row ) )
122 leftMatrix.
add( rightMatrix );
131 leftMatrix.
divide( rightMatrix );
134 leftMatrix.
power( rightMatrix );
137 leftMatrix.
equal( rightMatrix );
161 leftMatrix.
min( rightMatrix );
164 leftMatrix.
max( rightMatrix );
202 const int newNColumns = leftMatrix.
nColumns();
203 const int newNRows = leftMatrix.
nRows();
209 const size_t nEntries =
static_cast<size_t>( result.
nColumns() * result.
nRows() );
210 double *data =
new double[nEntries];
211 std::fill( data, data + nEntries, mNumber );
218 const int nEntries = mMatrix->nColumns() * mMatrix->nRows();
219 double *data =
new double[nEntries];
220 for (
int i = 0; i < nEntries; ++i )
222 data[i] = mMatrix->data()[i] == mMatrix->nodataValue() ? result.
nodataValue() : mMatrix->data()[i];
229 std::vector<std::unique_ptr<QgsRasterMatrix>> matrixContainer;
230 for (
int i = 0; i < mFunctionArgs.size(); ++i )
232 auto singleMatrix = std::make_unique<QgsRasterMatrix>( result.
nColumns(), result.
nRows(),
nullptr, result.
nodataValue() );
233 if ( !mFunctionArgs.at( i ) || !mFunctionArgs.at( i )->calculate( rasterData, *singleMatrix, row ) )
237 matrixContainer.emplace_back( std::move( singleMatrix ) );
239 evaluateFunction( matrixContainer, result );
251 left = mLeft->toString( cStyle );
253 right = mRight->toString( cStyle );
261 result = u
"( %1 + %2 )"_s.arg( left ).arg( right );
264 result = u
"( %1 - %2 )"_s.arg( left ).arg( right );
267 result = u
"-%1"_s.arg( left );
270 result = u
"%1 * %2"_s.arg( left ).arg( right );
273 result = u
"%1 / %2"_s.arg( left ).arg( right );
277 result = u
"pow( %1, %2 )"_s.arg( left ).arg( right );
279 result = u
"%1^%2"_s.arg( left ).arg( right );
283 result = u
"( float ) ( %1 == %2 )"_s.arg( left ).arg( right );
285 result = u
"%1 = %2"_s.arg( left ).arg( right );
289 result = u
"( float ) ( %1 != %2 )"_s.arg( left ).arg( right );
291 result = u
"%1 != %2"_s.arg( left ).arg( right );
295 result = u
"( float ) ( %1 > %2 )"_s.arg( left ).arg( right );
297 result = u
"%1 > %2"_s.arg( left ).arg( right );
301 result = u
"( float ) ( %1 < %2 )"_s.arg( left ).arg( right );
303 result = u
"%1 < %2"_s.arg( left ).arg( right );
307 result = u
"( float ) ( %1 >= %2 )"_s.arg( left ).arg( right );
309 result = u
"%1 >= %2"_s.arg( left ).arg( right );
313 result = u
"( float ) ( %1 <= %2 )"_s.arg( left ).arg( right );
315 result = u
"%1 <= %2"_s.arg( left ).arg( right );
319 result = u
"( float ) ( %1 && %2 )"_s.arg( left ).arg( right );
321 result = u
"%1 AND %2"_s.arg( left ).arg( right );
325 result = u
"( float ) ( %1 || %2 )"_s.arg( left ).arg( right );
327 result = u
"%1 OR %2"_s.arg( left ).arg( right );
330 result = u
"sqrt( %1 )"_s.arg( left );
333 result = u
"sin( %1 )"_s.arg( left );
336 result = u
"cos( %1 )"_s.arg( left );
339 result = u
"tan( %1 )"_s.arg( left );
342 result = u
"asin( %1 )"_s.arg( left );
345 result = u
"acos( %1 )"_s.arg( left );
348 result = u
"atan( %1 )"_s.arg( left );
351 result = u
"log( %1 )"_s.arg( left );
354 result = u
"log10( %1 )"_s.arg( left );
358 result = u
"fabs( %1 )"_s.arg( left );
361 result = u
"abs( %1 )"_s.arg( left );
365 result = u
"min( ( float ) ( %1 ), ( float ) ( %2 ) )"_s.arg( left ).arg( right );
367 result = u
"min( %1, %2 )"_s.arg( left ).arg( right );
371 result = u
"max( ( float ) ( %1 ), ( float ) ( %2 ) )"_s.arg( left ).arg( right );
373 result = u
"max( %1, %2 )"_s.arg( left ).arg( right );
381 result = u
"( float ) \"%1\""_s.arg( mRasterName );
383 result = u
"\"%1\""_s.arg( mRasterName );
386 result = QString::number( mNumber );
389 result = u
"( float ) %1"_s.arg( result );
395 if ( mFunctionName ==
"if" )
397 const QString argOne = mFunctionArgs.at( 0 )->toString( cStyle );
398 const QString argTwo = mFunctionArgs.at( 1 )->toString( cStyle );
399 const QString argThree = mFunctionArgs.at( 2 )->toString( cStyle );
401 result = u
" ( %1 ) ? ( %2 ) : ( %3 ) "_s.arg( argOne, argTwo, argThree );
403 result = u
"if( %1 , %2 , %3 )"_s.arg( argOne, argTwo, argThree );
412 QList<const QgsRasterCalcNode *> nodeList;
414 nodeList.push_back(
this );
416 nodeList.append( mLeft->findNodes(
type ) );
418 nodeList.append( mRight->findNodes(
type ) );
421 nodeList.append( node->findNodes(
type ) );
428 extern QgsRasterCalcNode *localParseRasterCalcString(
const QString &str, QString &parserErrorMsg );
429 return localParseRasterCalcString( str, parserErrorMsg );
434 QStringList referencedRasters;
437 for (
const auto &i : rasterRef )
439 if ( referencedRasters.contains( i.mid( 0, i.lastIndexOf(
"@" ) ) ) )
441 referencedRasters << i.mid( 0, i.lastIndexOf(
"@" ) );
444 return referencedRasters;
449 QStringList rasterReferences;
454 QString layerRef( r->toString() );
455 if ( layerRef.at( 0 ) ==
"\""_L1 && layerRef.at( layerRef.size() - 1 ) ==
"\""_L1 )
457 layerRef.remove( 0, 1 );
460 layerRef.remove( QChar(
'\\' ), Qt::CaseInsensitive );
461 rasterReferences << layerRef;
464 return rasterReferences;
467QgsRasterMatrix QgsRasterCalcNode::evaluateFunction(
const std::vector<std::unique_ptr<QgsRasterMatrix>> &matrixVector,
QgsRasterMatrix &result )
const
469 if ( mFunctionName ==
"if" )
472 if ( matrixVector.at( 0 )->isNumber() )
474 result = ( matrixVector.at( 0 )->data() ? *matrixVector.at( 1 ) : *matrixVector.at( 2 ) );
477 int nCols = matrixVector.at( 0 )->nColumns();
478 int nRows = matrixVector.at( 0 )->nRows();
479 int nEntries = nCols * nRows;
480 auto dataResult = std::make_unique<double[]>( nEntries );
481 double *dataResultRawPtr = dataResult.get();
483 double *condition = matrixVector.at( 0 )->data();
484 double *firstOption = matrixVector.at( 1 )->data();
485 double *secondOption = matrixVector.at( 2 )->data();
487 bool isFirstOptionNumber = matrixVector.at( 1 )->isNumber();
488 bool isSecondCOptionNumber = matrixVector.at( 2 )->isNumber();
489 double noDataValueCondition = matrixVector.at( 0 )->nodataValue();
491 for (
int i = 0; i < nEntries; ++i )
493 if ( condition[i] == noDataValueCondition )
498 else if ( condition[i] != 0 )
500 dataResultRawPtr[i] = isFirstOptionNumber ? firstOption[0] : firstOption[i];
503 dataResultRawPtr[i] = isSecondCOptionNumber ? secondOption[0] : secondOption[i];
QString toString(bool cStyle=false) const
Returns a string representation of the expression.
Operator
possible operators
QgsRasterCalcNode()=default
QList< const QgsRasterCalcNode * > findNodes(const QgsRasterCalcNode::Type type) const
Returns a list of nodes of a specific type.
static QgsRasterCalcNode * parseRasterCalcString(const QString &str, QString &parserErrorMsg)
bool calculate(QMap< QString, QgsRasterBlock * > &rasterData, QgsRasterMatrix &result, int row=-1) const
Calculates result of raster calculation (might be real matrix or single number).
QStringList referencedLayerNames() const
Returns a list of raster layer names that are referenced in the formula without the quotation marks.
QStringList cleanRasterReferences() const
Returns a list of raster layer references that are addressed in the formula, without quotation marks.
Type
defines possible types of node
Represents a matrix in a raster calculator operation.
bool equal(const QgsRasterMatrix &other)
bool max(const QgsRasterMatrix &other)
Calculates the maximum value between two matrices.
bool greaterEqual(const QgsRasterMatrix &other)
double * takeData()
Returns data and ownership.
bool notEqual(const QgsRasterMatrix &other)
bool greaterThan(const QgsRasterMatrix &other)
bool logicalOr(const QgsRasterMatrix &other)
bool lesserEqual(const QgsRasterMatrix &other)
bool absoluteValue()
Calculates the absolute value.
bool logicalAnd(const QgsRasterMatrix &other)
bool lesserThan(const QgsRasterMatrix &other)
bool add(const QgsRasterMatrix &other)
Adds another matrix to this one.
bool multiply(const QgsRasterMatrix &other)
bool power(const QgsRasterMatrix &other)
double nodataValue() const
bool min(const QgsRasterMatrix &other)
Calculates the minimum value between two matrices.
bool divide(const QgsRasterMatrix &other)
void setData(int cols, int rows, double *data, double nodataValue)
bool subtract(const QgsRasterMatrix &other)
Subtracts another matrix from this one.
#define QgsDebugError(str)