68#include <QMimeDatabase>
69#include <QProcessEnvironment>
70#include <QCryptographicHash>
71#include <QRegularExpression>
94 QVariantList argValues;
98 const QList< QgsExpressionNode * > argList = args->
list();
105 v = QVariant::fromValue( n );
109 v = n->eval( parent, context );
111 bool defaultParamIsNull = mParameterList.count() > arg && mParameterList.at( arg ).optional() && !mParameterList.at( arg ).defaultValue().isValid();
112 if ( QgsExpressionUtils::isNull( v ) && !defaultParamIsNull && !
handlesNull() )
115 argValues.append( v );
120 return func( argValues, context, parent, node );
131 return QStringList();
158 return mGroups.isEmpty() ? false : mGroups.contains( QStringLiteral(
"deprecated" ) );
163 return ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 );
175 const QString &group,
176 const QString &helpText,
180 const QStringList &aliases,
184 , mAliases( aliases )
185 , mUsesGeometry( false )
186 , mUsesGeometryFunc( usesGeometry )
187 , mReferencedColumnsFunc( referencedColumns )
199 if ( mUsesGeometryFunc )
200 return mUsesGeometryFunc( node );
202 return mUsesGeometry;
212 if ( mReferencedColumnsFunc )
213 return mReferencedColumnsFunc( node );
215 return mReferencedColumns;
221 return mIsStaticFunc( node, parent, context );
229 return mPrepareFunc( node, parent, context );
241 mIsStaticFunc =
nullptr;
247 mPrepareFunc = prepareFunc;
252 if ( node && node->
args() )
254 const QList< QgsExpressionNode * > argList = node->
args()->
list();
257 if ( !argNode->isStatic( parent, context ) )
267 double start = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
268 double stop = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
269 double step = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
271 if ( step == 0.0 || ( step > 0.0 && start > stop ) || ( step < 0.0 && start < stop ) )
278 double current = start + step;
279 while ( ( ( step > 0.0 && current <= stop ) || ( step < 0.0 && current >= stop ) ) && length <= 1000000 )
294 const QString name = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
296 if ( name == QLatin1String(
"feature" ) )
298 return context->
hasFeature() ? QVariant::fromValue( context->
feature() ) : QVariant();
300 else if ( name == QLatin1String(
"id" ) )
302 return context->
hasFeature() ? QVariant::fromValue( context->
feature().
id() ) : QVariant();
304 else if ( name == QLatin1String(
"geometry" ) )
320 QString templateString = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
329 QString expString = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
331 return expression.evaluate( context );
336 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
337 return QVariant( std::sqrt( x ) );
342 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
343 return QVariant( std::fabs( val ) );
348 double deg = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
349 return ( deg * M_PI ) / 180;
353 double rad = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
354 return ( 180 * rad ) / M_PI;
358 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
359 return QVariant( std::sin( x ) );
363 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
364 return QVariant( std::cos( x ) );
368 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
369 return QVariant( std::tan( x ) );
373 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
374 return QVariant( std::asin( x ) );
378 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
379 return QVariant( std::acos( x ) );
383 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
384 return QVariant( std::atan( x ) );
388 double y = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
389 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
390 return QVariant( std::atan2( y, x ) );
394 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
395 return QVariant( std::exp( x ) );
399 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
402 return QVariant( std::log( x ) );
406 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
409 return QVariant( log10( x ) );
413 double b = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
414 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
415 if ( x <= 0 || b <= 0 )
417 return QVariant( std::log( x ) / std::log( b ) );
421 double min = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
422 double max = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
426 std::random_device rd;
427 std::mt19937_64 generator( rd() );
429 if ( !QgsExpressionUtils::isNull( values.at( 2 ) ) )
432 if ( QgsExpressionUtils::isIntSafe( values.at( 2 ) ) )
435 seed = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
440 QString seedStr = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
441 std::hash<std::string> hasher;
442 seed = hasher( seedStr.toStdString() );
444 generator.seed( seed );
448 double f =
static_cast< double >( generator() ) /
static_cast< double >( std::mt19937_64::max() );
449 return QVariant( min + f * ( max - min ) );
453 qlonglong min = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
454 qlonglong max = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
458 std::random_device rd;
459 std::mt19937_64 generator( rd() );
461 if ( !QgsExpressionUtils::isNull( values.at( 2 ) ) )
464 if ( QgsExpressionUtils::isIntSafe( values.at( 2 ) ) )
467 seed = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
472 QString seedStr = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
473 std::hash<std::string> hasher;
474 seed = hasher( seedStr.toStdString() );
476 generator.seed( seed );
479 qint64 randomInteger = min + ( generator() % ( max - min + 1 ) );
480 if ( randomInteger > std::numeric_limits<int>::max() || randomInteger < -std::numeric_limits<int>::max() )
481 return QVariant( randomInteger );
484 return QVariant(
int( randomInteger ) );
489 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
490 double domainMin = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
491 double domainMax = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
492 double rangeMin = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
493 double rangeMax = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
495 if ( domainMin >= domainMax )
497 parent->
setEvalErrorString( QObject::tr(
"Domain max must be greater than domain min" ) );
502 if ( val >= domainMax )
506 else if ( val <= domainMin )
512 double m = ( rangeMax - rangeMin ) / ( domainMax - domainMin );
513 double c = rangeMin - ( domainMin * m );
516 return QVariant( m * val +
c );
521 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
522 double domainMin = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
523 double domainMax = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
524 double rangeMin = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
525 double rangeMax = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
526 double exponent = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
528 if ( domainMin >= domainMax )
530 parent->
setEvalErrorString( QObject::tr(
"Domain max must be greater than domain min" ) );
540 if ( val >= domainMax )
544 else if ( val <= domainMin )
550 return QVariant( ( ( rangeMax - rangeMin ) / std::pow( domainMax - domainMin, exponent ) ) * std::pow( val - domainMin, exponent ) + rangeMin );
555 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
556 double domainMin = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
557 double domainMax = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
558 double rangeMin = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
559 double rangeMax = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
560 double exponent = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
562 if ( domainMin >= domainMax )
564 parent->
setEvalErrorString( QObject::tr(
"Domain max must be greater than domain min" ) );
574 if ( val >= domainMax )
578 else if ( val <= domainMin )
584 double ratio = ( std::pow( exponent, val - domainMin ) - 1 ) / ( std::pow( exponent, domainMax - domainMin ) - 1 );
585 return QVariant( ( rangeMax - rangeMin ) * ratio + rangeMin );
591 double maxVal = std::numeric_limits<double>::quiet_NaN();
592 for (
const QVariant &val : values )
595 if ( std::isnan( maxVal ) )
599 else if ( !std::isnan( testVal ) )
601 maxVal = std::max( maxVal, testVal );
605 if ( !std::isnan( maxVal ) )
607 result = QVariant( maxVal );
615 double minVal = std::numeric_limits<double>::quiet_NaN();
616 for (
const QVariant &val : values )
619 if ( std::isnan( minVal ) )
623 else if ( !std::isnan( testVal ) )
625 minVal = std::min( minVal, testVal );
629 if ( !std::isnan( minVal ) )
631 result = QVariant( minVal );
643 QVariant value = node->
eval( parent, context );
648 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( value, context, parent );
652 parent->
setEvalErrorString( QObject::tr(
"Cannot find layer with name or ID '%1'" ).arg( value.toString() ) );
657 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
659 value = node->
eval( parent, context );
665 parent->
setEvalErrorString( QObject::tr(
"No such aggregate '%1'" ).arg( value.toString() ) );
670 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
672 QString subExpression = node->
dump();
676 if ( values.count() > 3 )
678 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
681 if ( !nl || nl->value().isValid() )
686 if ( values.count() > 4 )
688 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
690 value = node->
eval( parent, context );
697 if ( values.count() > 5 )
699 node = QgsExpressionUtils::getNode( values.at( 5 ), parent );
702 if ( !nl || nl->value().isValid() )
704 orderBy = node->
dump();
709 QString aggregateError;
717 const QSet< QString > filterVars = filterExp.referencedVariables();
718 const QSet< QString > subExpVars = subExp.referencedVariables();
719 QSet<QString> allVars = filterVars + subExpVars;
721 bool isStatic =
true;
722 if ( filterVars.contains( QStringLiteral(
"parent" ) )
723 || filterVars.contains( QString() )
724 || subExpVars.contains( QStringLiteral(
"parent" ) )
725 || subExpVars.contains( QString() ) )
731 for (
const QString &varName : allVars )
734 if ( scope && !scope->
isStatic( varName ) )
742 if ( isStatic && ! parameters.
orderBy.isEmpty() )
744 for (
const auto &orderByClause : std::as_const( parameters.orderBy ) )
747 if ( orderByExpression.referencedVariables().contains( QStringLiteral(
"parent" ) ) || orderByExpression.referencedVariables().contains( QString() ) )
758 const QString contextHash = context->
uniqueHash( ok, allVars );
761 cacheKey = QStringLiteral(
"aggfcn:%1:%2:%3:%4:%5:%6" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter,
762 orderBy, contextHash );
767 cacheKey = QStringLiteral(
"aggfcn:%1:%2:%3:%4:%5" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter, orderBy );
778 subContext.appendScope( subScope );
779 result = vl->aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &aggregateError );
781 if ( ok && !cacheKey.isEmpty() )
791 result = vl->aggregate( aggregate, subExpression, parameters,
nullptr, &ok,
nullptr,
nullptr, &aggregateError );
795 if ( !aggregateError.isEmpty() )
796 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, aggregateError ) );
798 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
809 parent->
setEvalErrorString( QObject::tr(
"Cannot use relation aggregate function in this context" ) );
817 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
821 parent->
setEvalErrorString( QObject::tr(
"Cannot use relation aggregate function in this context" ) );
830 QVariant value = node->
eval( parent, context );
832 QString relationId = value.toString();
839 if ( relations.isEmpty() || relations.at( 0 ).referencedLayer() != vl )
841 parent->
setEvalErrorString( QObject::tr(
"Cannot find relation with id '%1'" ).arg( relationId ) );
846 relation = relations.at( 0 );
853 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
855 value = node->
eval( parent, context );
861 parent->
setEvalErrorString( QObject::tr(
"No such aggregate '%1'" ).arg( value.toString() ) );
866 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
868 QString subExpression = node->
dump();
872 if ( values.count() > 3 )
874 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
876 value = node->
eval( parent, context );
883 if ( values.count() > 4 )
885 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
888 if ( !nl || nl->value().isValid() )
890 orderBy = node->
dump();
901 const QString cacheKey = QStringLiteral(
"relagg:%1%:%2:%3:%4:%5:%6" ).arg( relationId, vl->id(),
902 QString::number(
static_cast< int >( aggregate ) ),
915 result = childLayer->
aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &error );
919 if ( !error.isEmpty() )
920 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, error ) );
922 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
936 parent->
setEvalErrorString( QObject::tr(
"Cannot use aggregate function in this context" ) );
944 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
948 parent->
setEvalErrorString( QObject::tr(
"Cannot use aggregate function in this context" ) );
957 QString subExpression = node->
dump();
961 if ( values.count() > 1 )
963 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
966 if ( !nl || nl->value().isValid() )
967 groupBy = node->
dump();
971 if ( values.count() > 2 )
973 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
976 if ( !nl || nl->value().isValid() )
982 if ( orderByPos >= 0 && values.count() > orderByPos )
984 node = QgsExpressionUtils::getNode( values.at( orderByPos ), parent );
987 if ( !nl || nl->value().isValid() )
989 orderBy = node->
dump();
997 if ( !groupBy.isEmpty() )
1000 QVariant groupByValue = groupByExp.evaluate( context );
1001 QString groupByClause = QStringLiteral(
"%1 %2 %3" ).arg( groupBy,
1004 if ( !parameters.
filter.isEmpty() )
1005 parameters.
filter = QStringLiteral(
"(%1) AND (%2)" ).arg( parameters.
filter, groupByClause );
1007 parameters.
filter = groupByClause;
1013 bool isStatic =
true;
1014 const QSet<QString> refVars = filterExp.referencedVariables() + subExp.referencedVariables();
1015 for (
const QString &varName : refVars )
1018 if ( scope && !scope->
isStatic( varName ) )
1029 const QString contextHash = context->
uniqueHash( ok, refVars );
1032 cacheKey = QStringLiteral(
"agg:%1:%2:%3:%4:%5:%6" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter,
1033 orderBy, contextHash );
1038 cacheKey = QStringLiteral(
"agg:%1:%2:%3:%4:%5" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter, orderBy );
1050 subContext.appendScope( subScope );
1052 result = vl->aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &error );
1056 if ( !error.isEmpty() )
1057 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, error ) );
1059 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
1164 if ( values.count() > 3 )
1166 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
1168 QVariant value = node->
eval( parent, context );
1170 parameters.
delimiter = value.toString();
1181 if ( values.count() > 3 )
1183 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
1185 QVariant value = node->
eval( parent, context );
1187 parameters.
delimiter = value.toString();
1203 QVariant scale = context->
variable( QStringLiteral(
"map_scale" ) );
1208 const double v = scale.toDouble( &ok );
1216 double minValue = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1217 double testValue = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1218 double maxValue = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1221 if ( testValue <= minValue )
1223 return QVariant( minValue );
1225 else if ( testValue >= maxValue )
1227 return QVariant( maxValue );
1231 return QVariant( testValue );
1237 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1238 return QVariant( std::floor( x ) );
1243 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1244 return QVariant( std::ceil( x ) );
1249 return QVariant( QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) );
1253 return QVariant( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) );
1257 return QVariant( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ) );
1262 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1263 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1264 if ( format.isEmpty() && !language.isEmpty() )
1266 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to DateTime when the language is specified" ) );
1267 return QVariant( QDateTime() );
1270 if ( format.isEmpty() && language.isEmpty() )
1271 return QVariant( QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent ) );
1273 QString datetimestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1274 QLocale locale = QLocale();
1275 if ( !language.isEmpty() )
1277 locale = QLocale( language );
1280 QDateTime datetime = locale.toDateTime( datetimestring, format );
1281 if ( !datetime.isValid() )
1283 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to DateTime" ).arg( datetimestring ) );
1284 datetime = QDateTime();
1286 return QVariant( datetime );
1291 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1292 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1293 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1295 const QDate date( year, month, day );
1296 if ( !date.isValid() )
1298 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1301 return QVariant( date );
1306 const int hours = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1307 const int minutes = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1308 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1310 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1311 if ( !time.isValid() )
1313 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1316 return QVariant( time );
1321 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1322 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1323 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1324 const int hours = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
1325 const int minutes = QgsExpressionUtils::getIntValue( values.at( 4 ), parent );
1326 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1328 const QDate date( year, month, day );
1329 if ( !date.isValid() )
1331 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1334 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1335 if ( !time.isValid() )
1337 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1340 return QVariant( QDateTime( date, time ) );
1345 const double years = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1346 const double months = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1347 const double weeks = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1348 const double days = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
1349 const double hours = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
1350 const double minutes = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1351 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
1353 return QVariant::fromValue(
QgsInterval( years, months, weeks, days, hours, minutes, seconds ) );
1358 for (
const QVariant &value : values )
1369 const QVariant val1 = values.at( 0 );
1370 const QVariant val2 = values.at( 1 );
1380 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1381 return QVariant(
str.toLower() );
1385 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1386 return QVariant(
str.toUpper() );
1390 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1391 QStringList elems =
str.split(
' ' );
1392 for (
int i = 0; i < elems.size(); i++ )
1394 if ( elems[i].size() > 1 )
1395 elems[i] = elems[i].at( 0 ).toUpper() + elems[i].mid( 1 ).toLower();
1397 return QVariant( elems.join( QLatin1Char(
' ' ) ) );
1402 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1403 return QVariant(
str.trimmed() );
1408 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1410 const QString characters = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1412 const QRegularExpression re( QStringLiteral(
"^([%1]*)" ).arg( QRegularExpression::escape( characters ) ) );
1413 str.replace( re, QString() );
1414 return QVariant(
str );
1419 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1421 const QString characters = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1423 const QRegularExpression re( QStringLiteral(
"([%1]*)$" ).arg( QRegularExpression::escape( characters ) ) );
1424 str.replace( re, QString() );
1425 return QVariant(
str );
1430 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1431 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1437 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1438 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1444 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1445 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1447 return ( dist < 0 ? QVariant() : QVariant(
QgsStringUtils::hammingDistance( string1, string2, true ) ) );
1452 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1458 QChar character = QChar( QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent ) );
1459 return QVariant( QString( character ) );
1464 QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1466 if ( value.isEmpty() )
1471 int res = value.at( 0 ).unicode();
1472 return QVariant( res );
1477 if ( values.length() == 2 || values.length() == 3 )
1479 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1480 qlonglong wrap = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1482 QString customdelimiter = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1495 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent,
true );
1499 return QVariant( geom.
length() );
1505 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1506 return QVariant(
str.length() );
1511 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
1516 double totalLength = 0;
1519 if (
const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( *it ) )
1521 totalLength += line->length3D();
1525 std::unique_ptr< QgsLineString > segmentized( qgsgeometry_cast< const QgsCurve * >( *it )->curveToLine() );
1526 totalLength += segmentized->length3D();
1535 if ( values.count() == 2 && values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
1537 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1538 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
1539 QVector< QPair< QString, QString > > mapItems;
1541 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
1543 mapItems.append( qMakePair( it.key(), it.value().toString() ) );
1547 std::sort( mapItems.begin(),
1549 [](
const QPair< QString, QString > &pair1,
1550 const QPair< QString, QString > &pair2 )
1552 return ( pair1.first.length() > pair2.first.length() );
1555 for (
auto it = mapItems.constBegin(); it != mapItems.constEnd(); ++it )
1557 str =
str.replace( it->first, it->second );
1560 return QVariant(
str );
1562 else if ( values.count() == 3 )
1564 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1565 QVariantList before;
1567 bool isSingleReplacement =
false;
1569 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).userType() != QMetaType::Type::QStringList )
1571 before = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1575 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
1578 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
1580 after = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1581 isSingleReplacement =
true;
1585 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
1588 if ( !isSingleReplacement && before.length() != after.length() )
1590 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
1594 for (
int i = 0; i < before.length(); i++ )
1596 str =
str.replace( before.at( i ).toString(), after.at( isSingleReplacement ? 0 : i ).toString() );
1599 return QVariant(
str );
1603 parent->
setEvalErrorString( QObject::tr(
"Function replace requires 2 or 3 arguments" ) );
1610 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1611 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1612 QString after = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1614 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1615 if ( !re.isValid() )
1617 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1620 return QVariant(
str.replace( re, after ) );
1625 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1626 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1628 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1629 if ( !re.isValid() )
1631 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1634 return QVariant( (
str.indexOf( re ) + 1 ) );
1639 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1640 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1641 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1643 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1644 if ( !re.isValid() )
1646 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1650 QRegularExpressionMatch matches = re.match(
str );
1651 if ( matches.hasMatch() )
1654 QStringList list = matches.capturedTexts();
1657 for ( QStringList::const_iterator it = ++list.constBegin(); it != list.constEnd(); ++it )
1659 array += ( !( *it ).isEmpty() ) ? *it : empty;
1662 return QVariant( array );
1672 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1673 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1675 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1676 if ( !re.isValid() )
1678 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1683 QRegularExpressionMatch match = re.match(
str );
1684 if ( match.hasMatch() )
1687 if ( match.lastCapturedIndex() > 0 )
1690 return QVariant( match.captured( 1 ) );
1695 return QVariant( match.captured( 0 ) );
1700 return QVariant(
"" );
1706 QString uuid = QUuid::createUuid().toString();
1707 if ( values.at( 0 ).toString().compare( QStringLiteral(
"WithoutBraces" ), Qt::CaseInsensitive ) == 0 )
1708 uuid = QUuid::createUuid().toString( QUuid::StringFormat::WithoutBraces );
1709 else if ( values.at( 0 ).toString().compare( QStringLiteral(
"Id128" ), Qt::CaseInsensitive ) == 0 )
1710 uuid = QUuid::createUuid().toString( QUuid::StringFormat::Id128 );
1716 if ( !values.at( 0 ).isValid() || !values.at( 1 ).isValid() )
1719 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1720 int from = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1723 if ( values.at( 2 ).isValid() )
1724 len = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
1730 from =
str.size() + from;
1736 else if ( from > 0 )
1744 len =
str.size() + len - from;
1751 return QVariant(
str.mid( from, len ) );
1757 return QVariant(
static_cast< int >( f.
id() ) );
1762 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1763 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
1764 bool foundLayer =
false;
1765 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, geom](
QgsMapLayer * mapLayer )
1767 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer * >( mapLayer );
1768 if ( !layer || !layer->dataProvider() )
1770 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1774 if ( bandNb < 1 || bandNb > layer->bandCount() )
1776 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster band number." ) );
1782 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid point geometry." ) );
1790 if ( multiPoint.count() == 1 )
1792 point = multiPoint[0];
1801 double value = layer->dataProvider()->sample( point, bandNb );
1802 return std::isnan( value ) ? QVariant() : value;
1808 parent->
setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1819 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1820 const double value = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1822 bool foundLayer =
false;
1823 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, value](
QgsMapLayer * mapLayer )-> QVariant
1825 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer *>( mapLayer );
1826 if ( !layer || !layer->dataProvider() )
1828 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1832 if ( bandNb < 1 || bandNb > layer->bandCount() )
1834 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster band number." ) );
1838 if ( std::isnan( value ) )
1840 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster value." ) );
1844 if ( ! layer->dataProvider()->attributeTable( bandNb ) )
1849 const QVariantList data = layer->dataProvider()->attributeTable( bandNb )->row( value );
1850 if ( data.isEmpty() )
1856 const QList<QgsRasterAttributeTable::Field> fields { layer->dataProvider()->attributeTable( bandNb )->fields() };
1857 for (
int idx = 0; idx < static_cast<int>( fields.count( ) ) && idx < static_cast<int>( data.count() ); ++idx )
1860 if ( field.isColor() || field.isRamp() )
1864 result.insert( fields.at( idx ).name, data.at( idx ) );
1872 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1893 if ( values.size() == 1 )
1895 attr = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1898 else if ( values.size() == 2 )
1900 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
1901 attr = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1905 parent->
setEvalErrorString( QObject::tr(
"Function `attribute` requires one or two parameters. %n given.",
nullptr, values.length() ) );
1914 QString table { R
"html(
1917 <tr><th>%1</th></tr>
1920 <tr><td>%2</td></tr>
1924 if ( values.size() == 1 )
1926 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1930 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_table` requires one parameter. %n given.",
nullptr, values.length() ) );
1934 if ( dict.isEmpty() )
1939 QStringList headers;
1942 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
1944 headers.push_back( it.key().toHtmlEscaped() );
1945 cells.push_back( it.value().toString( ).toHtmlEscaped() );
1948 return table.arg( headers.join( QLatin1String(
"</th><th>" ) ), cells.join( QLatin1String(
"</td><td>" ) ) );
1953 QString table { R
"html(
1958 if ( values.size() == 1 )
1960 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1964 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_dl` requires one parameter. %n given.",
nullptr, values.length() ) );
1968 if ( dict.isEmpty() )
1975 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
1977 rows.append( QStringLiteral(
"<dt>%1</dt><dd>%2</dd>" ).arg( it.key().toHtmlEscaped(), it.value().toString().toHtmlEscaped() ) );
1980 return table.arg( rows );
1988 layer = context->
variable( QStringLiteral(
"layer" ) );
1993 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
1995 layer = node->
eval( parent, context );
2006 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2010 const QString strength = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).toLower();
2011 if ( strength == QLatin1String(
"hard" ) )
2015 else if ( strength == QLatin1String(
"soft" ) )
2020 bool foundLayer =
false;
2021 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
2023 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2026 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2032 for (
int i = 0; i < fields.
size(); i++ )
2047 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2059 layer = context->
variable( QStringLiteral(
"layer" ) );
2064 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
2066 layer = node->
eval( parent, context );
2077 feature = QgsExpressionUtils::getFeature( values.at( 2 ), parent );
2081 const QString strength = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).toLower();
2082 if ( strength == QLatin1String(
"hard" ) )
2086 else if ( strength == QLatin1String(
"soft" ) )
2091 const QString attributeName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2093 bool foundLayer =
false;
2094 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, attributeName, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
2096 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2103 if ( fieldIndex == -1 )
2105 parent->
setEvalErrorString( QObject::tr(
"The attribute name did not match any field for the given feature" ) );
2116 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2132 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2137 for (
int i = 0; i < fields.
count(); ++i )
2151 if ( values.isEmpty() )
2154 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2156 else if ( values.size() == 1 )
2158 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2159 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2161 else if ( values.size() == 2 )
2163 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2164 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2168 parent->
setEvalErrorString( QObject::tr(
"Function `represent_attributes` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2175 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: layer could not be resolved." ) );
2181 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: feature could not be resolved." ) );
2187 for (
int fieldIndex = 0; fieldIndex < fields.
count(); ++fieldIndex )
2189 const QString fieldName { fields.
at( fieldIndex ).
name() };
2190 const QVariant attributeVal = feature.
attribute( fieldIndex );
2191 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer->
id(), fieldName, attributeVal.toString() );
2194 result.insert( fieldName, context->
cachedValue( cacheValueKey ) );
2203 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer->
id(), fieldName );
2215 QString value( fieldFormatter->
representValue( layer, fieldIndex, setup.
config(), cache, attributeVal ) );
2217 result.insert( fields.
at( fieldIndex ).
name(), value );
2233 bool evaluate =
true;
2237 if ( values.isEmpty() )
2240 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2242 else if ( values.size() == 1 )
2244 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2245 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2247 else if ( values.size() == 2 )
2249 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2250 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2252 else if ( values.size() == 3 )
2254 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2255 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2256 evaluate = values.value( 2 ).toBool();
2262 parent->
setEvalErrorString( QObject::tr(
"Function `maptip` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2266 parent->
setEvalErrorString( QObject::tr(
"Function `display` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2298 subContext.setFeature( feature );
2307 exp.prepare( &subContext );
2308 return exp.evaluate( &subContext ).toString();
2314 return fcnCoreFeatureMaptipDisplay( values, context, parent,
false );
2319 return fcnCoreFeatureMaptipDisplay( values, context, parent,
true );
2326 if ( values.isEmpty() )
2329 layer = context->
variable( QStringLiteral(
"layer" ) );
2331 else if ( values.size() == 1 )
2333 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2334 layer = context->
variable( QStringLiteral(
"layer" ) );
2336 else if ( values.size() == 2 )
2338 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2339 layer = values.at( 0 );
2343 parent->
setEvalErrorString( QObject::tr(
"Function `is_selected` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2347 bool foundLayer =
false;
2348 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [feature](
QgsMapLayer * mapLayer ) -> QVariant
2350 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2351 if ( !layer || !feature.
isValid() )
2368 if ( values.isEmpty() )
2369 layer = context->
variable( QStringLiteral(
"layer" ) );
2370 else if ( values.count() == 1 )
2371 layer = values.at( 0 );
2374 parent->
setEvalErrorString( QObject::tr(
"Function `num_selected` requires no more than one parameter. %n given.",
nullptr, values.length() ) );
2378 bool foundLayer =
false;
2379 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [](
QgsMapLayer * mapLayer ) -> QVariant
2381 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2397 static QMap<QString, qlonglong> counterCache;
2398 QVariant functionResult;
2400 auto fetchAndIncrementFunc = [ values, parent, &functionResult ](
QgsMapLayer * mapLayer,
const QString & databaseArgument )
2404 const QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( mapLayer );
2409 database = decodedUri.value( QStringLiteral(
"path" ) ).toString();
2410 if ( database.isEmpty() )
2412 parent->
setEvalErrorString( QObject::tr(
"Could not extract file path from layer `%1`." ).arg( layer->
name() ) );
2417 database = databaseArgument;
2420 const QString table = values.at( 1 ).toString();
2421 const QString idColumn = values.at( 2 ).toString();
2422 const QString filterAttribute = values.at( 3 ).toString();
2423 const QVariant filterValue = values.at( 4 ).toString();
2424 const QVariantMap defaultValues = values.at( 5 ).toMap();
2430 if ( sqliteDb.
open_v2( database, SQLITE_OPEN_READWRITE,
nullptr ) != SQLITE_OK )
2433 functionResult = QVariant();
2437 QString errorMessage;
2438 QString currentValSql;
2440 qlonglong nextId = 0;
2441 bool cachedMode =
false;
2442 bool valueRetrieved =
false;
2444 QString cacheString = QStringLiteral(
"%1:%2:%3:%4:%5" ).arg( database, table, idColumn, filterAttribute, filterValue.toString() );
2451 auto cachedCounter = counterCache.find( cacheString );
2453 if ( cachedCounter != counterCache.end() )
2455 qlonglong &cachedValue = cachedCounter.value();
2456 nextId = cachedValue;
2458 cachedValue = nextId;
2459 valueRetrieved =
true;
2464 if ( !cachedMode || !valueRetrieved )
2466 int result = SQLITE_ERROR;
2469 if ( !filterAttribute.isNull() )
2474 sqliteStatement = sqliteDb.
prepare( currentValSql, result );
2476 if ( result == SQLITE_OK )
2479 if ( sqliteStatement.
step() == SQLITE_ROW )
2485 if ( cachedMode && result == SQLITE_OK )
2487 counterCache.insert( cacheString, nextId );
2491 counterCache.remove( cacheString );
2494 valueRetrieved =
true;
2498 if ( valueRetrieved )
2507 if ( !filterAttribute.isNull() )
2513 for ( QVariantMap::const_iterator iter = defaultValues.constBegin(); iter != defaultValues.constEnd(); ++iter )
2516 vals << iter.value().toString();
2519 upsertSql += QLatin1String(
" (" ) + cols.join(
',' ) +
')';
2520 upsertSql += QLatin1String(
" VALUES " );
2521 upsertSql +=
'(' + vals.join(
',' ) +
')';
2523 int result = SQLITE_ERROR;
2527 if ( transaction->
executeSql( upsertSql, errorMessage ) )
2534 result = sqliteDb.
exec( upsertSql, errorMessage );
2536 if ( result == SQLITE_OK )
2538 functionResult = QVariant( nextId );
2543 parent->
setEvalErrorString( QStringLiteral(
"Could not increment value: SQLite error: \"%1\" (%2)." ).arg( errorMessage, QString::number( result ) ) );
2544 functionResult = QVariant();
2549 functionResult = QVariant();
2552 bool foundLayer =
false;
2553 QgsExpressionUtils::executeLambdaForMapLayer( values.at( 0 ), context, parent, [&fetchAndIncrementFunc](
QgsMapLayer * layer )
2555 fetchAndIncrementFunc( layer, QString() );
2559 const QString databasePath = values.at( 0 ).toString();
2562 fetchAndIncrementFunc(
nullptr, databasePath );
2566 return functionResult;
2572 for (
const QVariant &value : values )
2575 concat += QgsExpressionUtils::getStringValue( value, parent );
2582 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2583 return string.indexOf( QgsExpressionUtils::getStringValue( values.at( 1 ), parent ) ) + 1;
2588 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2589 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2590 return string.right( pos );
2595 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2596 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2597 return string.left( pos );
2602 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2603 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2604 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2605 return string.leftJustified( length, fill.at( 0 ),
true );
2610 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2611 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2612 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2613 return string.rightJustified( length, fill.at( 0 ),
true );
2618 if ( values.size() < 1 )
2620 parent->
setEvalErrorString( QObject::tr(
"Function format requires at least 1 argument" ) );
2624 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2625 for (
int n = 1; n < values.length(); n++ )
2627 string =
string.arg( QgsExpressionUtils::getStringValue( values.at( n ), parent ) );
2635 return QVariant( QDateTime::currentDateTime() );
2640 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2641 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2642 if ( format.isEmpty() && !language.isEmpty() )
2644 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Date when the language is specified" ) );
2645 return QVariant( QDate() );
2648 if ( format.isEmpty() && language.isEmpty() )
2649 return QVariant( QgsExpressionUtils::getDateValue( values.at( 0 ), parent ) );
2651 QString datestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2652 QLocale locale = QLocale();
2653 if ( !language.isEmpty() )
2655 locale = QLocale( language );
2658 QDate date = locale.toDate( datestring, format );
2659 if ( !date.isValid() )
2661 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Date" ).arg( datestring ) );
2664 return QVariant( date );
2669 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2670 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2671 if ( format.isEmpty() && !language.isEmpty() )
2673 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Time when the language is specified" ) );
2674 return QVariant( QTime() );
2677 if ( format.isEmpty() && language.isEmpty() )
2678 return QVariant( QgsExpressionUtils::getTimeValue( values.at( 0 ), parent ) );
2680 QString timestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2681 QLocale locale = QLocale();
2682 if ( !language.isEmpty() )
2684 locale = QLocale( language );
2687 QTime time = locale.toTime( timestring, format );
2688 if ( !time.isValid() )
2690 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Time" ).arg( timestring ) );
2693 return QVariant( time );
2698 return QVariant::fromValue( QgsExpressionUtils::getInterval( values.at( 0 ), parent ) );
2707 double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
2708 QString axis = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2709 int precision = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
2711 QString formatString;
2712 if ( values.count() > 3 )
2713 formatString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
2716 if ( formatString.compare( QLatin1String(
"suffix" ), Qt::CaseInsensitive ) == 0 )
2720 else if ( formatString.compare( QLatin1String(
"aligned" ), Qt::CaseInsensitive ) == 0 )
2724 else if ( ! formatString.isEmpty() )
2726 parent->
setEvalErrorString( QObject::tr(
"Invalid formatting parameter: '%1'. It must be empty, or 'suffix' or 'aligned'." ).arg( formatString ) );
2730 if ( axis.compare( QLatin1String(
"x" ), Qt::CaseInsensitive ) == 0 )
2734 else if ( axis.compare( QLatin1String(
"y" ), Qt::CaseInsensitive ) == 0 )
2740 parent->
setEvalErrorString( QObject::tr(
"Invalid axis name: '%1'. It must be either 'x' or 'y'." ).arg( axis ) );
2748 return floatToDegreeFormat( format, values, context, parent, node );
2755 value = QgsCoordinateUtils::dmsToDecimal( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), &ok );
2757 return ok ? QVariant( value ) : QVariant();
2763 return floatToDegreeFormat( format, values, context, parent, node );
2768 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2769 QDateTime d2 = QgsExpressionUtils::getDateTimeValue( values.at( 1 ), parent );
2770 qint64 seconds = d2.secsTo( d1 );
2771 return QVariant::fromValue(
QgsInterval( seconds ) );
2776 if ( !values.at( 0 ).canConvert<QDate>() )
2779 QDate date = QgsExpressionUtils::getDateValue( values.at( 0 ), parent );
2780 if ( !date.isValid() )
2785 return date.dayOfWeek() % 7;
2790 QVariant value = values.at( 0 );
2791 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2794 return QVariant( inter.
days() );
2798 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2799 return QVariant( d1.date().day() );
2805 QVariant value = values.at( 0 );
2806 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2809 return QVariant( inter.
years() );
2813 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2814 return QVariant( d1.date().year() );
2820 QVariant value = values.at( 0 );
2821 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2824 return QVariant( inter.
months() );
2828 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2829 return QVariant( d1.date().month() );
2835 QVariant value = values.at( 0 );
2836 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2839 return QVariant( inter.
weeks() );
2843 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2844 return QVariant( d1.date().weekNumber() );
2850 QVariant value = values.at( 0 );
2851 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2854 return QVariant( inter.
hours() );
2858 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2859 return QVariant( t1.hour() );
2865 QVariant value = values.at( 0 );
2866 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2869 return QVariant( inter.
minutes() );
2873 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2874 return QVariant( t1.minute() );
2880 QVariant value = values.at( 0 );
2881 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2884 return QVariant( inter.
seconds() );
2888 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2889 return QVariant( t1.second() );
2895 QDateTime dt = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2898 return QVariant( dt.toMSecsSinceEpoch() );
2908 long long millisecs_since_epoch = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
2910 return QVariant( QDateTime::fromMSecsSinceEpoch( millisecs_since_epoch ) );
2915 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2918 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif" ) ) );
2921 QString tag = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2927 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2930 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif_geotag" ) ) );
2937#define ENSURE_GEOM_TYPE(f, g, geomtype) \
2938 if ( !(f).hasGeometry() ) \
2939 return QVariant(); \
2940 QgsGeometry g = (f).geometry(); \
2941 if ( (g).type() != (geomtype) ) \
2948 if ( g.isMultipart() )
2950 return g.asMultiPoint().at( 0 ).x();
2954 return g.asPoint().x();
2962 if ( g.isMultipart() )
2964 return g.asMultiPoint().at( 0 ).y();
2968 return g.asPoint().y();
2982 if ( g.isEmpty() || !abGeom->
is3D() )
2987 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( g.constGet() );
2993 if (
const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( g.constGet() ) )
2995 if ( collection->numGeometries() > 0 )
2997 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3008 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3014 return QVariant( isValid );
3019 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3023 const QString methodString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).trimmed();
3024#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
3029 if ( methodString.compare( QLatin1String(
"linework" ), Qt::CaseInsensitive ) == 0 )
3031 else if ( methodString.compare( QLatin1String(
"structure" ), Qt::CaseInsensitive ) == 0 )
3034 const bool keepCollapsed = values.value( 2 ).toBool();
3039 valid = geom.
makeValid( method, keepCollapsed );
3043 parent->
setEvalErrorString( QObject::tr(
"The make_valid parameters require a newer GEOS library version" ) );
3047 return QVariant::fromValue( valid );
3052 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3058 for (
int i = 0; i < multiGeom.size(); ++i )
3060 array += QVariant::fromValue( multiGeom.at( i ) );
3068 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3080 QVariant result( centroid.asPoint().
x() );
3086 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3098 QVariant result( centroid.asPoint().
y() );
3104 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3114 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3122 if ( collection->numGeometries() == 1 )
3124 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3135 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3145 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3153 if ( collection->numGeometries() == 1 )
3155 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3166 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3171 int idx = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
3198 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3215 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3232 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3237 bool ignoreClosing =
false;
3238 if ( values.length() > 1 )
3240 ignoreClosing = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3250 bool skipLast =
false;
3251 if ( ignoreClosing && ring.count() > 2 && ring.first() == ring.last() )
3256 for (
int i = 0; i < ( skipLast ? ring.count() - 1 : ring.count() ); ++ i )
3268 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3279 for (
int i = 0; i < line->numPoints() - 1; ++i )
3283 << line->pointN( i )
3284 << line->pointN( i + 1 ) );
3295 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3305 if ( collection->numGeometries() == 1 )
3307 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->geometryN( 0 ) );
3312 if ( !curvePolygon )
3316 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3322 QVariant result = curve ? QVariant::fromValue(
QgsGeometry( curve ) ) : QVariant();
3328 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3338 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3344 QVariant result = part ? QVariant::fromValue(
QgsGeometry( part ) ) : QVariant();
3350 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3359 return QVariant::fromValue(
QgsGeometry( boundary ) );
3364 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3373 return QVariant::fromValue( merged );
3378 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3382 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3387 if ( sharedPaths.
isNull() )
3390 return QVariant::fromValue( sharedPaths );
3396 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3401 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3404 if ( simplified.
isNull() )
3412 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3417 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3422 if ( simplified.
isNull() )
3430 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3435 int iterations = std::min( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), 10 );
3436 double offset = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0.0, 0.5 );
3437 double minLength = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3438 double maxAngle = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ), 0.0, 180.0 );
3440 QgsGeometry smoothed = geom.
smooth(
static_cast<unsigned int>( iterations ), offset, minLength, maxAngle );
3449 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3454 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3455 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3456 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3467 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3472 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3473 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3474 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3475 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3476 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3479 minAmplitude, maxAmplitude, seed );
3488 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3493 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3494 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3495 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3506 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3511 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3512 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3513 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3514 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3515 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3518 minAmplitude, maxAmplitude, seed );
3527 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3532 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3533 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3534 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3545 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3550 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3551 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3552 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3553 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3554 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3557 minAmplitude, maxAmplitude, seed );
3566 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3571 const QVariantList pattern = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
3572 QVector< double > dashPattern;
3573 dashPattern.reserve( pattern.size() );
3574 for (
const QVariant &value : std::as_const( pattern ) )
3577 double v = value.toDouble( &ok );
3584 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must be an array of numbers" ) );
3589 if ( dashPattern.size() % 2 != 0 )
3591 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must contain an even number of elements" ) );
3595 const QString startRuleString = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).trimmed();
3597 if ( startRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3599 else if ( startRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3601 else if ( startRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3603 else if ( startRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3605 else if ( startRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3609 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( startRuleString ) );
3613 const QString endRuleString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
3615 if ( endRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3617 else if ( endRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3619 else if ( endRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3621 else if ( endRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3623 else if ( endRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3627 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( endRuleString ) );
3631 const QString adjustString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
3633 if ( adjustString.compare( QLatin1String(
"both" ), Qt::CaseInsensitive ) == 0 )
3635 else if ( adjustString.compare( QLatin1String(
"dash" ), Qt::CaseInsensitive ) == 0 )
3637 else if ( adjustString.compare( QLatin1String(
"gap" ), Qt::CaseInsensitive ) == 0 )
3641 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern size adjustment" ).arg( adjustString ) );
3645 const double patternOffset = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
3656 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3661 const long long count = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3663 if ( densified.
isNull() )
3671 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3676 const double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3678 if ( densified.
isNull() )
3687 if ( values.size() == 1 && QgsExpressionUtils::isList( values.at( 0 ) ) )
3689 list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
3696 QVector< QgsGeometry > parts;
3697 parts.reserve( list.size() );
3698 for (
const QVariant &value : std::as_const( list ) )
3700 QgsGeometry part = QgsExpressionUtils::getGeometry( value, parent );
3711 if ( values.count() < 2 || values.count() > 4 )
3713 parent->
setEvalErrorString( QObject::tr(
"Function make_point requires 2-4 arguments" ) );
3717 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3718 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3719 double z = values.count() >= 3 ? QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) : 0.0;
3720 double m = values.count() >= 4 ? QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) : 0.0;
3721 switch ( values.count() )
3735 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3736 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3737 double m = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3743 if ( values.empty() )
3748 QVector<QgsPoint> points;
3749 points.reserve( values.count() );
3751 auto addPoint = [&points](
const QgsGeometry & geom )
3759 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3766 for (
const QVariant &value : values )
3768 if ( value.userType() == QMetaType::Type::QVariantList )
3770 const QVariantList list = value.toList();
3771 for (
const QVariant &v : list )
3773 addPoint( QgsExpressionUtils::getGeometry( v, parent ) );
3778 addPoint( QgsExpressionUtils::getGeometry( value, parent ) );
3782 if ( points.count() < 2 )
3790 if ( values.count() < 1 )
3792 parent->
setEvalErrorString( QObject::tr(
"Function make_polygon requires an argument" ) );
3796 QgsGeometry outerRing = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3804 std::unique_ptr< QgsPolygon > polygon = std::make_unique< QgsPolygon >();
3806 const QgsCurve *exteriorRing = qgsgeometry_cast< QgsCurve * >( outerRing.
constGet() );
3813 exteriorRing = qgsgeometry_cast< QgsCurve * >( collection->
geometryN( 0 ) );
3818 if ( !exteriorRing )
3821 polygon->setExteriorRing( exteriorRing->
segmentize() );
3824 for (
int i = 1; i < values.count(); ++i )
3826 QgsGeometry ringGeom = QgsExpressionUtils::getGeometry( values.at( i ), parent );
3833 const QgsCurve *ring = qgsgeometry_cast< QgsCurve * >( ringGeom.
constGet() );
3840 ring = qgsgeometry_cast< QgsCurve * >( collection->
geometryN( 0 ) );
3848 polygon->addInteriorRing( ring->
segmentize() );
3851 return QVariant::fromValue(
QgsGeometry( std::move( polygon ) ) );
3856 std::unique_ptr<QgsTriangle> tr(
new QgsTriangle() );
3857 std::unique_ptr<QgsLineString> lineString(
new QgsLineString() );
3858 lineString->clear();
3860 for (
const QVariant &value : values )
3862 QgsGeometry geom = QgsExpressionUtils::getGeometry( value, parent );
3869 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3876 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3884 lineString->addVertex( *point );
3887 tr->setExteriorRing( lineString.release() );
3889 return QVariant::fromValue(
QgsGeometry( tr.release() ) );
3894 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3901 double radius = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3902 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
3909 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3916 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3924 return QVariant::fromValue(
QgsGeometry( circ.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
3929 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3936 double majorAxis = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3937 double minorAxis = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3938 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3939 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 4 ), parent );
3945 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3952 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3959 QgsEllipse elp( *point, majorAxis, minorAxis, azimuth );
3960 return QVariant::fromValue(
QgsGeometry( elp.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
3966 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3973 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3980 unsigned int nbEdges =
static_cast<unsigned int>( QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) );
3983 parent->
setEvalErrorString( QObject::tr(
"Number of edges/sides must be greater than 2" ) );
3990 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (inscribed) or 1 (circumscribed)" ) );
3994 const QgsPoint *center = qgsgeometry_cast< const QgsPoint * >( pt1.
constGet() );
4001 center = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4008 const QgsPoint *corner = qgsgeometry_cast< const QgsPoint * >( pt2.
constGet() );
4015 corner = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4030 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4036 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4042 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
4043 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
4051 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4057 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4063 QgsGeometry pt3 = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
4072 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (distance) or 1 (projected)" ) );
4075 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
4076 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
4077 const QgsPoint *point3 = qgsgeometry_cast< const QgsPoint *>( pt3.
constGet() );
4096 return QVariant::fromValue( geom.
vertexAt( idx ) );
4104 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4106 const QVariant v = pointAt( geom, idx, parent );
4109 return QVariant( v.value<
QgsPoint>().
x() );
4115 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4117 return fcnOldXat( values, f, parent, node );
4119 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4121 return fcnOldXat( QVariantList() << values[1], f, parent, node );
4124 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4130 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4132 const QVariant v = pointAt( geom, vertexNumber, parent );
4134 return QVariant( v.value<
QgsPoint>().
x() );
4144 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4146 const QVariant v = pointAt( geom, idx, parent );
4149 return QVariant( v.value<
QgsPoint>().
y() );
4155 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4157 return fcnOldYat( values, f, parent, node );
4159 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4161 return fcnOldYat( QVariantList() << values[1], f, parent, node );
4164 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4170 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4172 const QVariant v = pointAt( geom, vertexNumber, parent );
4174 return QVariant( v.value<
QgsPoint>().
y() );
4181 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4187 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4189 const QVariant v = pointAt( geom, vertexNumber, parent );
4191 return QVariant( v.value<
QgsPoint>().
z() );
4198 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4204 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4206 const QVariant v = pointAt( geom, vertexNumber, parent );
4208 return QVariant( v.value<
QgsPoint>().
m() );
4227 return QVariant::fromValue( geom );
4235 QString wkt = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4237 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4243 const QByteArray wkb = QgsExpressionUtils::getBinaryValue( values.at( 0 ), parent );
4249 return !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4254 QString gml = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4261 ogcContext.
layer = mapLayerPtr.data();
4262 ogcContext.
transformContext = context->
variable( QStringLiteral(
"_project_transform_context" ) ).value<QgsCoordinateTransformContext>();
4266 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4281 return QVariant( area );
4285 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating area" ) );
4297 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4302 return QVariant( geom.
area() );
4316 return QVariant( len );
4320 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating length" ) );
4341 return QVariant( len );
4345 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating perimeter" ) );
4351 return f.
geometry().
isNull() ? QVariant( 0 ) : QVariant( f.geometry().constGet()->perimeter() );
4357 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4363 return QVariant( geom.
length() );
4368 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4369 return QVariant( geom.
isNull() ? 0 : geom.constGet()->nCoordinates() );
4374 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4383 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4392 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4407 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon *>( collection->
geometryN( i ) );
4408 if ( !curvePolygon )
4411 return QVariant( curvePolygon->
isEmpty() ? 0 : curvePolygon->numInteriorRings() );
4420 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4427 return QVariant( curvePolygon->
ringCount() );
4429 bool foundPoly =
false;
4437 curvePolygon = qgsgeometry_cast< QgsCurvePolygon *>( collection->
geometryN( i ) );
4438 if ( !curvePolygon )
4449 return QVariant( ringCount );
4454 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4456 QVariant result = !geomBounds.
isNull() ? QVariant::fromValue( geomBounds ) : QVariant();
4462 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4468 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4474 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4483 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4489 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4495 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4501 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4507 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4515 double max = std::numeric_limits< double >::lowest();
4519 double z = ( *it ).z();
4525 if ( max == std::numeric_limits< double >::lowest() )
4528 return QVariant( max );
4533 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4541 double min = std::numeric_limits< double >::max();
4545 double z = ( *it ).z();
4551 if ( min == std::numeric_limits< double >::max() )
4554 return QVariant( min );
4559 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4567 double min = std::numeric_limits< double >::max();
4571 double m = ( *it ).m();
4577 if ( min == std::numeric_limits< double >::max() )
4580 return QVariant( min );
4585 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4593 double max = std::numeric_limits< double >::lowest();
4597 double m = ( *it ).m();
4603 if ( max == std::numeric_limits< double >::lowest() )
4606 return QVariant( max );
4611 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4612 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom.
constGet() );
4615 parent->
setEvalErrorString( QObject::tr(
"Function `sinuosity` requires a line geometry." ) );
4624 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4628 parent->
setEvalErrorString( QObject::tr(
"Function `straight_distance_2d` requires a line geometry or a multi line geometry with a single part." ) );
4637 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4642 parent->
setEvalErrorString( QObject::tr(
"Function `roundness` requires a polygon geometry or a multi polygon geometry with a single part." ) );
4653 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4657 std::unique_ptr< QgsAbstractGeometry > flipped( geom.
constGet()->
clone() );
4659 return QVariant::fromValue(
QgsGeometry( std::move( flipped ) ) );
4664 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4668 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( fGeom.
constGet() );
4675 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
4683 return QVariant::fromValue( curve->
isClosed() );
4688 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4701 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4702 closedLine->close();
4704 result = QVariant::fromValue(
QgsGeometry( std::move( closedLine ) ) );
4714 if (
const QgsLineString *line = qgsgeometry_cast<const QgsLineString * >( collection->
geometryN( i ) ) )
4716 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4717 closedLine->close();
4719 closed->addGeometry( closedLine.release() );
4722 result = QVariant::fromValue(
QgsGeometry( std::move( closed ) ) );
4730 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4734 return QVariant::fromValue( fGeom.
isEmpty() );
4740 return QVariant::fromValue(
true );
4742 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4743 return QVariant::fromValue( fGeom.
isNull() || fGeom.
isEmpty() );
4748 if ( values.length() < 2 || values.length() > 3 )
4751 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4752 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4759 if ( values.length() == 2 )
4762 QString result = engine->relate( sGeom.
constGet() );
4763 return QVariant::fromValue( result );
4768 QString pattern = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
4769 bool result = engine->relatePattern( sGeom.
constGet(), pattern );
4770 return QVariant::fromValue( result );
4776 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4777 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4782 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4783 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4784 return fGeom.
disjoint( sGeom ) ? TVL_True : TVL_False;
4788 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4789 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4790 return fGeom.
intersects( sGeom ) ? TVL_True : TVL_False;
4794 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4795 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4796 return fGeom.
touches( sGeom ) ? TVL_True : TVL_False;
4800 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4801 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4802 return fGeom.
crosses( sGeom ) ? TVL_True : TVL_False;
4806 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4807 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4808 return fGeom.
contains( sGeom ) ? TVL_True : TVL_False;
4812 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4813 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4814 return fGeom.
overlaps( sGeom ) ? TVL_True : TVL_False;
4818 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4819 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4820 return fGeom.
within( sGeom ) ? TVL_True : TVL_False;
4825 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4826 const double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4827 const int seg = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4828 const QString endCapString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
4829 const QString joinString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
4830 const double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
4833 if ( endCapString.compare( QLatin1String(
"flat" ), Qt::CaseInsensitive ) == 0 )
4835 else if ( endCapString.compare( QLatin1String(
"square" ), Qt::CaseInsensitive ) == 0 )
4839 if ( joinString.compare( QLatin1String(
"miter" ), Qt::CaseInsensitive ) == 0 )
4841 else if ( joinString.compare( QLatin1String(
"bevel" ), Qt::CaseInsensitive ) == 0 )
4845 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4851 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4853 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4858 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4860 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4865 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4867 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4872 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4873 const QgsPoint *pt = qgsgeometry_cast<const QgsPoint *>( fGeom.
constGet() );
4880 pt = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4887 parent->
setEvalErrorString( QObject::tr(
"Function `wedge_buffer` requires a point value for the center." ) );
4891 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4892 double width = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4893 double outerRadius = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4894 double innerRadius = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
4897 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4903 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4906 parent->
setEvalErrorString( QObject::tr(
"Function `tapered_buffer` requires a line geometry." ) );
4910 double startWidth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4911 double endWidth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4912 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) );
4915 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4921 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4924 parent->
setEvalErrorString( QObject::tr(
"Function `buffer_by_m` requires a line geometry." ) );
4928 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) );
4931 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4937 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4938 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4939 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4940 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4941 if ( joinInt < 1 || joinInt > 3 )
4945 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4948 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4954 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4955 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4956 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4958 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4959 if ( joinInt < 1 || joinInt > 3 )
4963 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4966 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4972 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4973 double distStart = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4974 double distEnd = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4977 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4983 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4984 double dx = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4985 double dy = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4987 return QVariant::fromValue( fGeom );
4992 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4993 const double rotation = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4994 const QgsGeometry center = values.at( 2 ).
isValid() ? QgsExpressionUtils::getGeometry( values.at( 2 ), parent )
4996 const bool perPart = values.value( 3 ).toBool();
5003 std::unique_ptr< QgsGeometryCollection > collection( qgsgeometry_cast< QgsGeometryCollection * >( fGeom.
constGet()->
clone() ) );
5006 const QgsPointXY partCenter = ( *it )->boundingBox().center();
5007 QTransform t = QTransform::fromTranslate( partCenter.
x(), partCenter.
y() );
5008 t.rotate( -rotation );
5009 t.translate( -partCenter.
x(), -partCenter.
y() );
5010 ( *it )->transform( t );
5012 return QVariant::fromValue(
QgsGeometry( std::move( collection ) ) );
5024 parent->
setEvalErrorString( QObject::tr(
"Function 'rotate' requires a point value for the center" ) );
5032 fGeom.
rotate( rotation, pt );
5033 return QVariant::fromValue( fGeom );
5039 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5040 const double xScale = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5041 const double yScale = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5042 const QgsGeometry center = values.at( 3 ).isValid() ? QgsExpressionUtils::getGeometry( values.at( 3 ), parent )
5053 parent->
setEvalErrorString( QObject::tr(
"Function 'scale' requires a point value for the center" ) );
5061 QTransform t = QTransform::fromTranslate( pt.
x(), pt.
y() );
5062 t.scale( xScale, yScale );
5063 t.translate( -pt.
x(), -pt.
y() );
5065 return QVariant::fromValue( fGeom );
5070 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5076 const double deltaX = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5077 const double deltaY = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5079 const double rotationZ = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5081 const double scaleX = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
5082 const double scaleY = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
5084 const double deltaZ = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
5085 const double deltaM = QgsExpressionUtils::getDoubleValue( values.at( 7 ), parent );
5086 const double scaleZ = QgsExpressionUtils::getDoubleValue( values.at( 8 ), parent );
5087 const double scaleM = QgsExpressionUtils::getDoubleValue( values.at( 9 ), parent );
5098 QTransform transform;
5099 transform.translate( deltaX, deltaY );
5100 transform.rotate( rotationZ );
5101 transform.scale( scaleX, scaleY );
5102 fGeom.
transform( transform, deltaZ, scaleZ, deltaM, scaleM );
5104 return QVariant::fromValue( fGeom );
5110 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5112 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5117 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5119 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5125 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5126 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5128 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5134 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5136 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5140#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
5145 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5146 const double targetPercent = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5147 const bool allowHoles = values.value( 2 ).toBool();
5149 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5162 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5164 if ( values.length() == 2 )
5165 segments = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5173 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5179 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5181 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5187 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5193 double area,
angle, width, height;
5206 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5207 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5209 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5215 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5222 const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( fGeom.
constGet() );
5227 result = reversed ? QVariant::fromValue(
QgsGeometry( reversed ) ) : QVariant();
5235 if (
const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( collection->
geometryN( i ) ) )
5237 reversed->addGeometry( curve->
reversed() );
5244 result = reversed ? QVariant::fromValue(
QgsGeometry( std::move( reversed ) ) ) : QVariant();
5251 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5262 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->
geometryN( 0 ) );
5271 QVariant result = exterior ? QVariant::fromValue(
QgsGeometry( exterior ) ) : QVariant();
5277 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5278 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5279 return QVariant( fGeom.
distance( sGeom ) );
5284 QgsGeometry g1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5285 QgsGeometry g2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5288 if ( values.length() == 3 && values.at( 2 ).isValid() )
5290 double densify = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5291 densify = std::clamp( densify, 0.0, 1.0 );
5299 return res > -1 ? QVariant( res ) : QVariant();
5304 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5305 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5307 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5312 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5313 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5315 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5320 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5321 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5323 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5329 if ( values.length() < 1 || values.length() > 2 )
5332 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5334 if ( values.length() == 2 )
5335 prec = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5336 QString wkt = fGeom.
asWkt( prec );
5337 return QVariant( wkt );
5342 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5343 return fGeom.
isNull() ? QVariant() : QVariant( fGeom.asWkb() );
5348 if ( values.length() != 2 )
5350 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires exactly two parameters. %n given.",
nullptr, values.length() ) );
5354 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5355 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5357 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5364 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5369 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5376 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5383 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires two points as arguments." ) );
5390 if ( pt1->
y() < pt2->
y() )
5392 else if ( pt1->
y() > pt2->
y() )
5400 if ( pt1->
x() < pt2->
x() )
5402 else if ( pt1->
x() > pt2->
x() )
5403 return M_PI + ( M_PI_2 );
5408 if ( pt1->
x() < pt2->
x() )
5410 if ( pt1->
y() < pt2->
y() )
5412 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) );
5416 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5423 if ( pt1->
y() > pt2->
y() )
5425 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) )
5430 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5431 + ( M_PI + ( M_PI_2 ) );
5438 const QgsGeometry geom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5439 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5440 QString sourceCrs = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5441 QString ellipsoid = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
5445 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires two valid point geometries." ) );
5453 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires point geometries or multi point geometries with a single part." ) );
5462 if ( sourceCrs.isEmpty() )
5464 sourceCrs = context->
variable( QStringLiteral(
"layer_crs" ) ).toString();
5467 if ( ellipsoid.isEmpty() )
5469 ellipsoid = context->
variable( QStringLiteral(
"project_ellipsoid" ) ).toString();
5476 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires a valid source CRS." ) );
5484 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires a valid ellipsoid acronym or ellipsoid authority ID." ) );
5490 const double bearing = da.
bearing( point1, point2 );
5491 if ( std::isfinite( bearing ) )
5493 return std::fmod( bearing + 2 * M_PI, 2 * M_PI );
5506 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5510 parent->
setEvalErrorString( QStringLiteral(
"'project' requires a point geometry" ) );
5514 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5515 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5516 double inclination = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5519 QgsPoint newPoint = p->
project( distance, 180.0 * azimuth / M_PI, 180.0 * inclination / M_PI );
5526 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5527 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5529 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5536 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5540 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5547 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5555 parent->
setEvalErrorString( QStringLiteral(
"Function 'inclination' requires two points as arguments." ) );
5565 if ( values.length() != 3 )
5568 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5569 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5570 double y = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5574 QVariant result = geom.
constGet() ? QVariant::fromValue( geom ) : QVariant();
5580 if ( values.length() < 2 )
5583 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5586 return values.at( 0 );
5588 QString expString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5589 QVariant cachedExpression;
5594 if ( cachedExpression.isValid() )
5601 bool asc = values.value( 2 ).toBool();
5619 Q_ASSERT( collection );
5623 QgsExpressionSorter sorter( orderBy );
5625 QList<QgsFeature> partFeatures;
5626 partFeatures.reserve( collection->
partCount() );
5627 for (
int i = 0; i < collection->
partCount(); ++i )
5633 sorter.sortFeatures( partFeatures, unconstedContext );
5637 Q_ASSERT( orderedGeom );
5642 for (
const QgsFeature &feature : std::as_const( partFeatures ) )
5647 QVariant result = QVariant::fromValue(
QgsGeometry( orderedGeom ) );
5650 delete unconstedContext;
5657 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5658 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5662 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5668 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5669 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5673 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5679 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5680 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5684 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5690 const QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5691 const double m = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5692 const bool use3DDistance = values.at( 2 ).toBool();
5694 double x, y, z, distance;
5717 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5720 parent->
setEvalErrorString( QObject::tr(
"line_substring requires a curve geometry input" ) );
5726 curve = qgsgeometry_cast< const QgsCurve * >( lineGeom.
constGet() );
5733 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
5740 double startDistance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5741 double endDistance = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5743 std::unique_ptr< QgsCurve > substring( curve->
curveSubstring( startDistance, endDistance ) );
5745 return !result.isNull() ? QVariant::fromValue( result ) : QVariant();
5750 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5751 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5758 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5759 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5764 vertex = count + vertex;
5772 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5773 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5778 vertex = count + vertex;
5786 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5787 QgsGeometry pointGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5791 return distance >= 0 ? distance : QVariant();
5796 const QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5797 const double m = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5798 const bool use3DDistance = values.at( 2 ).toBool();
5800 double x, y, z, distance;
5809 return found ? distance : QVariant();
5814 if ( values.length() == 2 && values.at( 1 ).toInt() != 0 )
5816 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5817 return qgsRound( number, QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
5820 if ( values.length() >= 1 )
5822 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5823 return QVariant( qlonglong( std::round( number ) ) );
5838 const double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5839 const int places = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5840 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5847 const bool omitGroupSeparator = values.value( 3 ).toBool();
5848 const bool trimTrailingZeros = values.value( 4 ).toBool();
5850 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5851 if ( !omitGroupSeparator )
5852 locale.setNumberOptions( locale.numberOptions() & ~QLocale::NumberOption::OmitGroupSeparator );
5854 locale.setNumberOptions( locale.numberOptions() | QLocale::NumberOption::OmitGroupSeparator );
5856 QString res = locale.toString( value,
'f', places );
5858 if ( trimTrailingZeros )
5860#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
5861 const QChar decimal = locale.decimalPoint();
5862 const QChar zeroDigit = locale.zeroDigit();
5864 const QChar decimal = locale.decimalPoint().at( 0 );
5865 const QChar zeroDigit = locale.zeroDigit().at( 0 );
5868 if ( res.contains( decimal ) )
5870 int trimPoint = res.length() - 1;
5872 while ( res.at( trimPoint ) == zeroDigit )
5875 if ( res.at( trimPoint ) == decimal )
5878 res.truncate( trimPoint + 1 );
5887 QDateTime datetime = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
5888 const QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5889 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5892 if ( format.indexOf(
"Z" ) > 0 )
5893 datetime = datetime.toUTC();
5895 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5896 return locale.toString( datetime, format );
5901 const QVariant variant = values.at( 0 );
5903 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
5904 if ( !color.isValid() )
5907 const float alpha = color.alphaF();
5908 if ( color.spec() == QColor::Spec::Cmyk )
5910 const float avg = ( color.cyanF() + color.magentaF() + color.yellowF() ) / 3;
5911 color = QColor::fromCmykF( avg, avg, avg, color.blackF(), alpha );
5915 const float avg = ( color.redF() + color.greenF() + color.blueF() ) / 3;
5916 color.setRgbF( avg, avg, avg, alpha );
5919 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
5926 double ratio = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5931 else if ( ratio < 0 )
5936 int red =
static_cast<int>( color1.red() * ( 1 - ratio ) + color2.red() * ratio );
5937 int green =
static_cast<int>( color1.green() * ( 1 - ratio ) + color2.green() * ratio );
5938 int blue =
static_cast<int>( color1.blue() * ( 1 - ratio ) + color2.blue() * ratio );
5939 int alpha =
static_cast<int>( color1.alpha() * ( 1 - ratio ) + color2.alpha() * ratio );
5941 QColor newColor( red, green, blue, alpha );
5948 const QVariant variant1 = values.at( 0 );
5949 const QVariant variant2 = values.at( 1 );
5951 if ( variant1.userType() != variant2.userType() )
5953 parent->
setEvalErrorString( QObject::tr(
"Both color arguments must have the same type (string or color object)" ) );
5958 const QColor color1 = QgsExpressionUtils::getColorValue( variant1, parent, isQColor );
5959 if ( !color1.isValid() )
5962 const QColor color2 = QgsExpressionUtils::getColorValue( variant2, parent, isQColor );
5963 if ( !color2.isValid() )
5966 if ( ( color1.spec() == QColor::Cmyk ) != ( color2.spec() == QColor::Cmyk ) )
5968 parent->
setEvalErrorString( QObject::tr(
"Both color arguments must have compatible color type (CMYK or RGB/HSV/HSL)" ) );
5972 const float ratio =
static_cast<float>( std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0., 1. ) );
5978 const float alpha = color1.alphaF() * ( 1 - ratio ) + color2.alphaF() * ratio;
5979 if ( color1.spec() == QColor::Spec::Cmyk )
5981 float cyan = color1.cyanF() * ( 1 - ratio ) + color2.cyanF() * ratio;
5982 float magenta = color1.magentaF() * ( 1 - ratio ) + color2.magentaF() * ratio;
5983 float yellow = color1.yellowF() * ( 1 - ratio ) + color2.yellowF() * ratio;
5984 float black = color1.blackF() * ( 1 - ratio ) + color2.blackF() * ratio;
5985 newColor = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
5989 float red = color1.redF() * ( 1 - ratio ) + color2.redF() * ratio;
5990 float green = color1.greenF() * ( 1 - ratio ) + color2.greenF() * ratio;
5991 float blue = color1.blueF() * ( 1 - ratio ) + color2.blueF() * ratio;
5992 newColor = QColor::fromRgbF( red, green, blue, alpha );
5997 return isQColor ? QVariant( newColor ) : QVariant(
QgsSymbolLayerUtils::encodeColor( newColor ) );
6002 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
6003 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6004 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6005 QColor color = QColor( red, green, blue );
6006 if ( ! color.isValid() )
6008 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( red ).arg( green ).arg( blue ) );
6009 color = QColor( 0, 0, 0 );
6012 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6017 const float red = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6018 const float green = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6019 const float blue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6020 const float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6021 QColor color = QColor::fromRgbF( red, green, blue, alpha );
6022 if ( ! color.isValid() )
6024 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
6033 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
6034 QVariant value = node->
eval( parent, context );
6038 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
6040 value = node->
eval( parent, context );
6048 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
6050 QVariant value = node->
eval( parent, context );
6052 if ( value.toBool() )
6054 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
6056 value = node->
eval( parent, context );
6061 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
6063 value = node->
eval( parent, context );
6071 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
6072 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6073 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6074 int alpha = QgsExpressionUtils::getNativeIntValue( values.at( 3 ), parent );
6075 QColor color = QColor( red, green, blue, alpha );
6076 if ( ! color.isValid() )
6078 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
6079 color = QColor( 0, 0, 0 );
6088 if ( values.at( 0 ).userType() == qMetaTypeId< QgsGradientColorRamp>() )
6090 expRamp = QgsExpressionUtils::getRamp( values.at( 0 ), parent );
6095 QString rampName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
6099 parent->
setEvalErrorString( QObject::tr(
"\"%1\" is not a valid color ramp" ).arg( rampName ) );
6104 double value = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
6105 QColor color = ramp->
color( value );
6118 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6120 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6122 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6124 QColor color = QColor::fromHslF( hue, saturation, lightness );
6126 if ( ! color.isValid() )
6128 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( lightness ) );
6129 color = QColor( 0, 0, 0 );
6132 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6138 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6140 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6142 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6144 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
6146 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
6147 if ( ! color.isValid() )
6149 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
6150 color = QColor( 0, 0, 0 );
6157 float hue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6158 float saturation = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6159 float lightness = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6160 float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6162 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
6163 if ( ! color.isValid() )
6165 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
6175 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6177 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6179 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6181 QColor color = QColor::fromHsvF( hue, saturation, value );
6183 if ( ! color.isValid() )
6185 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( value ) );
6186 color = QColor( 0, 0, 0 );
6189 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6195 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6197 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6199 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6201 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
6203 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
6204 if ( ! color.isValid() )
6206 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
6207 color = QColor( 0, 0, 0 );
6214 float hue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6215 float saturation = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6216 float value = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6217 float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6218 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
6220 if ( ! color.isValid() )
6222 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
6231 const float cyan = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6232 const float magenta = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6233 const float yellow = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6234 const float black = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6235 const float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ) ), 0.f, 1.f );
6237 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6238 if ( ! color.isValid() )
6240 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
6250 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
6252 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6254 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6256 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
6258 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black );
6260 if ( ! color.isValid() )
6262 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ) );
6263 color = QColor( 0, 0, 0 );
6266 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6272 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
6274 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6276 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6278 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
6280 double alpha = QgsExpressionUtils::getIntValue( values.at( 4 ), parent ) / 255.0;
6282 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6283 if ( ! color.isValid() )
6285 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
6286 color = QColor( 0, 0, 0 );
6293 const QVariant variant = values.at( 0 );
6295 const QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6296 if ( !color.isValid() )
6299 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6300 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6302 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6303 return color.green();
6304 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6305 return color.blue();
6306 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6307 return color.alpha();
6308 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6309 return static_cast< double >( color.hsvHueF() * 360 );
6310 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6311 return static_cast< double >( color.hsvSaturationF() * 100 );
6312 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6313 return static_cast< double >( color.valueF() * 100 );
6314 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6315 return static_cast< double >( color.hslHueF() * 360 );
6316 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6317 return static_cast< double >( color.hslSaturationF() * 100 );
6318 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6319 return static_cast< double >( color.lightnessF() * 100 );
6320 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6321 return static_cast< double >( color.cyanF() * 100 );
6322 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6323 return static_cast< double >( color.magentaF() * 100 );
6324 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6325 return static_cast< double >( color.yellowF() * 100 );
6326 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6327 return static_cast< double >( color.blackF() * 100 );
6329 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6335 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
6338 parent->
setEvalErrorString( QObject::tr(
"A minimum of two colors is required to create a ramp" ) );
6342 QList< QColor > colors;
6344 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
6347 if ( !colors.last().isValid() )
6349 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( it.value().toString() ) );
6353 double step = it.key().toDouble();
6354 if ( it == map.constBegin() )
6359 else if ( it == map.constEnd() )
6369 bool discrete = values.at( 1 ).toBool();
6371 if ( colors.empty() )
6374 return QVariant::fromValue(
QgsGradientColorRamp( colors.first(), colors.last(), discrete, stops ) );
6379 const QVariant variant = values.at( 0 );
6381 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6382 if ( !color.isValid() )
6385 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6386 int value = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6387 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6388 color.setRed( std::clamp( value, 0, 255 ) );
6389 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6390 color.setGreen( std::clamp( value, 0, 255 ) );
6391 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6392 color.setBlue( std::clamp( value, 0, 255 ) );
6393 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6394 color.setAlpha( std::clamp( value, 0, 255 ) );
6395 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6396 color.setHsv( std::clamp( value, 0, 359 ), color.hsvSaturation(), color.value(), color.alpha() );
6397 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6398 color.setHsvF( color.hsvHueF(), std::clamp( value, 0, 100 ) / 100.0, color.valueF(), color.alphaF() );
6399 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6400 color.setHsvF( color.hsvHueF(), color.hsvSaturationF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6401 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6402 color.setHsl( std::clamp( value, 0, 359 ), color.hslSaturation(), color.lightness(), color.alpha() );
6403 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6404 color.setHslF( color.hslHueF(), std::clamp( value, 0, 100 ) / 100.0, color.lightnessF(), color.alphaF() );
6405 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6406 color.setHslF( color.hslHueF(), color.hslSaturationF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6407 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6408 color.setCmykF( std::clamp( value, 0, 100 ) / 100.0, color.magentaF(), color.yellowF(), color.blackF(), color.alphaF() );
6409 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6410 color.setCmykF( color.cyanF(), std::clamp( value, 0, 100 ) / 100.0, color.yellowF(), color.blackF(), color.alphaF() );
6411 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6412 color.setCmykF( color.cyanF(), color.magentaF(), std::clamp( value, 0, 100 ) / 100.0, color.blackF(), color.alphaF() );
6413 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6414 color.setCmykF( color.cyanF(), color.magentaF(), color.yellowF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6417 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6420 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6425 const QVariant variant = values.at( 0 );
6427 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6428 if ( !color.isValid() )
6431 color = color.darker( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6433 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6438 const QVariant variant = values.at( 0 );
6440 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6441 if ( !color.isValid() )
6444 color = color.lighter( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6446 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6451 QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6454 return QVariant::fromValue( geom );
6460 const QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6468 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
6469 QString sAuthId = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6470 QString dAuthId = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6474 return QVariant::fromValue( fGeom );
6477 return QVariant::fromValue( fGeom );
6486 return QVariant::fromValue( fGeom );
6499 bool foundLayer =
false;
6500 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6503 if ( !featureSource || !foundLayer )
6508 const QgsFeatureId fid = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
6521 result = QVariant::fromValue( fet );
6529 bool foundLayer =
false;
6530 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6533 if ( !featureSource || !foundLayer )
6538 QString cacheValueKey;
6539 if ( values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
6541 QVariantMap attributeMap = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
6543 QMap <QString, QVariant>::const_iterator i = attributeMap.constBegin();
6544 QString filterString;
6545 for ( ; i != attributeMap.constEnd(); ++i )
6547 if ( !filterString.isEmpty() )
6549 filterString.append(
" AND " );
6553 cacheValueKey = QStringLiteral(
"getfeature:%1:%2" ).arg( featureSource->id(), filterString );
6562 QString attribute = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6563 int attributeId = featureSource->fields().lookupField( attribute );
6564 if ( attributeId == -1 )
6569 const QVariant &attVal = values.at( 2 );
6571 cacheValueKey = QStringLiteral(
"getfeature:%1:%2:%3" ).arg( featureSource->id(), QString::number( attributeId ), attVal.toString() );
6594 res = QVariant::fromValue( fet );
6609 if ( !values.isEmpty() )
6612 if ( col && ( values.size() == 1 || !values.at( 1 ).isValid() ) )
6613 fieldName = col->
name();
6614 else if ( values.size() == 2 )
6615 fieldName = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6618 QVariant value = values.at( 0 );
6623 if ( fieldIndex == -1 )
6625 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: Field not found %2" ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6631 QgsVectorLayer *layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
6634 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName, value.toString() );
6643 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName );
6654 result =
formatter->representValue( layer, fieldIndex, setup.
config(), cache, value );
6661 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: function cannot be evaluated without a context." ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6669 const QVariant data = values.at( 0 );
6670 const QMimeDatabase db;
6671 return db.mimeTypeForData( data.toByteArray() ).name();
6676 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6678 bool foundLayer =
false;
6679 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [layerProperty](
QgsMapLayer * layer )-> QVariant
6685 if ( QString::compare( layerProperty, QStringLiteral(
"name" ), Qt::CaseInsensitive ) == 0 )
6686 return layer->name();
6687 else if ( QString::compare( layerProperty, QStringLiteral(
"id" ), Qt::CaseInsensitive ) == 0 )
6689 else if ( QString::compare( layerProperty, QStringLiteral(
"title" ), Qt::CaseInsensitive ) == 0 )
6690 return !layer->metadata().title().isEmpty() ? layer->metadata().title() : layer->serverProperties()->title();
6691 else if ( QString::compare( layerProperty, QStringLiteral(
"abstract" ), Qt::CaseInsensitive ) == 0 )
6692 return !layer->metadata().abstract().isEmpty() ? layer->metadata().abstract() : layer->serverProperties()->abstract();
6693 else if ( QString::compare( layerProperty, QStringLiteral(
"keywords" ), Qt::CaseInsensitive ) == 0 )
6695 QStringList keywords;
6696 const QgsAbstractMetadataBase::KeywordMap keywordMap = layer->metadata().keywords();
6697 for ( auto it = keywordMap.constBegin(); it != keywordMap.constEnd(); ++it )
6699 keywords.append( it.value() );
6701 if ( !keywords.isEmpty() )
6703 return layer->serverProperties()->keywordList();
6705 else if ( QString::compare( layerProperty, QStringLiteral(
"data_url" ), Qt::CaseInsensitive ) == 0 )
6707 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution" ), Qt::CaseInsensitive ) == 0 )
6709 return !layer->
metadata().
rights().isEmpty() ? QVariant( layer->
metadata().
rights() ) : QVariant( layer->serverProperties()->attribution() );
6711 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution_url" ), Qt::CaseInsensitive ) == 0 )
6713 else if ( QString::compare( layerProperty, QStringLiteral(
"source" ), Qt::CaseInsensitive ) == 0 )
6715 else if ( QString::compare( layerProperty, QStringLiteral(
"min_scale" ), Qt::CaseInsensitive ) == 0 )
6717 else if ( QString::compare( layerProperty, QStringLiteral(
"max_scale" ), Qt::CaseInsensitive ) == 0 )
6719 else if ( QString::compare( layerProperty, QStringLiteral(
"is_editable" ), Qt::CaseInsensitive ) == 0 )
6721 else if ( QString::compare( layerProperty, QStringLiteral(
"crs" ), Qt::CaseInsensitive ) == 0 )
6723 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_definition" ), Qt::CaseInsensitive ) == 0 )
6725 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_description" ), Qt::CaseInsensitive ) == 0 )
6727 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_ellipsoid" ), Qt::CaseInsensitive ) == 0 )
6729 else if ( QString::compare( layerProperty, QStringLiteral(
"extent" ), Qt::CaseInsensitive ) == 0 )
6732 QVariant result = QVariant::fromValue( extentGeom );
6735 else if ( QString::compare( layerProperty, QStringLiteral(
"distance_units" ), Qt::CaseInsensitive ) == 0 )
6737 else if ( QString::compare( layerProperty, QStringLiteral(
"path" ), Qt::CaseInsensitive ) == 0 )
6740 return decodedUri.value( QStringLiteral(
"path" ) );
6742 else if ( QString::compare( layerProperty, QStringLiteral(
"type" ), Qt::CaseInsensitive ) == 0 )
6744 switch ( layer->
type() )
6747 return QCoreApplication::translate(
"expressions",
"Vector" );
6749 return QCoreApplication::translate(
"expressions",
"Raster" );
6751 return QCoreApplication::translate(
"expressions",
"Mesh" );
6753 return QCoreApplication::translate(
"expressions",
"Vector Tile" );
6755 return QCoreApplication::translate(
"expressions",
"Plugin" );
6757 return QCoreApplication::translate(
"expressions",
"Annotation" );
6759 return QCoreApplication::translate(
"expressions",
"Point Cloud" );
6761 return QCoreApplication::translate(
"expressions",
"Group" );
6763 return QCoreApplication::translate(
"expressions",
"Tiled Scene" );
6769 QgsVectorLayer *vLayer = qobject_cast< QgsVectorLayer * >( layer );
6772 if ( QString::compare( layerProperty, QStringLiteral(
"storage_type" ), Qt::CaseInsensitive ) == 0 )
6774 else if ( QString::compare( layerProperty, QStringLiteral(
"geometry_type" ), Qt::CaseInsensitive ) == 0 )
6776 else if ( QString::compare( layerProperty, QStringLiteral(
"feature_count" ), Qt::CaseInsensitive ) == 0 )
6792 const QString uriPart = values.at( 1 ).toString();
6794 bool foundLayer =
false;
6796 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, uriPart](
QgsMapLayer * layer )-> QVariant
6798 if ( !layer->dataProvider() )
6800 parent->setEvalErrorString( QObject::tr(
"Layer %1 has invalid data provider" ).arg( layer->name() ) );
6806 if ( !uriPart.isNull() )
6808 return decodedUri.value( uriPart );
6818 parent->
setEvalErrorString( QObject::tr(
"Function `decode_uri` requires a valid layer." ) );
6829 const int band = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6830 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6832 bool foundLayer =
false;
6833 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, band, layerProperty](
QgsMapLayer * layer )-> QVariant
6835 QgsRasterLayer *rl = qobject_cast< QgsRasterLayer * >( layer );
6839 if ( band < 1 || band > rl->bandCount() )
6841 parent->setEvalErrorString( QObject::tr(
"Invalid band number %1 for layer" ).arg( band ) );
6847 if ( QString::compare( layerProperty, QStringLiteral(
"avg" ), Qt::CaseInsensitive ) == 0 )
6849 else if ( QString::compare( layerProperty, QStringLiteral(
"stdev" ), Qt::CaseInsensitive ) == 0 )
6851 else if ( QString::compare( layerProperty, QStringLiteral(
"min" ), Qt::CaseInsensitive ) == 0 )
6853 else if ( QString::compare( layerProperty, QStringLiteral(
"max" ), Qt::CaseInsensitive ) == 0 )
6855 else if ( QString::compare( layerProperty, QStringLiteral(
"range" ), Qt::CaseInsensitive ) == 0 )
6857 else if ( QString::compare( layerProperty, QStringLiteral(
"sum" ), Qt::CaseInsensitive ) == 0 )
6861 parent->
setEvalErrorString( QObject::tr(
"Invalid raster statistic: '%1'" ).arg( layerProperty ) );
6889 parent->
setEvalErrorString( QObject::tr(
"Function `raster_statistic` requires a valid raster layer." ) );
6906 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6907 bool ascending = values.value( 1 ).toBool();
6908 std::sort( list.begin(), list.end(), [ascending]( QVariant a, QVariant b ) ->
bool { return ( !ascending ? qgsVariantLessThan( b, a ) : qgsVariantLessThan( a, b ) ); } );
6914 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).length();
6919 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).contains( values.at( 1 ) ) );
6924 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).count( values.at( 1 ) ) );
6929 QVariantList listA = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6930 QVariantList listB = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
6932 for (
const auto &item : listB )
6934 if ( listA.contains( item ) )
6938 return QVariant( match == listB.count() );
6943 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).indexOf( values.at( 1 ) );
6948 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6949 const int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6950 if ( pos < list.length() && pos >= 0 )
return list.at( pos );
6951 else if ( pos < 0 && ( list.length() + pos ) >= 0 )
6952 return list.at( list.length() + pos );
6958 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6959 return list.value( 0 );
6964 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6965 return list.value( list.size() - 1 );
6970 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6971 return list.isEmpty() ? QVariant() : *std::min_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
6976 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6977 return list.isEmpty() ? QVariant() : *std::max_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
6982 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6985 for (
const QVariant &item : list )
6987 switch ( item.userType() )
6989 case QMetaType::Int:
6990 case QMetaType::UInt:
6991 case QMetaType::LongLong:
6992 case QMetaType::ULongLong:
6993 case QMetaType::Float:
6994 case QMetaType::Double:
6995 total += item.toDouble();
7000 return i == 0 ? QVariant() : total / i;
7005 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7006 QVariantList numbers;
7007 for (
const auto &item : list )
7009 switch ( item.userType() )
7011 case QMetaType::Int:
7012 case QMetaType::UInt:
7013 case QMetaType::LongLong:
7014 case QMetaType::ULongLong:
7015 case QMetaType::Float:
7016 case QMetaType::Double:
7017 numbers.append( item );
7021 std::sort( numbers.begin(), numbers.end(), []( QVariant a, QVariant b ) ->
bool { return ( qgsVariantLessThan( a, b ) ); } );
7022 const int count = numbers.count();
7027 else if ( count % 2 )
7029 return numbers.at( count / 2 );
7033 return ( numbers.at( count / 2 - 1 ).toDouble() + numbers.at( count / 2 ).toDouble() ) / 2;
7039 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7042 for (
const QVariant &item : list )
7044 switch ( item.userType() )
7046 case QMetaType::Int:
7047 case QMetaType::UInt:
7048 case QMetaType::LongLong:
7049 case QMetaType::ULongLong:
7050 case QMetaType::Float:
7051 case QMetaType::Double:
7052 total += item.toDouble();
7057 return i == 0 ? QVariant() : total;
7060static QVariant convertToSameType(
const QVariant &value, QMetaType::Type type )
7062 QVariant result = value;
7063 result.convert(
static_cast<int>( type ) );
7069 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7070 QHash< QVariant, int > hash;
7071 for (
const auto &item : list )
7075 const QList< int > occurrences = hash.values();
7076 if ( occurrences.empty() )
7077 return QVariantList();
7079 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
7081 const QString option = values.at( 1 ).toString();
7082 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
7084 return convertToSameType( hash.keys( maxValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7086 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
7088 if ( hash.isEmpty() )
7091 return QVariant( hash.key( maxValue ) );
7093 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
7095 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( maxValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) ), context, parent, node );
7097 else if ( option.compare( QLatin1String(
"real_majority" ), Qt::CaseInsensitive ) == 0 )
7099 if ( maxValue * 2 <= list.size() )
7102 return QVariant( hash.key( maxValue ) );
7113 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7114 QHash< QVariant, int > hash;
7115 for (
const auto &item : list )
7119 const QList< int > occurrences = hash.values();
7120 if ( occurrences.empty() )
7121 return QVariantList();
7123 const int minValue = *std::min_element( occurrences.constBegin(), occurrences.constEnd() );
7125 const QString option = values.at( 1 ).toString();
7126 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
7128 return convertToSameType( hash.keys( minValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7130 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
7132 if ( hash.isEmpty() )
7135 return QVariant( hash.key( minValue ) );
7137 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
7139 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( minValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) ), context, parent, node );
7141 else if ( option.compare( QLatin1String(
"real_minority" ), Qt::CaseInsensitive ) == 0 )
7143 if ( hash.isEmpty() )
7147 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
7148 if ( maxValue * 2 > list.size() )
7149 hash.remove( hash.key( maxValue ) );
7151 return convertToSameType( hash.keys(),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7162 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7163 list.append( values.at( 1 ) );
7164 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7169 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7170 list.prepend( values.at( 1 ) );
7171 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7176 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7177 list.insert( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), values.at( 2 ) );
7178 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7183 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7184 int position = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7186 position = position + list.length();
7187 if ( position >= 0 && position < list.length() )
7188 list.removeAt( position );
7189 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7197 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7199 const QVariant toRemove = values.at( 1 );
7202 list.erase( std::remove_if( list.begin(), list.end(), [](
const QVariant & element )
7204 return QgsVariantUtils::isNull( element );
7209 list.removeAll( toRemove );
7211 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7216 if ( values.count() == 2 && values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
7218 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
7220 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7221 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
7223 int index = list.indexOf( it.key() );
7224 while ( index >= 0 )
7226 list.replace( index, it.value() );
7227 index = list.indexOf( it.key() );
7231 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7233 else if ( values.count() == 3 )
7235 QVariantList before;
7237 bool isSingleReplacement =
false;
7239 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).userType() != QMetaType::Type::QStringList )
7241 before = QVariantList() << values.at( 1 );
7245 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
7248 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
7250 after = QVariantList() << values.at( 2 );
7251 isSingleReplacement =
true;
7255 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
7258 if ( !isSingleReplacement && before.length() != after.length() )
7260 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
7264 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7265 for (
int i = 0; i < before.length(); i++ )
7267 int index = list.indexOf( before.at( i ) );
7268 while ( index >= 0 )
7270 list.replace( index, after.at( isSingleReplacement ? 0 : i ) );
7271 index = list.indexOf( before.at( i ) );
7275 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7279 parent->
setEvalErrorString( QObject::tr(
"Function array_replace requires 2 or 3 arguments" ) );
7286 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7287 QVariantList list_new;
7289 for (
const QVariant &cur :
QgsExpressionUtils::getListValue( values.at( 1 ), parent ) )
7291 while ( list.removeOne( cur ) )
7293 list_new.append( cur );
7297 list_new.append( list );
7299 return convertToSameType( list_new,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7305 for (
const QVariant &cur : values )
7307 list += QgsExpressionUtils::getListValue( cur, parent );
7309 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7314 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7315 int start_pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7316 const int end_pos = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
7317 int slice_length = 0;
7319 if ( start_pos < 0 )
7321 start_pos = list.length() + start_pos;
7325 slice_length = end_pos - start_pos + 1;
7329 slice_length = list.length() + end_pos - start_pos + 1;
7332 if ( slice_length < 0 )
7336 list = list.mid( start_pos, slice_length );
7342 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7343 std::reverse( list.begin(), list.end() );
7349 const QVariantList array1 = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7350 const QVariantList array2 = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
7351 for (
const QVariant &cur : array2 )
7353 if ( array1.contains( cur ) )
7354 return QVariant(
true );
7356 return QVariant(
false );
7361 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7363 QVariantList distinct;
7365 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7367 if ( !distinct.contains( *it ) )
7369 distinct += ( *it );
7378 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7379 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7380 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7384 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7386 str += ( !( *it ).toString().isEmpty() ) ? ( *it ).toString() : empty;
7387 if ( it != ( array.constEnd() - 1 ) )
7393 return QVariant(
str );
7398 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7399 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7400 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7402 QStringList list =
str.split( delimiter );
7405 for ( QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
7407 array += ( !( *it ).isEmpty() ) ? *it : empty;
7415 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7416 QJsonDocument document = QJsonDocument::fromJson(
str.toUtf8() );
7417 if ( document.isNull() )
7420 return document.toVariant();
7426 QJsonDocument document = QJsonDocument::fromVariant( values.at( 0 ) );
7427 return QString( document.toJson( QJsonDocument::Compact ) );
7432 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7433 if (
str.isEmpty() )
7434 return QVariantMap();
7442 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7449 for (
int i = 0; i + 1 < values.length(); i += 2 )
7451 result.insert( QgsExpressionUtils::getStringValue( values.at( i ), parent ), values.at( i + 1 ) );
7458 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7459 const QString prefix = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7460 QVariantMap resultMap;
7462 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7464 resultMap.insert( QString( it.key() ).prepend( prefix ), it.value() );
7472 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).value( values.at( 1 ).toString() );
7477 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).contains( values.at( 1 ).toString() );
7482 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7483 map.remove( values.at( 1 ).toString() );
7489 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7490 map.insert( values.at( 1 ).toString(), values.at( 2 ) );
7497 for (
const QVariant &cur : values )
7499 const QVariantMap curMap = QgsExpressionUtils::getMapValue( cur, parent );
7500 for ( QVariantMap::const_iterator it = curMap.constBegin(); it != curMap.constEnd(); ++it )
7501 result.insert( it.key(), it.value() );
7508 return QStringList( QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).keys() );
7513 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).values();
7518 const QString envVarName = values.at( 0 ).toString();
7519 if ( !QProcessEnvironment::systemEnvironment().contains( envVarName ) )
7522 return QProcessEnvironment::systemEnvironment().value( envVarName );
7527 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7530 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"base_file_name" ) ) );
7533 return QFileInfo( file ).completeBaseName();
7538 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7541 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_suffix" ) ) );
7544 return QFileInfo( file ).completeSuffix();
7549 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7552 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_exists" ) ) );
7555 return QFileInfo::exists( file );
7560 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7563 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_name" ) ) );
7566 return QFileInfo( file ).fileName();
7571 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7574 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_file" ) ) );
7577 return QFileInfo( file ).isFile();
7582 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7585 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_directory" ) ) );
7588 return QFileInfo( file ).isDir();
7593 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7596 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_path" ) ) );
7599 return QDir::toNativeSeparators( QFileInfo( file ).path() );
7604 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7607 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_size" ) ) );
7610 return QFileInfo( file ).size();
7613static QVariant fcnHash(
const QString &
str,
const QCryptographicHash::Algorithm
algorithm )
7615 return QString( QCryptographicHash::hash(
str.toUtf8(),
algorithm ).toHex() );
7621 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7622 QString method = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).toLower();
7624 if ( method == QLatin1String(
"md4" ) )
7626 hash = fcnHash(
str, QCryptographicHash::Md4 );
7628 else if ( method == QLatin1String(
"md5" ) )
7630 hash = fcnHash(
str, QCryptographicHash::Md5 );
7632 else if ( method == QLatin1String(
"sha1" ) )
7634 hash = fcnHash(
str, QCryptographicHash::Sha1 );
7636 else if ( method == QLatin1String(
"sha224" ) )
7638 hash = fcnHash(
str, QCryptographicHash::Sha224 );
7640 else if ( method == QLatin1String(
"sha256" ) )
7642 hash = fcnHash(
str, QCryptographicHash::Sha256 );
7644 else if ( method == QLatin1String(
"sha384" ) )
7646 hash = fcnHash(
str, QCryptographicHash::Sha384 );
7648 else if ( method == QLatin1String(
"sha512" ) )
7650 hash = fcnHash(
str, QCryptographicHash::Sha512 );
7652 else if ( method == QLatin1String(
"sha3_224" ) )
7654 hash = fcnHash(
str, QCryptographicHash::Sha3_224 );
7656 else if ( method == QLatin1String(
"sha3_256" ) )
7658 hash = fcnHash(
str, QCryptographicHash::Sha3_256 );
7660 else if ( method == QLatin1String(
"sha3_384" ) )
7662 hash = fcnHash(
str, QCryptographicHash::Sha3_384 );
7664 else if ( method == QLatin1String(
"sha3_512" ) )
7666 hash = fcnHash(
str, QCryptographicHash::Sha3_512 );
7668 else if ( method == QLatin1String(
"keccak_224" ) )
7670 hash = fcnHash(
str, QCryptographicHash::Keccak_224 );
7672 else if ( method == QLatin1String(
"keccak_256" ) )
7674 hash = fcnHash(
str, QCryptographicHash::Keccak_256 );
7676 else if ( method == QLatin1String(
"keccak_384" ) )
7678 hash = fcnHash(
str, QCryptographicHash::Keccak_384 );
7680 else if ( method == QLatin1String(
"keccak_512" ) )
7682 hash = fcnHash(
str, QCryptographicHash::Keccak_512 );
7686 parent->
setEvalErrorString( QObject::tr(
"Hash method %1 is not available on this system." ).arg(
str ) );
7693 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Md5 );
7698 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Sha256 );
7703 const QByteArray input = values.at( 0 ).toByteArray();
7704 return QVariant( QString( input.toBase64() ) );
7709 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7711 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7713 query.addQueryItem( it.key(), it.value().toString() );
7715 return query.toString( QUrl::ComponentFormattingOption::FullyEncoded );
7720 const QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7721 const QByteArray base64 = value.toLocal8Bit();
7722 const QByteArray decoded = QByteArray::fromBase64( base64 );
7723 return QVariant( decoded );
7728static QVariant executeGeomOverlay(
const QVariantList &values,
const QgsExpressionContext *context,
QgsExpression *parent,
const RelationFunction &relationFunction,
bool invert =
false,
double bboxGrow = 0,
bool isNearestFunc =
false,
bool isIntersectsFunc =
false )
7731 const QVariant sourceLayerRef = context->
variable( QStringLiteral(
"layer" ) );
7734 QgsVectorLayer *sourceLayer = QgsExpressionUtils::getVectorLayer( sourceLayerRef, context, parent );
7743 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
7746 const bool layerCanBeCached = node->
isStatic( parent, context );
7747 QVariant targetLayerValue = node->
eval( parent, context );
7751 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
7753 QString subExpString = node->dump();
7755 bool testOnly = ( subExpString ==
"NULL" );
7758 QgsVectorLayer *targetLayer = QgsExpressionUtils::getVectorLayer( targetLayerValue, context, parent );
7762 parent->
setEvalErrorString( QObject::tr(
"Layer '%1' could not be loaded." ).arg( targetLayerValue.toString() ) );
7767 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
7769 QString filterString = node->dump();
7770 if ( filterString !=
"NULL" )
7772 request.setFilterExpression( filterString );
7776 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
7778 QVariant limitValue = node->eval( parent, context );
7780 qlonglong limit = QgsExpressionUtils::getIntValue( limitValue, parent );
7783 double max_distance = 0;
7784 if ( isNearestFunc )
7786 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
7788 QVariant distanceValue = node->eval( parent, context );
7790 max_distance = QgsExpressionUtils::getDoubleValue( distanceValue, parent );
7794 node = QgsExpressionUtils::getNode( values.at( isNearestFunc ? 5 : 4 ), parent );
7796 QVariant cacheValue = node->eval( parent, context );
7798 bool cacheEnabled = cacheValue.toBool();
7804 double minOverlap { -1 };
7805 double minInscribedCircleRadius { -1 };
7806 bool returnDetails =
false;
7807 bool sortByMeasure =
false;
7808 bool sortAscending =
false;
7809 bool requireMeasures =
false;
7810 bool overlapOrRadiusFilter =
false;
7811 if ( isIntersectsFunc )
7814 node = QgsExpressionUtils::getNode( values.at( 5 ), parent );
7816 const QVariant minOverlapValue = node->eval( parent, context );
7818 minOverlap = QgsExpressionUtils::getDoubleValue( minOverlapValue, parent );
7819 node = QgsExpressionUtils::getNode( values.at( 6 ), parent );
7821 const QVariant minInscribedCircleRadiusValue = node->eval( parent, context );
7823 minInscribedCircleRadius = QgsExpressionUtils::getDoubleValue( minInscribedCircleRadiusValue, parent );
7824 node = QgsExpressionUtils::getNode( values.at( 7 ), parent );
7826 returnDetails = !testOnly && node->eval( parent, context ).toBool();
7827 node = QgsExpressionUtils::getNode( values.at( 8 ), parent );
7829 const QString sorting { node->eval( parent, context ).toString().toLower() };
7830 sortByMeasure = !testOnly && ( sorting.startsWith(
"asc" ) || sorting.startsWith(
"des" ) );
7831 sortAscending = sorting.startsWith(
"asc" );
7832 requireMeasures = sortByMeasure || returnDetails;
7833 overlapOrRadiusFilter = minInscribedCircleRadius != -1 || minOverlap != -1;
7840 if ( sourceLayer && targetLayer->crs() != sourceLayer->crs() )
7843 request.setDestinationCrs( sourceLayer->crs(), TransformContext );
7846 bool sameLayers = ( sourceLayer && sourceLayer->id() == targetLayer->id() );
7849 if ( bboxGrow != 0 )
7851 intDomain.
grow( bboxGrow );
7854 const QString cacheBase { QStringLiteral(
"%1:%2:%3" ).arg( targetLayer->id(), subExpString, filterString ) };
7860 QList<QgsFeature> features;
7861 if ( isNearestFunc || ( layerCanBeCached && cacheEnabled ) )
7865 const QString cacheLayer { QStringLiteral(
"ovrlaylyr:%1" ).arg( cacheBase ) };
7866 const QString cacheIndex { QStringLiteral(
"ovrlayidx:%1" ).arg( cacheBase ) };
7870 cachedTarget = targetLayer->
materialize( request );
7871 if ( layerCanBeCached )
7872 context->
setCachedValue( cacheLayer, QVariant::fromValue( cachedTarget ) );
7882 if ( layerCanBeCached )
7883 context->
setCachedValue( cacheIndex, QVariant::fromValue( spatialIndex ) );
7890 QList<QgsFeatureId> fidsList;
7891 if ( isNearestFunc )
7893 fidsList = spatialIndex.
nearestNeighbor( geometry, sameLayers ? limit + 1 : limit, max_distance );
7897 fidsList = spatialIndex.
intersects( intDomain );
7900 QListIterator<QgsFeatureId> i( fidsList );
7901 while ( i.hasNext() )
7904 if ( sameLayers && feat.
id() == fId2 )
7906 features.append( cachedTarget->
getFeature( fId2 ) );
7914 request.setFilterRect( intDomain );
7919 if ( sameLayers && feat.
id() == feat2.
id() )
7921 features.append( feat2 );
7929 const QString expCacheKey { QStringLiteral(
"exp:%1" ).arg( cacheBase ) };
7930 const QString ctxCacheKey { QStringLiteral(
"ctx:%1" ).arg( cacheBase ) };
7936 subExpression.
prepare( &subContext );
7949 auto testLinestring = [ = ](
const QgsGeometry intersection,
double & overlapValue ) ->
bool
7951 bool testResult {
false };
7953 QVector<double> overlapValues;
7956 const QgsCurve *geom = qgsgeometry_cast< const QgsCurve * >( *it );
7958 if ( minOverlap != -1 || requireMeasures )
7960 overlapValue = geom->
length();
7961 overlapValues.append( overlapValue );
7962 if ( minOverlap != -1 )
7964 if ( overlapValue >= minOverlap )
7976 if ( ! overlapValues.isEmpty() )
7978 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
7985 auto testPolygon = [ = ](
const QgsGeometry intersection,
double & radiusValue,
double & overlapValue ) ->
bool
7988 bool testResult {
false };
7990 QVector<double> overlapValues;
7991 QVector<double> radiusValues;
7994 const QgsCurvePolygon *geom = qgsgeometry_cast< const QgsCurvePolygon * >( *it );
7996 if ( minOverlap != -1 || requireMeasures )
7998 overlapValue = geom->
area();
7999 overlapValues.append( geom->
area() );
8000 if ( minOverlap != - 1 )
8002 if ( overlapValue >= minOverlap )
8014 if ( minInscribedCircleRadius != -1 || requireMeasures )
8017 const double width = bbox.
width();
8018 const double height = bbox.
height();
8019 const double size = width > height ? width : height;
8020 const double tolerance = size / 100.0;
8022 testResult = radiusValue >= minInscribedCircleRadius;
8023 radiusValues.append( radiusValues );
8028 if ( !radiusValues.isEmpty() )
8030 radiusValue = *std::max_element( radiusValues.cbegin(), radiusValues.cend() );
8033 if ( ! overlapValues.isEmpty() )
8035 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
8045 QVariantList results;
8047 QListIterator<QgsFeature> i( features );
8048 while ( i.hasNext() && ( sortByMeasure || limit == -1 || foundCount < limit ) )
8054 if ( ! relationFunction || ( geometry.*relationFunction )( feat2.
geometry() ) )
8057 double overlapValue = -1;
8058 double radiusValue = -1;
8060 if ( isIntersectsFunc && ( requireMeasures || overlapOrRadiusFilter ) )
8067 switch ( intersection.
type() )
8074 bool testResult { testPolygon( intersection, radiusValue, overlapValue ) };
8076 if ( ! testResult && overlapOrRadiusFilter )
8089 if ( minInscribedCircleRadius != -1 )
8095 const bool testResult { testLinestring( intersection, overlapValue ) };
8097 if ( ! testResult && overlapOrRadiusFilter )
8110 if ( minInscribedCircleRadius != -1 )
8115 bool testResult {
false };
8116 if ( minOverlap != -1 || requireMeasures )
8136 testResult = testLinestring( feat2.
geometry(), overlapValue );
8141 testResult = testPolygon( feat2.
geometry(), radiusValue, overlapValue );
8147 if ( ! testResult && overlapOrRadiusFilter )
8175 const QVariant expResult = subExpression.
evaluate( &subContext );
8177 if ( requireMeasures )
8179 QVariantMap resultRecord;
8180 resultRecord.insert( QStringLiteral(
"id" ), feat2.
id() );
8181 resultRecord.insert( QStringLiteral(
"result" ), expResult );
8183 resultRecord.insert( QStringLiteral(
"overlap" ), overlapValue );
8185 if ( radiusValue != -1 )
8187 resultRecord.insert( QStringLiteral(
"radius" ), radiusValue );
8189 results.append( resultRecord );
8193 results.append( expResult );
8199 results.append( feat2.
id() );
8213 if ( requireMeasures )
8215 if ( sortByMeasure )
8217 std::sort( results.begin(), results.end(), [ sortAscending ](
const QVariant & recordA,
const QVariant & recordB ) ->
bool
8219 return sortAscending ?
8220 recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble()
8221 : recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble();
8225 if ( limit > 0 && results.size() > limit )
8227 results.erase( results.begin() + limit );
8230 if ( ! returnDetails )
8232 QVariantList expResults;
8233 for (
auto it = results.constBegin(); it != results.constEnd(); ++it )
8235 expResults.append( it->toMap().value( QStringLiteral(
"result" ) ) );
8245 QVariantList disjoint_results;
8254 if ( !results.contains( feat2.
id() ) )
8257 disjoint_results.append( subExpression.
evaluate( &subContext ) );
8260 return disjoint_results;
8303 return executeGeomOverlay( values, context, parent,
nullptr,
false, 0,
true );
8312 QMutexLocker locker( &sFunctionsMutex );
8314 QList<QgsExpressionFunction *> &functions = *sFunctions();
8316 if ( functions.isEmpty() )
8354 functions << randFunc;
8358 functions << randfFunc;
8361 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max" ), -1, fcnMax, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8362 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min" ), -1, fcnMin, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8369 <<
new QgsStaticExpressionFunction( QStringLiteral(
"pi" ), 0, fcnPi, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$pi" ) )
8373 <<
new QgsStaticExpressionFunction( QStringLiteral(
"to_datetime" ),
QgsExpressionFunction::ParameterList() <<
QgsExpressionFunction::Parameter( QStringLiteral(
"value" ) ) <<
QgsExpressionFunction::Parameter( QStringLiteral(
"format" ),
true, QVariant() ) <<
QgsExpressionFunction::Parameter( QStringLiteral(
"language" ),
true, QVariant() ), fcnToDateTime, QStringList() << QStringLiteral(
"Conversions" ) << QStringLiteral(
"Date and Time" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"todatetime" ) )
8374 <<
new QgsStaticExpressionFunction( QStringLiteral(
"to_date" ),
QgsExpressionFunction::ParameterList() <<
QgsExpressionFunction::Parameter( QStringLiteral(
"value" ) ) <<
QgsExpressionFunction::Parameter( QStringLiteral(
"format" ),
true, QVariant() ) <<
QgsExpressionFunction::Parameter( QStringLiteral(
"language" ),
true, QVariant() ), fcnToDate, QStringList() << QStringLiteral(
"Conversions" ) << QStringLiteral(
"Date and Time" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"todate" ) )
8375 <<
new QgsStaticExpressionFunction( QStringLiteral(
"to_time" ),
QgsExpressionFunction::ParameterList() <<
QgsExpressionFunction::Parameter( QStringLiteral(
"value" ) ) <<
QgsExpressionFunction::Parameter( QStringLiteral(
"format" ),
true, QVariant() ) <<
QgsExpressionFunction::Parameter( QStringLiteral(
"language" ),
true, QVariant() ), fcnToTime, QStringList() << QStringLiteral(
"Conversions" ) << QStringLiteral(
"Date and Time" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"totime" ) )
8380 <<
new QgsStaticExpressionFunction( QStringLiteral(
"coalesce" ), -1, fcnCoalesce, QStringLiteral(
"Conditionals" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8394 QStringLiteral(
"Aggregates" ),
8403 if ( !node->
args() )
8406 QSet<QString> referencedVars;
8418 return referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() );
8427 if ( !node->
args() )
8428 return QSet<QString>();
8430 QSet<QString> referencedCols;
8431 QSet<QString> referencedVars;
8446 if ( referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() ) )
8449 return referencedCols;
8462 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count" ), aggParams, fcnAggregateCount, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8463 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_distinct" ), aggParams, fcnAggregateCountDistinct, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8464 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_missing" ), aggParams, fcnAggregateCountMissing, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8465 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minimum" ), aggParams, fcnAggregateMin, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8466 <<
new QgsStaticExpressionFunction( QStringLiteral(
"maximum" ), aggParams, fcnAggregateMax, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8467 <<
new QgsStaticExpressionFunction( QStringLiteral(
"sum" ), aggParams, fcnAggregateSum, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8468 <<
new QgsStaticExpressionFunction( QStringLiteral(
"mean" ), aggParams, fcnAggregateMean, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8469 <<
new QgsStaticExpressionFunction( QStringLiteral(
"median" ), aggParams, fcnAggregateMedian, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8470 <<
new QgsStaticExpressionFunction( QStringLiteral(
"stdev" ), aggParams, fcnAggregateStdev, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8471 <<
new QgsStaticExpressionFunction( QStringLiteral(
"range" ), aggParams, fcnAggregateRange, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8472 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minority" ), aggParams, fcnAggregateMinority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8473 <<
new QgsStaticExpressionFunction( QStringLiteral(
"majority" ), aggParams, fcnAggregateMajority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8474 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q1" ), aggParams, fcnAggregateQ1, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8475 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q3" ), aggParams, fcnAggregateQ3, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8476 <<
new QgsStaticExpressionFunction( QStringLiteral(
"iqr" ), aggParams, fcnAggregateIQR, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8477 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min_length" ), aggParams, fcnAggregateMinLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8478 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max_length" ), aggParams, fcnAggregateMaxLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8479 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect" ), aggParams, fcnAggregateCollectGeometry, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8480 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate" ), aggParamsConcat, fcnAggregateStringConcat, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8481 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate_unique" ), aggParamsConcat, fcnAggregateStringConcatUnique, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8482 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array_agg" ), aggParamsArray, fcnAggregateArray, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8487 <<
new QgsStaticExpressionFunction( QStringLiteral(
"now" ), 0, fcnNow, QStringLiteral(
"Date and Time" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$now" ) )
8490 fcnAge, QStringLiteral(
"Date and Time" ) )
8504 fcnMakeDate, QStringLiteral(
"Date and Time" ) )
8508 fcnMakeTime, QStringLiteral(
"Date and Time" ) )
8515 fcnMakeDateTime, QStringLiteral(
"Date and Time" ) )
8523 fcnMakeInterval, QStringLiteral(
"Date and Time" ) )
8548 false, QSet< QString >(),
false, QStringList(), true )
8549 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concat" ), -1, fcnConcat, QStringLiteral(
"String" ), QString(),
false, QSet<QString>(),
false, QStringList(), true )
8567 fcnColorMixRgb, QStringLiteral(
"Color" ) )
8571 fcnColorMix, QStringLiteral(
"Color" ) )
8575 fcnColorRgb, QStringLiteral(
"Color" ) )
8580 fcnColorRgbF, QStringLiteral(
"Color" ) )
8585 fncColorRgba, QStringLiteral(
"Color" ) )
8594 fcnCreateRamp, QStringLiteral(
"Color" ) )
8598 fcnColorHsl, QStringLiteral(
"Color" ) )
8603 fncColorHsla, QStringLiteral(
"Color" ) )
8608 fcnColorHslF, QStringLiteral(
"Color" ) )
8612 fcnColorHsv, QStringLiteral(
"Color" ) )
8617 fncColorHsva, QStringLiteral(
"Color" ) )
8622 fcnColorHsvF, QStringLiteral(
"Color" ) )
8627 fcnColorCmyk, QStringLiteral(
"Color" ) )
8633 fncColorCmyka, QStringLiteral(
"Color" ) )
8639 fcnColorCmykF, QStringLiteral(
"Color" ) )
8642 fncColorPart, QStringLiteral(
"Color" ) )
8645 fncDarker, QStringLiteral(
"Color" ) )
8648 fncLighter, QStringLiteral(
"Color" ) )
8653 fcnBaseFileName, QStringLiteral(
"Files and Paths" ) )
8655 fcnFileSuffix, QStringLiteral(
"Files and Paths" ) )
8657 fcnFileExists, QStringLiteral(
"Files and Paths" ) )
8659 fcnFileName, QStringLiteral(
"Files and Paths" ) )
8661 fcnPathIsFile, QStringLiteral(
"Files and Paths" ) )
8663 fcnPathIsDir, QStringLiteral(
"Files and Paths" ) )
8665 fcnFilePath, QStringLiteral(
"Files and Paths" ) )
8667 fcnFileSize, QStringLiteral(
"Files and Paths" ) )
8670 fcnExif, QStringLiteral(
"Files and Paths" ) )
8672 fcnExifGeoTag, QStringLiteral(
"GeometryGroup" ) )
8676 fcnGenericHash, QStringLiteral(
"Conversions" ) )
8678 fcnHashMd5, QStringLiteral(
"Conversions" ) )
8680 fcnHashSha256, QStringLiteral(
"Conversions" ) )
8684 fcnToBase64, QStringLiteral(
"Conversions" ) )
8686 fcnFromBase64, QStringLiteral(
"Conversions" ) )
8692 geomFunc->setIsStatic(
false );
8693 functions << geomFunc;
8697 functions << areaFunc;
8703 functions << lengthFunc;
8707 functions << perimeterFunc;
8713 fcnRoundness, QStringLiteral(
"GeometryGroup" ) );
8727 QMap< QString, QgsExpressionFunction::FcnEval > geometry_overlay_definitions
8729 { QStringLiteral(
"overlay_intersects" ), fcnGeomOverlayIntersects },
8730 { QStringLiteral(
"overlay_contains" ), fcnGeomOverlayContains },
8731 { QStringLiteral(
"overlay_crosses" ), fcnGeomOverlayCrosses },
8732 { QStringLiteral(
"overlay_equals" ), fcnGeomOverlayEquals },
8733 { QStringLiteral(
"overlay_touches" ), fcnGeomOverlayTouches },
8734 { QStringLiteral(
"overlay_disjoint" ), fcnGeomOverlayDisjoint },
8735 { QStringLiteral(
"overlay_within" ), fcnGeomOverlayWithin },
8737 QMapIterator< QString, QgsExpressionFunction::FcnEval > i( geometry_overlay_definitions );
8738 while ( i.hasNext() )
8755 functions << fcnGeomOverlayFunc;
8768 functions << fcnGeomOverlayNearestFunc;
8781 fcnNodesToPoints, QStringLiteral(
"GeometryGroup" ) )
8783 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect_geometries" ), -1, fcnCollectGeometries, QStringLiteral(
"GeometryGroup" ) )
8788 fcnMakePointM, QStringLiteral(
"GeometryGroup" ) )
8794 fcnMakeTriangle, QStringLiteral(
"GeometryGroup" ) )
8799 fcnMakeCircle, QStringLiteral(
"GeometryGroup" ) )
8806 fcnMakeEllipse, QStringLiteral(
"GeometryGroup" ) )
8812 fcnMakeRegularPolygon, QStringLiteral(
"GeometryGroup" ) )
8816 fcnMakeSquare, QStringLiteral(
"GeometryGroup" ) )
8822 fcnMakeRectangleFrom3Points, QStringLiteral(
"GeometryGroup" ) )
8826#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
8832 }, fcnGeomMakeValid, QStringLiteral(
"GeometryGroup" ) );
8841 functions << xAtFunc;
8846 functions << yAtFunc;
8862 fcnDisjoint, QStringLiteral(
"GeometryGroup" ) )
8865 fcnIntersects, QStringLiteral(
"GeometryGroup" ) )
8868 fcnTouches, QStringLiteral(
"GeometryGroup" ) )
8871 fcnCrosses, QStringLiteral(
"GeometryGroup" ) )
8874 fcnContains, QStringLiteral(
"GeometryGroup" ) )
8877 fcnOverlaps, QStringLiteral(
"GeometryGroup" ) )
8880 fcnWithin, QStringLiteral(
"GeometryGroup" ) )
8884 fcnTranslate, QStringLiteral(
"GeometryGroup" ) )
8889 fcnRotate, QStringLiteral(
"GeometryGroup" ) )
8894 fcnScale, QStringLiteral(
"GeometryGroup" ) )
8905 fcnAffineTransform, QStringLiteral(
"GeometryGroup" ) )
8912 fcnBuffer, QStringLiteral(
"GeometryGroup" ) )
8914 fcnForceRHR, QStringLiteral(
"GeometryGroup" ) )
8916 fcnForcePolygonCW, QStringLiteral(
"GeometryGroup" ) )
8918 fcnForcePolygonCCW, QStringLiteral(
"GeometryGroup" ) )
8928 , fcnTaperedBuffer, QStringLiteral(
"GeometryGroup" ) )
8931 , fcnBufferByM, QStringLiteral(
"GeometryGroup" ) )
8937 fcnOffsetCurve, QStringLiteral(
"GeometryGroup" ) )
8943 fcnSingleSidedBuffer, QStringLiteral(
"GeometryGroup" ) )
8947 fcnExtend, QStringLiteral(
"GeometryGroup" ) )
8956 fcnInteriorRingN, QStringLiteral(
"GeometryGroup" ) )
8959 fcnGeometryN, QStringLiteral(
"GeometryGroup" ) )
8966 }, fcnSharedPaths, QStringLiteral(
"GeometryGroup" ) )
8980 }, fcnTriangularWave, QStringLiteral(
"GeometryGroup" ) )
8989 }, fcnTriangularWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
8996 }, fcnSquareWave, QStringLiteral(
"GeometryGroup" ) )
9005 }, fcnSquareWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9012 }, fcnRoundWave, QStringLiteral(
"GeometryGroup" ) )
9021 }, fcnRoundWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9030 }, fcnApplyDashPattern, QStringLiteral(
"GeometryGroup" ) )
9035 }, fcnDensifyByCount, QStringLiteral(
"GeometryGroup" ) )
9040 }, fcnDensifyByDistance, QStringLiteral(
"GeometryGroup" ) )
9052#
if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
9059 fcnOrientedBBox, QStringLiteral(
"GeometryGroup" ) )
9062 fcnMainAngle, QStringLiteral(
"GeometryGroup" ) )
9066 fcnMinimalCircle, QStringLiteral(
"GeometryGroup" ) )
9069 fcnDifference, QStringLiteral(
"GeometryGroup" ) )
9072 fcnDistance, QStringLiteral(
"GeometryGroup" ) )
9075 fcnHausdorffDistance, QStringLiteral(
"GeometryGroup" ) )
9078 fcnIntersection, QStringLiteral(
"GeometryGroup" ) )
9081 fcnSymDifference, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"symDifference" ) )
9084 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
9087 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
9090 fcnGeomToWKT, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"geomToWKT" ) )
9092 fcnGeomToWKB, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false )
9097 fcnTransformGeometry, QStringLiteral(
"GeometryGroup" ) )
9101 fcnExtrude, QStringLiteral(
"GeometryGroup" ), QString() )
9103 fcnGeomIsMultipart, QStringLiteral(
"GeometryGroup" ) )
9105 fcnZMax, QStringLiteral(
"GeometryGroup" ) )
9107 fcnZMin, QStringLiteral(
"GeometryGroup" ) )
9109 fcnMMax, QStringLiteral(
"GeometryGroup" ) )
9111 fcnMMin, QStringLiteral(
"GeometryGroup" ) )
9113 fcnSinuosity, QStringLiteral(
"GeometryGroup" ) )
9115 fcnStraightDistance2d, QStringLiteral(
"GeometryGroup" ) );
9121 fcnOrderParts, QStringLiteral(
"GeometryGroup" ), QString() );
9126 const QList< QgsExpressionNode *> argList = node->
args()->list();
9129 if ( !argNode->isStatic( parent, context ) )
9137 QString expString = argNode->
eval( parent, context ).toString();
9141 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9153 QString
expression = argNode->
eval( parent, context ).toString();
9155 e.prepare( context );
9161 functions << orderPartsFunc;
9166 fcnClosestPoint, QStringLiteral(
"GeometryGroup" ) )
9169 fcnShortestLine, QStringLiteral(
"GeometryGroup" ) )
9174 fcnLineInterpolatePointByM, QStringLiteral(
"GeometryGroup" ) )
9181 fcnLineLocateM, QStringLiteral(
"GeometryGroup" ) )
9194 functions << idFunc;
9198 functions << currentFeatureFunc;
9200 QgsStaticExpressionFunction *uuidFunc =
new QgsStaticExpressionFunction( QStringLiteral(
"uuid" ),
QgsExpressionFunction::ParameterList() <<
QgsExpressionFunction::Parameter( QStringLiteral(
"format" ),
true, QStringLiteral(
"WithBraces" ) ), fcnUuid, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$uuid" ) );
9202 functions << uuidFunc;
9209 fcnGetFeature, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"QgsExpressionUtils::getFeature" ) )
9212 fcnGetFeatureById, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false );
9217 functions << attributesFunc;
9221 functions << representAttributesFunc;
9229 functions << validateFeature;
9238 functions << validateAttribute;
9241 QStringLiteral(
"maptip" ),
9244 QStringLiteral(
"Record and Attributes" ),
9250 functions << maptipFunc;
9253 QStringLiteral(
"display_expression" ),
9255 fcnFeatureDisplayExpression,
9256 QStringLiteral(
"Record and Attributes" ),
9262 functions << displayFunc;
9265 QStringLiteral(
"is_selected" ),
9268 QStringLiteral(
"Record and Attributes" ),
9274 functions << isSelectedFunc;
9278 QStringLiteral(
"num_selected" ),
9281 QStringLiteral(
"Record and Attributes" ),
9289 QStringLiteral(
"sqlite_fetch_and_increment" ),
9297 fcnSqliteFetchAndIncrement,
9298 QStringLiteral(
"Record and Attributes" )
9316 parent->
setEvalErrorString( tr(
"If represent_value is called with 1 parameter, it must be an attribute." ) );
9326 parent->
setEvalErrorString( tr(
"represent_value must be called with exactly 1 or 2 parameters." ) );
9332 functions << representValueFunc;
9338 fcnGetLayerProperty, QStringLiteral(
"Map Layers" ) )
9343 fcnDecodeUri, QStringLiteral(
"Map Layers" ) )
9347 fcnMimeType, QStringLiteral(
"General" ) )
9364 QgsExpressionNode *argNode = node->args()->at( 0 );
9366 if ( !argNode->isStatic( parent, context ) )
9369 const QString varName = argNode->eval( parent, context ).toString();
9370 if ( varName == QLatin1String(
"feature" ) || varName == QLatin1String(
"id" ) || varName == QLatin1String(
"geometry" ) )
9373 const QgsExpressionContextScope *scope = context->activeScopeForVariable( varName );
9374 return scope ? scope->isStatic( varName ) : false;
9382 if ( node && node->
args()->
count() > 0 )
9387 if ( literal->value() == QLatin1String(
"geometry" ) || literal->value() == QLatin1String(
"feature" ) )
9404 QgsExpressionNode *argNode = node->args()->at( 0 );
9406 if ( argNode->isStatic( parent, context ) )
9408 QString expString = argNode->eval( parent, context ).toString();
9410 QgsExpression e( expString );
9412 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9419 functions << evalTemplateFunction;
9427 QgsExpressionNode *argNode = node->args()->at( 0 );
9429 if ( argNode->isStatic( parent, context ) )
9431 QString expString = argNode->eval( parent, context ).toString();
9433 QgsExpression e( expString );
9435 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9443 functions << evalFunc;
9449 const QList< QgsExpressionNode *> argList = node->
args()->list();
9452 if ( !argNode->
isStatic( parent, context ) )
9464 functions << attributeFunc;
9475 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array" ), -1, fcnArray, QStringLiteral(
"Arrays" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
9524 fcnMapPrefixKeys, QStringLiteral(
"Maps" ) )
9526 fcnMapToHtmlTable, QStringLiteral(
"Maps" ) )
9528 fcnMapToHtmlDefinitionList, QStringLiteral(
"Maps" ) )
9530 fcnToFormUrlEncode, QStringLiteral(
"Maps" ) )
9539 *sOwnedFunctions() << func;
9540 *sBuiltinFunctions() << func->name();
9541 sBuiltinFunctions()->append( func->aliases() );
9555 QMutexLocker locker( &sFunctionsMutex );
9556 sFunctions()->append( function );
9557 if ( transferOwnership )
9558 sOwnedFunctions()->append( function );
9573 QMutexLocker locker( &sFunctionsMutex );
9574 sFunctions()->removeAt( fnIdx );
9575 sFunctionIndexMap.clear();
9583 qDeleteAll( *sOwnedFunctions() );
9584 sOwnedFunctions()->clear();
9589 if ( sBuiltinFunctions()->isEmpty() )
9593 return *sBuiltinFunctions();
9600 QStringLiteral(
"Arrays" ) )
9611 if ( args->
count() < 2 )
9614 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9624 QVariantList result;
9626 if ( args->
count() < 2 )
9630 QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9633 std::unique_ptr< QgsExpressionContext > tempContext;
9636 tempContext = std::make_unique< QgsExpressionContext >();
9637 subContext = tempContext.get();
9644 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it, ++i )
9648 result << args->
at( 1 )->
eval( parent, subContext );
9673 if ( args->
count() < 2 )
9677 args->
at( 0 )->
prepare( parent, context );
9681 subContext = *context;
9688 args->
at( 1 )->
prepare( parent, &subContext );
9698 QStringLiteral(
"Arrays" ) )
9709 if ( args->
count() < 2 )
9712 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9722 QVariantList result;
9724 if ( args->
count() < 2 )
9728 const QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9731 std::unique_ptr< QgsExpressionContext > tempContext;
9734 tempContext = std::make_unique< QgsExpressionContext >();
9735 subContext = tempContext.get();
9742 if ( args->
count() >= 3 )
9744 const QVariant limitVar = args->
at( 2 )->
eval( parent, context );
9746 if ( QgsExpressionUtils::isIntSafe( limitVar ) )
9748 limit = limitVar.toInt();
9756 for (
const QVariant &value : array )
9759 if ( args->
at( 1 )->
eval( parent, subContext ).toBool() )
9763 if ( limit > 0 && limit == result.size() )
9790 if ( args->
count() < 2 )
9794 args->
at( 0 )->
prepare( parent, context );
9798 subContext = *context;
9804 args->
at( 1 )->
prepare( parent, &subContext );
9813 QStringLiteral(
"General" ) )
9824 if ( args->
count() < 3 )
9828 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9830 QVariant
name = args->
at( 0 )->
eval( parent, context );
9831 QVariant value = args->
at( 1 )->
eval( parent, context );
9834 appendTemporaryVariable( context,
name.toString(), value );
9835 if ( args->
at( 2 )->
isStatic( parent, context ) )
9837 popTemporaryVariable( context );
9848 if ( args->
count() < 3 )
9852 QVariant
name = args->
at( 0 )->
eval( parent, context );
9853 QVariant value = args->
at( 1 )->
eval( parent, context );
9856 std::unique_ptr< QgsExpressionContext > tempContext;
9857 if ( !updatedContext )
9859 tempContext = std::make_unique< QgsExpressionContext >();
9860 updatedContext = tempContext.get();
9863 appendTemporaryVariable( updatedContext,
name.toString(), value );
9864 result = args->
at( 2 )->
eval( parent, updatedContext );
9867 popTemporaryVariable( updatedContext );
9888 if ( args->
count() < 3 )
9893 QVariant value = args->
at( 1 )->
prepare( parent, context );
9896 std::unique_ptr< QgsExpressionContext > tempContext;
9897 if ( !updatedContext )
9899 tempContext = std::make_unique< QgsExpressionContext >();
9900 updatedContext = tempContext.get();
9903 appendTemporaryVariable( updatedContext,
name.toString(), value );
9904 args->
at( 2 )->
prepare( parent, updatedContext );
9907 popTemporaryVariable( updatedContext );
9912void QgsWithVariableExpressionFunction::popTemporaryVariable(
const QgsExpressionContext *context )
const
9918void QgsWithVariableExpressionFunction::appendTemporaryVariable(
const QgsExpressionContext *context,
const QString &name,
const QVariant &value )
const
@ Left
Buffer to left of line.
DashPatternSizeAdjustment
Dash pattern size adjustment options.
@ ScaleDashOnly
Only dash lengths are adjusted.
@ ScaleBothDashAndGap
Both the dash and gap lengths are adjusted equally.
@ ScaleGapOnly
Only gap lengths are adjusted.
@ Success
Operation succeeded.
@ Visvalingam
The simplification gives each point in a line an importance weighting, so that least important points...
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
JoinStyle
Join styles for buffers.
@ Bevel
Use beveled joins.
@ Round
Use rounded joins.
@ Miter
Use mitered joins.
RasterBandStatistic
Available raster band statistics.
@ StdDev
Standard deviation.
@ NoStatistic
No statistic.
@ Group
Composite group layer. Added in QGIS 3.24.
@ Plugin
Plugin based layer.
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
EndCapStyle
End cap styles for buffers.
@ Flat
Flat cap (in line with start/end of line)
@ Square
Square cap (extends past start/end of line by buffer distance)
Aggregate
Available aggregates to calculate.
@ StringMinimumLength
Minimum length of string (string fields only)
@ FirstQuartile
First quartile (numeric fields only)
@ Mean
Mean of values (numeric fields only)
@ Median
Median of values (numeric fields only)
@ StringMaximumLength
Maximum length of string (string fields only)
@ Range
Range of values (max - min) (numeric and datetime fields only)
@ StringConcatenateUnique
Concatenate unique values with a joining string (string fields only). Specify the delimiter using set...
@ Minority
Minority of values.
@ CountMissing
Number of missing (null) values.
@ ArrayAggregate
Create an array of values.
@ Majority
Majority of values.
@ StDevSample
Sample standard deviation of values (numeric fields only)
@ ThirdQuartile
Third quartile (numeric fields only)
@ CountDistinct
Number of distinct values.
@ StringConcatenate
Concatenate values with a joining string (string fields only). Specify the delimiter using setDelimit...
@ GeometryCollect
Create a multipart geometry from aggregated geometries.
@ InterQuartileRange
Inter quartile range (IQR) (numeric fields only)
DashPatternLineEndingRule
Dash pattern line ending rules.
@ HalfDash
Start or finish the pattern with a half length dash.
@ HalfGap
Start or finish the pattern with a half length gap.
@ FullGap
Start or finish the pattern with a full gap.
@ FullDash
Start or finish the pattern with a full dash.
MakeValidMethod
Algorithms to use when repairing invalid geometries.
@ Linework
Combines all rings into a set of noded lines and then extracts valid polygons from that linework.
@ Structure
Structured method, first makes all rings valid and then merges shells and subtracts holes from shells...
Abstract base class for all geometries.
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
virtual QgsAbstractGeometry * boundary() const =0
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
virtual const QgsAbstractGeometry * simplifiedTypeRef() const
Returns a reference to the simplest lossless representation of this geometry, e.g.
bool isMeasure() const
Returns true if the geometry contains m values.
virtual QgsRectangle boundingBox() const
Returns the minimal bounding box for the geometry.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
part_iterator parts_end()
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
virtual double length() const
Returns the planar, 2-dimensional length of the geometry.
virtual QgsCoordinateSequence coordinateSequence() const =0
Retrieves the sequence of geometries, rings and nodes.
virtual int partCount() const =0
Returns count of parts contained in the geometry.
part_iterator parts_begin()
Returns STL-style iterator pointing to the first part of the geometry.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
static Qgis::Aggregate stringToAggregate(const QString &string, bool *ok=nullptr)
Converts a string to a aggregate type.
static QgsFieldFormatterRegistry * fieldFormatterRegistry()
Gets the registry of available field formatters.
Handles the array_filter(array, expression) expression function.
QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Returns result of evaluating the function.
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Evaluates the function, first evaluating all required arguments before passing them to the function's...
QgsArrayFilterExpressionFunction()
Handles the array loopingarray_Foreach(array, expression) expression function.
QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Returns result of evaluating the function.
QgsArrayForeachExpressionFunction()
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Evaluates the function, first evaluating all required arguments before passing them to the function's...
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
Abstract base class for color ramps.
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QString toProj() const
Returns a Proj string representation of this CRS.
QString ellipsoidAcronym() const
Returns the ellipsoid acronym for the ellipsoid used by the CRS.
Qgis::DistanceUnit mapUnits
Contains information about the context in which a coordinate transform is executed.
Custom exception class for Coordinate Reference System related exceptions.
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
bool isEmpty() const override
Returns true if the geometry is empty.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
double area() const override
Returns the planar, 2-dimensional area of the geometry.
double roundness() const
Returns the roundness of the curve polygon.
int ringCount(int part=0) const override
Returns the number of rings of which this geometry is built.
Abstract base class for curved geometry type.
double sinuosity() const
Returns the curve sinuosity, which is the ratio of the curve length() to curve straightDistance2d().
QgsCurve * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
virtual QgsCurve * curveSubstring(double startDistance, double endDistance) const =0
Returns a new curve representing a substring of this curve.
virtual bool isClosed() const
Returns true if the curve is closed.
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
double straightDistance2d() const
Returns the straight distance of the curve, i.e.
virtual QgsCurve * reversed() const =0
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
double measureArea(const QgsGeometry &geometry) const
Measures the area of a geometry.
double convertLengthMeasurement(double length, Qgis::DistanceUnit toUnits) const
Takes a length measurement calculated by this QgsDistanceArea object and converts it to a different d...
double measurePerimeter(const QgsGeometry &geometry) const
Measures the perimeter of a polygon geometry.
double measureLength(const QgsGeometry &geometry) const
Measures the length of a geometry.
double bearing(const QgsPointXY &p1, const QgsPointXY &p2) const
Computes the bearing (in radians) between two points.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
double convertAreaMeasurement(double area, Qgis::AreaUnit toUnits) const
Takes an area measurement calculated by this QgsDistanceArea object and converts it to a different ar...
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
bool isStatic(const QString &name) const
Tests whether the variable with the specified name is static and can be cached.
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
static void registerContextFunctions()
Registers all known core functions provided by QgsExpressionContextScope objects.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
void setCachedValue(const QString &key, const QVariant &value) const
Sets a value to cache within the expression context.
QString uniqueHash(bool &ok, const QSet< QString > &variables=QSet< QString >()) const
Returns a unique hash representing the current state of the context.
QgsGeometry geometry() const
Convenience function for retrieving the geometry for the context, if set.
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
QgsExpressionContextScope * activeScopeForVariable(const QString &name)
Returns the currently active scope from the context for a specified variable name.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly by the expression to check if evaluation sh...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
bool hasGeometry() const
Returns true if the context has a geometry associated with it.
bool hasCachedValue(const QString &key) const
Returns true if the expression context contains a cached value with a matching key.
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
QVariant cachedValue(const QString &key) const
Returns the matching cached value, if set.
bool hasFeature() const
Returns true if the context has a feature associated with it.
QgsFields fields() const
Convenience function for retrieving the fields for the context, if set.
Represents a single parameter passed to a function.
A abstract base class for defining QgsExpression functions.
QList< QgsExpressionFunction::Parameter > ParameterList
List of parameters, used for function definition.
bool operator==(const QgsExpressionFunction &other) const
virtual bool isDeprecated() const
Returns true if the function is deprecated and should not be presented as a valid option to users in ...
virtual bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
Will be called during prepare to determine if the function is static.
virtual QStringList aliases() const
Returns a list of possible aliases for the function.
bool lazyEval() const
true if this function should use lazy evaluation.
static bool allParamsStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context)
This will return true if all the params for the provided function node are static within the constrai...
QString name() const
The name of the function.
virtual QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
Evaluates the function, first evaluating all required arguments before passing them to the function's...
virtual QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)=0
Returns result of evaluating the function.
virtual QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const
Returns a set of field names which are required for this function.
virtual bool handlesNull() const
Returns true if the function handles NULL values in arguments by itself, and the default NULL value h...
virtual bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
This will be called during the prepare step() of an expression if it is not static.
virtual bool usesGeometry(const QgsExpressionNodeFunction *node) const
Does this function use a geometry object.
An expression node which takes it value from a feature's field.
QString name() const
The name of the column.
An expression node for expression functions.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
An expression node for literal values.
A list of expression nodes.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
QgsExpressionNode * at(int i)
Gets the node at position i in the list.
int count() const
Returns the number of nodes in the list.
Abstract base class for all nodes that can appear in an expression.
virtual QString dump() const =0
Dump this node into a serialized (part) of an expression.
QVariant eval(QgsExpression *parent, const QgsExpressionContext *context)
Evaluate this node with the given context and parent.
virtual bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const =0
Returns true if this node can be evaluated for a static value.
bool prepare(QgsExpression *parent, const QgsExpressionContext *context)
Prepare this node for evaluation.
virtual QSet< QString > referencedColumns() const =0
Abstract virtual method which returns a list of columns required to evaluate this node.
virtual QSet< QString > referencedVariables() const =0
Returns a set of all variables which are used in this expression.
A set of expression-related functions.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
static const QList< QgsExpressionFunction * > & Functions()
QString expression() const
Returns the original, unmodified expression string.
static void cleanRegisteredFunctions()
Deletes all registered functions whose ownership have been transferred to the expression engine.
Qgis::DistanceUnit distanceUnits() const
Returns the desired distance units for calculations involving geomCalculator(), e....
static bool registerFunction(QgsExpressionFunction *function, bool transferOwnership=false)
Registers a function to the expression engine.
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
static const QStringList & BuiltinFunctions()
static QString replaceExpressionText(const QString &action, const QgsExpressionContext *context, const QgsDistanceArea *distanceArea=nullptr)
This function replaces each expression between [% and %] in the string with the result of its evaluat...
static PRIVATE QString helpText(QString name)
Returns the help text for a specified function.
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value, QMetaType::Type fieldType=QMetaType::Type::UnknownType)
Create an expression allowing to evaluate if a field is equal to a value.
static bool unregisterFunction(const QString &name)
Unregisters a function from the expression engine.
Qgis::AreaUnit areaUnits() const
Returns the desired areal units for calculations involving geomCalculator(), e.g.,...
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions)
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QVariant evaluate()
Evaluate the feature and return the result.
QgsDistanceArea * geomCalculator()
Returns calculator used for distance and area calculations (used by $length, $area and $perimeter fun...
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
Represents a list of OrderByClauses, with the most important first and the least important last.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsFeatureRequest & setRequestMayBeNested(bool requestMayBeNested)
In case this request may be run nested within another already running iteration on the same connectio...
QgsFeatureRequest & setTimeout(int timeout)
Sets the timeout (in milliseconds) for the maximum time we should wait during feature requests before...
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
void setFeedback(QgsFeedback *feedback)
Attach a feedback object that can be queried regularly by the iterator to check if it should be cance...
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Sets the feature ID that should be fetched.
QgsVectorLayer * materialize(const QgsFeatureRequest &request, QgsFeedback *feedback=nullptr)
Materializes a request (query) made against this feature source, by running it over the source and re...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
bool isValid() const
Returns the validity of this feature.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
ConstraintStrength
Strength of constraints.
@ ConstraintStrengthNotSet
Constraint is not set.
@ ConstraintStrengthSoft
User is warned if constraint is violated but feature can still be accepted.
@ ConstraintStrengthHard
Constraint must be honored before feature can be accepted.
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Container of fields for a vector layer.
Q_INVOKABLE int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
int size() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
virtual bool removeGeometry(int nr)
Removes a geometry from the collection.
QgsGeometryCollection * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
int partCount() const override
Returns count of parts contained in the geometry.
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
static QVector< QgsLineString * > extractLineStrings(const QgsAbstractGeometry *geom)
Returns list of linestrings extracted from the passed geometry.
A geometry is the spatial representation of a feature.
double hausdorffDistanceDensify(const QgsGeometry &geom, double densifyFraction) const
Returns the Hausdorff distance between this geometry and geom.
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Returns a copy of the geometry which has been densified by adding the specified number of extra nodes...
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
double lineLocatePoint(const QgsGeometry &point) const
Returns a distance representing the location along this linestring of the closest point on this lines...
QgsGeometry difference(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing the points making up this geometry that do not make up other.
double length() const
Returns the planar, 2-dimensional length of geometry.
QgsGeometry offsetCurve(double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
QgsGeometry poleOfInaccessibility(double precision, double *distanceToBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
QgsGeometry squareWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs square waves along the boundary of the geometry, with the specified wavelength and amplitu...
QgsGeometry triangularWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs triangular waves along the boundary of the geometry, with the specified wavelength and amp...
bool vertexIdFromVertexNr(int number, QgsVertexId &id) const
Calculates the vertex ID from a vertex number.
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
bool touches(const QgsGeometry &geometry) const
Returns true if the geometry touches another geometry.
QgsGeometry applyDashPattern(const QVector< double > &pattern, Qgis::DashPatternLineEndingRule startRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternLineEndingRule endRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternSizeAdjustment adjustment=Qgis::DashPatternSizeAdjustment::ScaleBothDashAndGap, double patternOffset=0) const
Applies a dash pattern to a geometry, returning a MultiLineString geometry which is the input geometr...
QgsGeometry roundWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs rounded (sine-like) waves along the boundary of the geometry, with the specified wavelengt...
QgsGeometry nearestPoint(const QgsGeometry &other) const
Returns the nearest (closest) point on this geometry to another geometry.
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
QgsGeometry makeValid(Qgis::MakeValidMethod method=Qgis::MakeValidMethod::Linework, bool keepCollapsed=false) const
Attempts to make an invalid geometry valid without losing vertices.
QString lastError() const
Returns an error string referring to the last error encountered either when this geometry was created...
QgsGeometry combine(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing all the points in this geometry and other (a union geometry operation...
QgsGeometry variableWidthBufferByM(int segments) const
Calculates a variable width buffer for a (multi)linestring geometry, where the width at each node is ...
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
QgsMultiPointXY asMultiPoint() const
Returns the contents of the geometry as a multi-point.
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
bool disjoint(const QgsGeometry &geometry) const
Returns true if the geometry is disjoint of another geometry.
QVector< QgsGeometry > asGeometryCollection() const
Returns contents of the geometry as a list of geometries.
QgsGeometry roundWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized rounded (sine-like) waves along the boundary of the geometry,...
double distance(const QgsGeometry &geom) const
Returns the minimum distance between this geometry and another geometry.
QgsGeometry interpolate(double distance) const
Returns an interpolated point on the geometry at the specified distance.
QgsGeometry extrude(double x, double y)
Returns an extruded version of this geometry.
QgsGeometry singleSidedBuffer(double distance, int segments, Qgis::BufferSide side, Qgis::JoinStyle joinStyle=Qgis::JoinStyle::Round, double miterLimit=2.0) const
Returns a single sided buffer for a (multi)line geometry.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
static Q_INVOKABLE QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
bool contains(const QgsPointXY *p) const
Returns true if the geometry contains the point p.
QgsGeometry forceRHR() const
Forces geometries to respect the Right-Hand-Rule, in which the area that is bounded by a polygon is t...
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
bool equals(const QgsGeometry &geometry) const
Test if this geometry is exactly equal to another geometry.
bool isGeosValid(Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const
Checks validity of the geometry using GEOS.
QgsGeometry taperedBuffer(double startWidth, double endWidth, int segments) const
Calculates a variable width buffer ("tapered buffer") for a (multi)curve geometry.
bool within(const QgsGeometry &geometry) const
Returns true if the geometry is completely within another geometry.
QgsGeometry orientedMinimumBoundingBox(double &area, double &angle, double &width, double &height) const
Returns the oriented minimum bounding box for the geometry, which is the smallest (by area) rotated r...
double area() const
Returns the planar, 2-dimensional area of the geometry.
bool isMultipart() const
Returns true if WKB of the geometry is of WKBMulti* type.
QgsGeometry centroid() const
Returns the center of mass of a geometry.
bool crosses(const QgsGeometry &geometry) const
Returns true if the geometry crosses another geometry.
double hausdorffDistance(const QgsGeometry &geom) const
Returns the Hausdorff distance between this geometry and geom.
QgsGeometry concaveHull(double targetPercent, bool allowHoles=false) const
Returns a possibly concave polygon that contains all the points in the geometry.
QgsGeometry convexHull() const
Returns the smallest convex polygon that contains all the points in the geometry.
QgsGeometry sharedPaths(const QgsGeometry &other) const
Find paths shared between the two given lineal geometries (this and other).
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
QgsGeometry intersection(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing the points shared by this geometry and other.
QgsGeometry symDifference(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing the points making up this geometry that do not make up other.
QgsGeometry minimalEnclosingCircle(QgsPointXY ¢er, double &radius, unsigned int segments=36) const
Returns the minimal enclosing circle for the geometry.
QgsGeometry mergeLines() const
Merges any connected lines in a LineString/MultiLineString geometry and converts them to single line ...
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
double distanceToVertex(int vertex) const
Returns the distance along this geometry from its first vertex to the specified vertex.
QgsAbstractGeometry::const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
QgsGeometry forcePolygonClockwise() const
Forces geometries to respect the exterior ring is clockwise, interior rings are counter-clockwise con...
static QgsGeometry createWedgeBuffer(const QgsPoint ¢er, double azimuth, double angularWidth, double outerRadius, double innerRadius=0)
Creates a wedge shaped buffer from a center point.
QgsGeometry extendLine(double startDistance, double endDistance) const
Extends a (multi)line geometry by extrapolating out the start or end of the line by a specified dista...
QgsGeometry triangularWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized triangular waves along the boundary of the geometry, with the specified wavelen...
QgsGeometry squareWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized square waves along the boundary of the geometry, with the specified wavelength ...
QgsGeometry simplify(double tolerance) const
Returns a simplified version of this geometry using a specified tolerance value.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Qgis::GeometryOperationResult rotate(double rotation, const QgsPointXY ¢er)
Rotate this geometry around the Z axis.
Qgis::GeometryOperationResult translate(double dx, double dy, double dz=0.0, double dm=0.0)
Translates this geometry by dx, dy, dz and dm.
double interpolateAngle(double distance) const
Returns the angle parallel to the linestring or polygon boundary at the specified distance along the ...
double angleAtVertex(int vertex) const
Returns the bisector angle for this geometry at the specified vertex.
QgsGeometry smooth(unsigned int iterations=1, double offset=0.25, double minimumDistance=-1.0, double maxAngle=180.0) const
Smooths a geometry by rounding off corners using the Chaikin algorithm.
QgsGeometry forcePolygonCounterClockwise() const
Forces geometries to respect the exterior ring is counter-clockwise, interior rings are clockwise con...
Q_INVOKABLE QString asWkt(int precision=17) const
Exports the geometry to WKT.
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
bool intersects(const QgsRectangle &rectangle) const
Returns true if this geometry exactly intersects with a rectangle.
QgsAbstractGeometry::vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
bool overlaps(const QgsGeometry &geometry) const
Returns true if the geometry overlaps another geometry.
QgsGeometry shortestLine(const QgsGeometry &other) const
Returns the shortest line joining this geometry to another geometry.
Does vector analysis using the geos library and handles import, export, exception handling*.
std::unique_ptr< QgsAbstractGeometry > maximumInscribedCircle(double tolerance, QString *errorMsg=nullptr) const
Returns the maximum inscribed circle.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
Represents a color stop within a QgsGradientColorRamp color ramp.
A representation of the interval between two datetime values.
bool isValid() const
Returns true if the interval is valid.
double days() const
Returns the interval duration in days.
double weeks() const
Returns the interval duration in weeks.
double months() const
Returns the interval duration in months (based on a 30 day month).
double seconds() const
Returns the interval duration in seconds.
double years() const
Returns the interval duration in years (based on an average year length)
double hours() const
Returns the interval duration in hours.
double minutes() const
Returns the interval duration in minutes.
Line string geometry type, with support for z-dimension and m-values.
bool lineLocatePointByM(double m, double &x, double &y, double &z, double &distanceFromStart, bool use3DDistance=true) const
Attempts to locate a point on the linestring by m value.
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
QString dataUrl() const
Returns the DataUrl of the layer used by QGIS Server in GetCapabilities request.
QString attributionUrl() const
Returns the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Base class for all map layer types.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QString source() const
Returns the source for the layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
QgsCoordinateReferenceSystem crs
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
QgsLayerMetadata metadata
QString publicSource(bool hidePassword=false) const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
virtual bool isEditable() const
Returns true if the layer can be edited.
double minimumScale() const
Returns the minimum map scale (i.e.
virtual Q_INVOKABLE QgsDataProvider * dataProvider()
Returns the layer's data provider, it may be nullptr.
double maximumScale() const
Returns the maximum map scale (i.e.
Implementation of GeometrySimplifier using the "MapToPixel" algorithm.
@ SimplifyGeometry
The geometries can be simplified using the current map2pixel context state.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Multi line string geometry collection.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
Multi point geometry collection.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
Custom exception class which is raised when an operation is not supported.
static QgsGeometry geometryFromGML(const QString &xmlString, const QgsOgcUtils::Context &context=QgsOgcUtils::Context())
Static method that creates geometry from GML.
A class to represent a 2D point.
bool isEmpty() const
Returns true if the geometry is empty.
Point geometry type, with support for z-dimension and m-values.
double inclination(const QgsPoint &other) const
Calculates Cartesian inclination between this point and other one (starting from zenith = 0 to nadir ...
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override
Checks validity of the geometry, and returns true if the geometry is valid.
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which corresponds to this point projected by a specified distance with specified ...
QgsRelationManager * relationManager
static QgsProject * instance()
Returns the QgsProject singleton instance.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
Quadrilateral geometry type.
static QgsQuadrilateral squareFromDiagonal(const QgsPoint &p1, const QgsPoint &p2)
Construct a QgsQuadrilateral as a square from a diagonal.
QgsPolygon * toPolygon(bool force2D=false) const
Returns the quadrilateral as a new polygon.
static QgsQuadrilateral rectangleFrom3Points(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &p3, ConstructionOption mode)
Construct a QgsQuadrilateral as a Rectangle from 3 points.
ConstructionOption
A quadrilateral can be constructed from 3 points where the second distance can be determined by the t...
@ Distance
Second distance is equal to the distance between 2nd and 3rd point.
@ Projected
Second distance is equal to the distance of the perpendicular projection of the 3rd point on the segm...
The Field class represents a Raster Attribute Table field, including its name, usage and type.
The RasterBandStats struct is a container for statistics about a single raster band.
double mean
The mean cell value for the band. NO_DATA values are excluded.
double stdDev
The standard deviation of the cell values.
double minimumValue
The minimum cell value in the raster band.
double sum
The sum of all cells in the band. NO_DATA values are excluded.
double maximumValue
The maximum cell value in the raster band.
double range
The range is the distance between min & max.
A rectangle specified with double values.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double width() const
Returns the width of the rectangle.
double xMaximum() const
Returns the x maximum value (right side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
QgsPointXY center() const
Returns the center point of the rectangle.
void grow(double delta)
Grows the rectangle in place by the specified amount.
double height() const
Returns the height of the rectangle.
Regular Polygon geometry type.
ConstructionOption
A regular polygon can be constructed inscribed in a circle or circumscribed about a circle.
@ CircumscribedCircle
Circumscribed about a circle (the radius is the distance from the center to the midpoints of the side...
@ InscribedCircle
Inscribed in a circle (the radius is the distance between the center and vertices)
QgsPolygon * toPolygon() const
Returns as a polygon.
QList< QgsRelation > relationsByName(const QString &name) const
Returns a list of relations with matching names.
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id.
Represents a relationship between two vector layers.
QgsVectorLayer * referencedLayer
QgsVectorLayer * referencingLayer
QString getRelatedFeaturesFilter(const QgsFeature &feature) const
Returns a filter expression which returns all the features on the referencing (child) layer which hav...
A spatial index for QgsFeature objects.
@ FlagStoreFeatureGeometries
Indicates that the spatial index should also store feature geometries. This requires more memory,...
QList< QgsFeatureId > nearestNeighbor(const QgsPointXY &point, int neighbors=1, double maxDistance=0) const
Returns nearest neighbors to a point.
QList< QgsFeatureId > intersects(const QgsRectangle &rectangle) const
Returns a list of features with a bounding box which intersects the specified rectangle.
static QString quotedIdentifier(const QString &identifier)
Returns a properly quoted version of identifier.
static QString quotedValue(const QVariant &value)
Returns a properly quoted and escaped version of value for use in SQL strings.
c++ helper class for defining QgsExpression functions.
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
void setIsStaticFunction(const std::function< bool(const QgsExpressionNodeFunction *, QgsExpression *, const QgsExpressionContext *) > &isStatic)
Set a function that will be called in the prepare step to determine if the function is static or not.
QStringList aliases() const override
Returns a list of possible aliases for the function.
void setPrepareFunction(const std::function< bool(const QgsExpressionNodeFunction *, QgsExpression *, const QgsExpressionContext *)> &prepareFunc)
Set a function that will be called in the prepare step to determine if the function is static or not.
void setUsesGeometryFunction(const std::function< bool(const QgsExpressionNodeFunction *node)> &usesGeometry)
Set a function that will be called when determining if the function requires feature geometry or not.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
void setIsStatic(bool isStatic)
Tag this function as either static or not static.
QgsStaticExpressionFunction(const QString &fnname, int params, FcnEval fcn, const QString &group, const QString &helpText=QString(), bool usesGeometry=false, const QSet< QString > &referencedColumns=QSet< QString >(), bool lazyEval=false, const QStringList &aliases=QStringList(), bool handlesNull=false)
Static function for evaluation against a QgsExpressionContext, using an unnamed list of parameter val...
QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const override
Returns a set of field names which are required for this function.
bool usesGeometry(const QgsExpressionNodeFunction *node) const override
Does this function use a geometry object.
Utility functions for working with strings.
static int hammingDistance(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the Hamming distance between two strings.
static QString soundex(const QString &string)
Returns the Soundex representation of a string.
static int levenshteinDistance(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the Levenshtein edit distance between two strings.
static QString longestCommonSubstring(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the longest common substring between two strings.
static QString wordWrap(const QString &string, int length, bool useMaxLineLength=true, const QString &customDelimiter=QString())
Automatically wraps a string by inserting new line characters at appropriate locations in the string.
const QgsColorRamp * colorRampRef(const QString &name) const
Returns a const pointer to a symbol (doesn't create new instance)
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Contains utility functions for working with symbols and symbol layers.
static QColor decodeColor(const QString &str)
static QString encodeColor(const QColor &color)
static bool runOnMainThread(const Func &func, QgsFeedback *feedback=nullptr)
Guarantees that func is executed on the main thread.
This class allows including a set of layers in a database-side transaction, provided the layer data p...
virtual bool executeSql(const QString &sql, QString &error, bool isDirty=false, const QString &name=QString())=0
Execute the sql string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
virtual QgsTransaction * transaction() const
Returns the transaction this data provider is included in, if any.
static bool validateAttribute(const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors, QgsFieldConstraints::ConstraintStrength strength=QgsFieldConstraints::ConstraintStrengthNotSet, QgsFieldConstraints::ConstraintOrigin origin=QgsFieldConstraints::ConstraintOriginNotSet)
Tests a feature attribute value to check whether it passes all constraints which are present on the c...
Represents a vector layer which manages a vector based data sets.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QVariant aggregate(Qgis::Aggregate aggregate, const QString &fieldOrExpression, const QgsAggregateCalculator::AggregateParameters ¶meters=QgsAggregateCalculator::AggregateParameters(), QgsExpressionContext *context=nullptr, bool *ok=nullptr, QgsFeatureIds *fids=nullptr, QgsFeedback *feedback=nullptr, QString *error=nullptr) const
Calculates an aggregated value from the layer's features.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QString displayExpression
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
QgsEditorWidgetSetup editorWidgetSetup(int index) const
Returns the editor widget setup for the field at the specified index.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
Q_INVOKABLE QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.
Handles the with_variable(name, value, node) expression function.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
QgsWithVariableExpressionFunction()
QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Evaluates the function, first evaluating all required arguments before passing them to the function's...
QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Returns result of evaluating the function.
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
static QString geometryDisplayString(Qgis::GeometryType type)
Returns a display string for a geometry type.
static bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
Unique pointer for sqlite3 databases, which automatically closes the database when the pointer goes o...
sqlite3_statement_unique_ptr prepare(const QString &sql, int &resultCode) const
Prepares a sql statement, returning the result.
QString errorMessage() const
Returns the most recent error message encountered by the database.
int open_v2(const QString &path, int flags, const char *zVfs)
Opens the database at the specified file path.
int exec(const QString &sql, QString &errorMessage) const
Executes the sql command in the database.
Unique pointer for sqlite3 prepared statements, which automatically finalizes the statement when the ...
int step()
Steps to the next record in the statement, returning the sqlite3 result code.
qlonglong columnAsInt64(int column) const
Gets column value from the current statement row as a long long integer (64 bits).
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
CORE_EXPORT QString build(const QVariantMap &map)
Build a hstore-formatted string from a QVariantMap.
CORE_EXPORT QVariantMap parse(const QString &string)
Returns a QVariantMap object containing the key and values from a hstore-formatted string.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QVector< QgsRingSequence > QgsCoordinateSequence
QVector< QgsPointSequence > QgsRingSequence
QVector< QgsPoint > QgsPointSequence
QList< QgsGradientStop > QgsGradientStopsList
List of gradient stops.
Q_DECLARE_METATYPE(QgsDatabaseQueryLogEntry)
Q_GLOBAL_STATIC(QReadWriteLock, sDefinitionCacheLock)
QList< QgsExpressionFunction * > ExpressionFunctionList
QVariant fcnRampColor(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
#define ENSURE_GEOM_TYPE(f, g, geomtype)
QVariant fcnRampColorObject(const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction *)
bool(QgsGeometry::* RelationFunction)(const QgsGeometry &geometry) const
#define ENSURE_NO_EVAL_ERROR
#define FEAT_FROM_CONTEXT(c, f)
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
QVector< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
QLineF segment(int index, QRectF rect, double radius)
A bundle of parameters controlling aggregate calculation.
QString filter
Optional filter for calculating aggregate over a subset of features, or an empty string to use all fe...
QString delimiter
Delimiter to use for joining values with the StringConcatenate aggregate.
QgsFeatureRequest::OrderBy orderBy
Optional order by clauses.
Single variable definition for use within a QgsExpressionContextScope.
The Context struct stores the current layer and coordinate transform context.
const QgsMapLayer * layer
QgsCoordinateTransformContext transformContext
Utility class for identifying a unique vertex within a geometry.