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 const QVariant value = values.at( 0 );
1250 if ( QgsExpressionUtils::isNull( value.isValid() ) )
1252 return QVariant(
false );
1254 else if ( value.userType() == QMetaType::QString )
1257 return QVariant( !value.toString().isEmpty() );
1259 else if ( QgsExpressionUtils::isList( value ) )
1261 return !value.toList().isEmpty();
1263 return QVariant( value.toBool() );
1267 return QVariant( QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) );
1271 return QVariant( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) );
1275 return QVariant( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ) );
1280 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1281 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1282 if ( format.isEmpty() && !language.isEmpty() )
1284 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to DateTime when the language is specified" ) );
1285 return QVariant( QDateTime() );
1288 if ( format.isEmpty() && language.isEmpty() )
1289 return QVariant( QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent ) );
1291 QString datetimestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1292 QLocale locale = QLocale();
1293 if ( !language.isEmpty() )
1295 locale = QLocale( language );
1298 QDateTime datetime = locale.toDateTime( datetimestring, format );
1299 if ( !datetime.isValid() )
1301 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to DateTime" ).arg( datetimestring ) );
1302 datetime = QDateTime();
1304 return QVariant( datetime );
1309 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1310 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1311 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1313 const QDate date( year, month, day );
1314 if ( !date.isValid() )
1316 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1319 return QVariant( date );
1324 const int hours = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1325 const int minutes = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1326 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1328 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1329 if ( !time.isValid() )
1331 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1334 return QVariant( time );
1339 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1340 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1341 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1342 const int hours = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
1343 const int minutes = QgsExpressionUtils::getIntValue( values.at( 4 ), parent );
1344 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1346 const QDate date( year, month, day );
1347 if ( !date.isValid() )
1349 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1352 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1353 if ( !time.isValid() )
1355 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1358 return QVariant( QDateTime( date, time ) );
1363 const double years = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1364 const double months = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1365 const double weeks = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1366 const double days = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
1367 const double hours = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
1368 const double minutes = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1369 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
1371 return QVariant::fromValue(
QgsInterval( years, months, weeks, days, hours, minutes, seconds ) );
1376 for (
const QVariant &value : values )
1387 const QVariant val1 = values.at( 0 );
1388 const QVariant val2 = values.at( 1 );
1398 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1399 return QVariant( str.toLower() );
1403 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1404 return QVariant( str.toUpper() );
1408 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1409 QStringList elems = str.split(
' ' );
1410 for (
int i = 0; i < elems.size(); i++ )
1412 if ( elems[i].size() > 1 )
1413 elems[i] = elems[i].at( 0 ).toUpper() + elems[i].mid( 1 ).toLower();
1415 return QVariant( elems.join( QLatin1Char(
' ' ) ) );
1420 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1421 return QVariant( str.trimmed() );
1426 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1428 const QString characters = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1430 const QRegularExpression re( QStringLiteral(
"^([%1]*)" ).arg( QRegularExpression::escape( characters ) ) );
1431 str.replace( re, QString() );
1432 return QVariant( str );
1437 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1439 const QString characters = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1441 const QRegularExpression re( QStringLiteral(
"([%1]*)$" ).arg( QRegularExpression::escape( characters ) ) );
1442 str.replace( re, QString() );
1443 return QVariant( str );
1448 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1449 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1455 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1456 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1462 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1463 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1465 return ( dist < 0 ? QVariant() : QVariant(
QgsStringUtils::hammingDistance( string1, string2, true ) ) );
1470 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1476 QChar character = QChar( QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent ) );
1477 return QVariant( QString( character ) );
1482 QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1484 if ( value.isEmpty() )
1489 int res = value.at( 0 ).unicode();
1490 return QVariant( res );
1495 if ( values.length() == 2 || values.length() == 3 )
1497 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1498 qlonglong wrap = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1500 QString customdelimiter = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1513 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent,
true );
1517 return QVariant( geom.
length() );
1523 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1524 return QVariant( str.length() );
1529 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
1534 double totalLength = 0;
1537 if (
const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( *it ) )
1539 totalLength += line->length3D();
1543 std::unique_ptr< QgsLineString > segmentized( qgsgeometry_cast< const QgsCurve * >( *it )->curveToLine() );
1544 totalLength += segmentized->length3D();
1553 if ( values.count() == 2 && values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
1555 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1556 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
1557 QVector< QPair< QString, QString > > mapItems;
1559 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
1561 mapItems.append( qMakePair( it.key(), it.value().toString() ) );
1565 std::sort( mapItems.begin(),
1567 [](
const QPair< QString, QString > &pair1,
1568 const QPair< QString, QString > &pair2 )
1570 return ( pair1.first.length() > pair2.first.length() );
1573 for (
auto it = mapItems.constBegin(); it != mapItems.constEnd(); ++it )
1575 str = str.replace( it->first, it->second );
1578 return QVariant( str );
1580 else if ( values.count() == 3 )
1582 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1583 QVariantList before;
1585 bool isSingleReplacement =
false;
1587 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).userType() != QMetaType::Type::QStringList )
1589 before = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1593 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
1596 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
1598 after = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1599 isSingleReplacement =
true;
1603 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
1606 if ( !isSingleReplacement && before.length() != after.length() )
1608 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
1612 for (
int i = 0; i < before.length(); i++ )
1614 str = str.replace( before.at( i ).toString(), after.at( isSingleReplacement ? 0 : i ).toString() );
1617 return QVariant( str );
1621 parent->
setEvalErrorString( QObject::tr(
"Function replace requires 2 or 3 arguments" ) );
1628 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1629 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1630 QString after = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1632 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1633 if ( !re.isValid() )
1635 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1638 return QVariant( str.replace( re, after ) );
1643 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1644 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1646 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1647 if ( !re.isValid() )
1649 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1652 return QVariant( ( str.indexOf( re ) + 1 ) );
1657 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1658 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1659 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1661 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1662 if ( !re.isValid() )
1664 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1668 QRegularExpressionMatch matches = re.match( str );
1669 if ( matches.hasMatch() )
1672 QStringList list = matches.capturedTexts();
1675 for ( QStringList::const_iterator it = ++list.constBegin(); it != list.constEnd(); ++it )
1677 array += ( !( *it ).isEmpty() ) ? *it : empty;
1680 return QVariant( array );
1690 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1691 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1693 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1694 if ( !re.isValid() )
1696 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1701 QRegularExpressionMatch match = re.match( str );
1702 if ( match.hasMatch() )
1705 if ( match.lastCapturedIndex() > 0 )
1708 return QVariant( match.captured( 1 ) );
1713 return QVariant( match.captured( 0 ) );
1718 return QVariant(
"" );
1724 QString uuid = QUuid::createUuid().toString();
1725 if ( values.at( 0 ).toString().compare( QStringLiteral(
"WithoutBraces" ), Qt::CaseInsensitive ) == 0 )
1726 uuid = QUuid::createUuid().toString( QUuid::StringFormat::WithoutBraces );
1727 else if ( values.at( 0 ).toString().compare( QStringLiteral(
"Id128" ), Qt::CaseInsensitive ) == 0 )
1728 uuid = QUuid::createUuid().toString( QUuid::StringFormat::Id128 );
1734 if ( !values.at( 0 ).isValid() || !values.at( 1 ).isValid() )
1737 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1738 int from = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1741 if ( values.at( 2 ).isValid() )
1742 len = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
1748 from = str.size() + from;
1754 else if ( from > 0 )
1762 len = str.size() + len - from;
1769 return QVariant( str.mid( from, len ) );
1774 return QVariant( f.
id() );
1779 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1780 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
1781 bool foundLayer =
false;
1782 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, geom](
QgsMapLayer * mapLayer )
1784 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer * >( mapLayer );
1785 if ( !layer || !layer->dataProvider() )
1787 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1791 if ( bandNb < 1 || bandNb > layer->bandCount() )
1793 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster band number." ) );
1799 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid point geometry." ) );
1807 if ( multiPoint.count() == 1 )
1809 point = multiPoint[0];
1818 double value = layer->dataProvider()->sample( point, bandNb );
1819 return std::isnan( value ) ? QVariant() : value;
1825 parent->
setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1836 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1837 const double value = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1839 bool foundLayer =
false;
1840 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, value](
QgsMapLayer * mapLayer )-> QVariant
1842 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer *>( mapLayer );
1843 if ( !layer || !layer->dataProvider() )
1845 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1849 if ( bandNb < 1 || bandNb > layer->bandCount() )
1851 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster band number." ) );
1855 if ( std::isnan( value ) )
1857 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster value." ) );
1861 if ( ! layer->dataProvider()->attributeTable( bandNb ) )
1866 const QVariantList data = layer->dataProvider()->attributeTable( bandNb )->row( value );
1867 if ( data.isEmpty() )
1873 const QList<QgsRasterAttributeTable::Field> fields { layer->dataProvider()->attributeTable( bandNb )->fields() };
1874 for (
int idx = 0; idx < static_cast<int>( fields.count( ) ) && idx < static_cast<int>( data.count() ); ++idx )
1877 if ( field.isColor() || field.isRamp() )
1881 result.insert( fields.at( idx ).name, data.at( idx ) );
1889 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1910 if ( values.size() == 1 )
1912 attr = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1915 else if ( values.size() == 2 )
1917 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
1918 attr = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1922 parent->
setEvalErrorString( QObject::tr(
"Function `attribute` requires one or two parameters. %n given.",
nullptr, values.length() ) );
1931 QString table { R
"html(
1934 <tr><th>%1</th></tr>
1937 <tr><td>%2</td></tr>
1941 if ( values.size() == 1 )
1943 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1947 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_table` requires one parameter. %n given.",
nullptr, values.length() ) );
1951 if ( dict.isEmpty() )
1956 QStringList headers;
1959 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
1961 headers.push_back( it.key().toHtmlEscaped() );
1962 cells.push_back( it.value().toString( ).toHtmlEscaped() );
1965 return table.arg( headers.join( QLatin1String(
"</th><th>" ) ), cells.join( QLatin1String(
"</td><td>" ) ) );
1970 QString table { R
"html(
1975 if ( values.size() == 1 )
1977 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1981 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_dl` requires one parameter. %n given.",
nullptr, values.length() ) );
1985 if ( dict.isEmpty() )
1992 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
1994 rows.append( QStringLiteral(
"<dt>%1</dt><dd>%2</dd>" ).arg( it.key().toHtmlEscaped(), it.value().toString().toHtmlEscaped() ) );
1997 return table.arg( rows );
2005 layer = context->
variable( QStringLiteral(
"layer" ) );
2010 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
2012 layer = node->
eval( parent, context );
2023 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2027 const QString strength = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).toLower();
2028 if ( strength == QLatin1String(
"hard" ) )
2032 else if ( strength == QLatin1String(
"soft" ) )
2037 bool foundLayer =
false;
2038 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
2040 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2043 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2049 for (
int i = 0; i < fields.
size(); i++ )
2064 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2076 layer = context->
variable( QStringLiteral(
"layer" ) );
2081 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
2083 layer = node->
eval( parent, context );
2094 feature = QgsExpressionUtils::getFeature( values.at( 2 ), parent );
2098 const QString strength = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).toLower();
2099 if ( strength == QLatin1String(
"hard" ) )
2103 else if ( strength == QLatin1String(
"soft" ) )
2108 const QString attributeName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2110 bool foundLayer =
false;
2111 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, attributeName, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
2113 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2120 if ( fieldIndex == -1 )
2122 parent->
setEvalErrorString( QObject::tr(
"The attribute name did not match any field for the given feature" ) );
2133 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2149 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2154 for (
int i = 0; i < fields.
count(); ++i )
2168 if ( values.isEmpty() )
2171 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2173 else if ( values.size() == 1 )
2175 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2176 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2178 else if ( values.size() == 2 )
2180 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2181 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2185 parent->
setEvalErrorString( QObject::tr(
"Function `represent_attributes` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2192 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: layer could not be resolved." ) );
2198 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: feature could not be resolved." ) );
2204 for (
int fieldIndex = 0; fieldIndex < fields.
count(); ++fieldIndex )
2206 const QString fieldName { fields.
at( fieldIndex ).
name() };
2207 const QVariant attributeVal = feature.
attribute( fieldIndex );
2208 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer->
id(), fieldName, attributeVal.toString() );
2211 result.insert( fieldName, context->
cachedValue( cacheValueKey ) );
2220 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer->
id(), fieldName );
2232 QString value( fieldFormatter->
representValue( layer, fieldIndex, setup.
config(), cache, attributeVal ) );
2234 result.insert( fields.
at( fieldIndex ).
name(), value );
2250 bool evaluate =
true;
2254 if ( values.isEmpty() )
2257 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2259 else if ( values.size() == 1 )
2261 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2262 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2264 else if ( values.size() == 2 )
2266 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2267 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2269 else if ( values.size() == 3 )
2271 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2272 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2273 evaluate = values.value( 2 ).toBool();
2279 parent->
setEvalErrorString( QObject::tr(
"Function `maptip` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2283 parent->
setEvalErrorString( QObject::tr(
"Function `display` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2315 subContext.setFeature( feature );
2324 exp.prepare( &subContext );
2325 return exp.evaluate( &subContext ).toString();
2331 return fcnCoreFeatureMaptipDisplay( values, context, parent,
false );
2336 return fcnCoreFeatureMaptipDisplay( values, context, parent,
true );
2343 if ( values.isEmpty() )
2346 layer = context->
variable( QStringLiteral(
"layer" ) );
2348 else if ( values.size() == 1 )
2350 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2351 layer = context->
variable( QStringLiteral(
"layer" ) );
2353 else if ( values.size() == 2 )
2355 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2356 layer = values.at( 0 );
2360 parent->
setEvalErrorString( QObject::tr(
"Function `is_selected` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2364 bool foundLayer =
false;
2365 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [feature](
QgsMapLayer * mapLayer ) -> QVariant
2367 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2368 if ( !layer || !feature.
isValid() )
2385 if ( values.isEmpty() )
2386 layer = context->
variable( QStringLiteral(
"layer" ) );
2387 else if ( values.count() == 1 )
2388 layer = values.at( 0 );
2391 parent->
setEvalErrorString( QObject::tr(
"Function `num_selected` requires no more than one parameter. %n given.",
nullptr, values.length() ) );
2395 bool foundLayer =
false;
2396 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [](
QgsMapLayer * mapLayer ) -> QVariant
2398 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2414 static QMap<QString, qlonglong> counterCache;
2415 QVariant functionResult;
2417 auto fetchAndIncrementFunc = [ values, parent, &functionResult ](
QgsMapLayer * mapLayer,
const QString & databaseArgument )
2421 const QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( mapLayer );
2426 database = decodedUri.value( QStringLiteral(
"path" ) ).toString();
2427 if ( database.isEmpty() )
2429 parent->
setEvalErrorString( QObject::tr(
"Could not extract file path from layer `%1`." ).arg( layer->
name() ) );
2434 database = databaseArgument;
2437 const QString table = values.at( 1 ).toString();
2438 const QString idColumn = values.at( 2 ).toString();
2439 const QString filterAttribute = values.at( 3 ).toString();
2440 const QVariant filterValue = values.at( 4 ).toString();
2441 const QVariantMap defaultValues = values.at( 5 ).toMap();
2447 if ( sqliteDb.
open_v2( database, SQLITE_OPEN_READWRITE,
nullptr ) != SQLITE_OK )
2450 functionResult = QVariant();
2454 QString errorMessage;
2455 QString currentValSql;
2457 qlonglong nextId = 0;
2458 bool cachedMode =
false;
2459 bool valueRetrieved =
false;
2461 QString cacheString = QStringLiteral(
"%1:%2:%3:%4:%5" ).arg( database, table, idColumn, filterAttribute, filterValue.toString() );
2468 auto cachedCounter = counterCache.find( cacheString );
2470 if ( cachedCounter != counterCache.end() )
2472 qlonglong &cachedValue = cachedCounter.value();
2473 nextId = cachedValue;
2475 cachedValue = nextId;
2476 valueRetrieved =
true;
2481 if ( !cachedMode || !valueRetrieved )
2483 int result = SQLITE_ERROR;
2486 if ( !filterAttribute.isNull() )
2491 sqliteStatement = sqliteDb.
prepare( currentValSql, result );
2493 if ( result == SQLITE_OK )
2496 if ( sqliteStatement.
step() == SQLITE_ROW )
2502 if ( cachedMode && result == SQLITE_OK )
2504 counterCache.insert( cacheString, nextId );
2508 counterCache.remove( cacheString );
2511 valueRetrieved =
true;
2515 if ( valueRetrieved )
2524 if ( !filterAttribute.isNull() )
2530 for ( QVariantMap::const_iterator iter = defaultValues.constBegin(); iter != defaultValues.constEnd(); ++iter )
2533 vals << iter.value().toString();
2536 upsertSql += QLatin1String(
" (" ) + cols.join(
',' ) +
')';
2537 upsertSql += QLatin1String(
" VALUES " );
2538 upsertSql +=
'(' + vals.join(
',' ) +
')';
2540 int result = SQLITE_ERROR;
2544 if ( transaction->
executeSql( upsertSql, errorMessage ) )
2551 result = sqliteDb.
exec( upsertSql, errorMessage );
2553 if ( result == SQLITE_OK )
2555 functionResult = QVariant( nextId );
2560 parent->
setEvalErrorString( QStringLiteral(
"Could not increment value: SQLite error: \"%1\" (%2)." ).arg( errorMessage, QString::number( result ) ) );
2561 functionResult = QVariant();
2566 functionResult = QVariant();
2569 bool foundLayer =
false;
2570 QgsExpressionUtils::executeLambdaForMapLayer( values.at( 0 ), context, parent, [&fetchAndIncrementFunc](
QgsMapLayer * layer )
2572 fetchAndIncrementFunc( layer, QString() );
2576 const QString databasePath = values.at( 0 ).toString();
2579 fetchAndIncrementFunc(
nullptr, databasePath );
2583 return functionResult;
2596 QString definition = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2601 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to cordinate reference system" ).arg( definition ) );
2604 return QVariant::fromValue(
crs );
2610 for (
const QVariant &value : values )
2613 concat += QgsExpressionUtils::getStringValue( value, parent );
2620 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2621 return string.indexOf( QgsExpressionUtils::getStringValue( values.at( 1 ), parent ) ) + 1;
2626 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2627 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2628 return string.right( pos );
2633 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2634 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2635 return string.left( pos );
2640 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2641 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2642 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2643 return string.leftJustified( length, fill.at( 0 ),
true );
2648 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2649 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2650 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2651 return string.rightJustified( length, fill.at( 0 ),
true );
2656 if ( values.size() < 1 )
2658 parent->
setEvalErrorString( QObject::tr(
"Function format requires at least 1 argument" ) );
2662 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2663 for (
int n = 1; n < values.length(); n++ )
2665 string =
string.arg( QgsExpressionUtils::getStringValue( values.at( n ), parent ) );
2673 return QVariant( QDateTime::currentDateTime() );
2678 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2679 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2680 if ( format.isEmpty() && !language.isEmpty() )
2682 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Date when the language is specified" ) );
2683 return QVariant( QDate() );
2686 if ( format.isEmpty() && language.isEmpty() )
2687 return QVariant( QgsExpressionUtils::getDateValue( values.at( 0 ), parent ) );
2689 QString datestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2690 QLocale locale = QLocale();
2691 if ( !language.isEmpty() )
2693 locale = QLocale( language );
2696 QDate date = locale.toDate( datestring, format );
2697 if ( !date.isValid() )
2699 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Date" ).arg( datestring ) );
2702 return QVariant( date );
2707 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2708 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2709 if ( format.isEmpty() && !language.isEmpty() )
2711 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Time when the language is specified" ) );
2712 return QVariant( QTime() );
2715 if ( format.isEmpty() && language.isEmpty() )
2716 return QVariant( QgsExpressionUtils::getTimeValue( values.at( 0 ), parent ) );
2718 QString timestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2719 QLocale locale = QLocale();
2720 if ( !language.isEmpty() )
2722 locale = QLocale( language );
2725 QTime time = locale.toTime( timestring, format );
2726 if ( !time.isValid() )
2728 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Time" ).arg( timestring ) );
2731 return QVariant( time );
2736 return QVariant::fromValue( QgsExpressionUtils::getInterval( values.at( 0 ), parent ) );
2745 double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
2746 QString axis = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2747 int precision = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
2749 QString formatString;
2750 if ( values.count() > 3 )
2751 formatString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
2754 if ( formatString.compare( QLatin1String(
"suffix" ), Qt::CaseInsensitive ) == 0 )
2758 else if ( formatString.compare( QLatin1String(
"aligned" ), Qt::CaseInsensitive ) == 0 )
2762 else if ( ! formatString.isEmpty() )
2764 parent->
setEvalErrorString( QObject::tr(
"Invalid formatting parameter: '%1'. It must be empty, or 'suffix' or 'aligned'." ).arg( formatString ) );
2768 if ( axis.compare( QLatin1String(
"x" ), Qt::CaseInsensitive ) == 0 )
2772 else if ( axis.compare( QLatin1String(
"y" ), Qt::CaseInsensitive ) == 0 )
2778 parent->
setEvalErrorString( QObject::tr(
"Invalid axis name: '%1'. It must be either 'x' or 'y'." ).arg( axis ) );
2786 return floatToDegreeFormat( format, values, context, parent, node );
2793 value = QgsCoordinateUtils::dmsToDecimal( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), &ok );
2795 return ok ? QVariant( value ) : QVariant();
2801 return floatToDegreeFormat( format, values, context, parent, node );
2806 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2807 QDateTime d2 = QgsExpressionUtils::getDateTimeValue( values.at( 1 ), parent );
2808 qint64 seconds = d2.secsTo( d1 );
2809 return QVariant::fromValue(
QgsInterval( seconds ) );
2814 if ( !values.at( 0 ).canConvert<QDate>() )
2817 QDate date = QgsExpressionUtils::getDateValue( values.at( 0 ), parent );
2818 if ( !date.isValid() )
2823 return date.dayOfWeek() % 7;
2828 QVariant value = values.at( 0 );
2829 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2832 return QVariant( inter.
days() );
2836 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2837 return QVariant( d1.date().day() );
2843 QVariant value = values.at( 0 );
2844 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2847 return QVariant( inter.
years() );
2851 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2852 return QVariant( d1.date().year() );
2858 QVariant value = values.at( 0 );
2859 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2862 return QVariant( inter.
months() );
2866 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2867 return QVariant( d1.date().month() );
2873 QVariant value = values.at( 0 );
2874 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2877 return QVariant( inter.
weeks() );
2881 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2882 return QVariant( d1.date().weekNumber() );
2888 QVariant value = values.at( 0 );
2889 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2892 return QVariant( inter.
hours() );
2896 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2897 return QVariant( t1.hour() );
2903 QVariant value = values.at( 0 );
2904 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2907 return QVariant( inter.
minutes() );
2911 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2912 return QVariant( t1.minute() );
2918 QVariant value = values.at( 0 );
2919 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2922 return QVariant( inter.
seconds() );
2926 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2927 return QVariant( t1.second() );
2933 QDateTime dt = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2936 return QVariant( dt.toMSecsSinceEpoch() );
2946 long long millisecs_since_epoch = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
2948 return QVariant( QDateTime::fromMSecsSinceEpoch( millisecs_since_epoch ) );
2953 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2956 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif" ) ) );
2959 QString tag = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2965 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2968 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif_geotag" ) ) );
2975#define ENSURE_GEOM_TYPE(f, g, geomtype) \
2976 if ( !(f).hasGeometry() ) \
2977 return QVariant(); \
2978 QgsGeometry g = (f).geometry(); \
2979 if ( (g).type() != (geomtype) ) \
2986 if ( g.isMultipart() )
2988 return g.asMultiPoint().at( 0 ).x();
2992 return g.asPoint().x();
3000 if ( g.isMultipart() )
3002 return g.asMultiPoint().at( 0 ).y();
3006 return g.asPoint().y();
3020 if ( g.isEmpty() || !abGeom->
is3D() )
3025 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( g.constGet() );
3031 if (
const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( g.constGet() ) )
3033 if ( collection->numGeometries() > 0 )
3035 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3046 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3052 return QVariant( isValid );
3057 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3061 const QString methodString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).trimmed();
3062#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
3067 if ( methodString.compare( QLatin1String(
"linework" ), Qt::CaseInsensitive ) == 0 )
3069 else if ( methodString.compare( QLatin1String(
"structure" ), Qt::CaseInsensitive ) == 0 )
3072 const bool keepCollapsed = values.value( 2 ).toBool();
3077 valid = geom.
makeValid( method, keepCollapsed );
3081 parent->
setEvalErrorString( QObject::tr(
"The make_valid parameters require a newer GEOS library version" ) );
3085 return QVariant::fromValue( valid );
3090 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3096 for (
int i = 0; i < multiGeom.size(); ++i )
3098 array += QVariant::fromValue( multiGeom.at( i ) );
3106 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3118 QVariant result( centroid.asPoint().
x() );
3124 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3136 QVariant result( centroid.asPoint().
y() );
3142 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3152 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3160 if ( collection->numGeometries() == 1 )
3162 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3173 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3183 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3191 if ( collection->numGeometries() == 1 )
3193 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3204 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3209 int idx = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
3236 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3253 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3270 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3275 bool ignoreClosing =
false;
3276 if ( values.length() > 1 )
3278 ignoreClosing = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3288 bool skipLast =
false;
3289 if ( ignoreClosing && ring.count() > 2 && ring.first() == ring.last() )
3294 for (
int i = 0; i < ( skipLast ? ring.count() - 1 : ring.count() ); ++ i )
3306 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3317 for (
int i = 0; i < line->numPoints() - 1; ++i )
3321 << line->pointN( i )
3322 << line->pointN( i + 1 ) );
3333 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3343 if ( collection->numGeometries() == 1 )
3345 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->geometryN( 0 ) );
3350 if ( !curvePolygon )
3354 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3360 QVariant result = curve ? QVariant::fromValue(
QgsGeometry( curve ) ) : QVariant();
3366 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3376 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3382 QVariant result = part ? QVariant::fromValue(
QgsGeometry( part ) ) : QVariant();
3388 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3397 return QVariant::fromValue(
QgsGeometry( boundary ) );
3402 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3411 return QVariant::fromValue( merged );
3416 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3420 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3425 if ( sharedPaths.
isNull() )
3428 return QVariant::fromValue( sharedPaths );
3434 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3439 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3442 if ( simplified.
isNull() )
3450 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3455 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3460 if ( simplified.
isNull() )
3468 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3473 int iterations = std::min( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), 10 );
3474 double offset = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0.0, 0.5 );
3475 double minLength = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3476 double maxAngle = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ), 0.0, 180.0 );
3478 QgsGeometry smoothed = geom.
smooth(
static_cast<unsigned int>( iterations ), offset, minLength, maxAngle );
3487 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3492 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3493 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3494 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3505 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3510 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3511 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3512 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3513 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3514 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3517 minAmplitude, maxAmplitude, seed );
3526 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3531 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3532 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3533 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3544 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3549 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3550 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3551 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3552 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3553 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3556 minAmplitude, maxAmplitude, seed );
3565 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3570 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3571 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3572 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3583 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3588 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3589 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3590 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3591 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3592 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3595 minAmplitude, maxAmplitude, seed );
3604 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3609 const QVariantList pattern = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
3610 QVector< double > dashPattern;
3611 dashPattern.reserve( pattern.size() );
3612 for (
const QVariant &value : std::as_const( pattern ) )
3615 double v = value.toDouble( &ok );
3622 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must be an array of numbers" ) );
3627 if ( dashPattern.size() % 2 != 0 )
3629 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must contain an even number of elements" ) );
3633 const QString startRuleString = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).trimmed();
3635 if ( startRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3637 else if ( startRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3639 else if ( startRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3641 else if ( startRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3643 else if ( startRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3647 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( startRuleString ) );
3651 const QString endRuleString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
3653 if ( endRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3655 else if ( endRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3657 else if ( endRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3659 else if ( endRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3661 else if ( endRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3665 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( endRuleString ) );
3669 const QString adjustString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
3671 if ( adjustString.compare( QLatin1String(
"both" ), Qt::CaseInsensitive ) == 0 )
3673 else if ( adjustString.compare( QLatin1String(
"dash" ), Qt::CaseInsensitive ) == 0 )
3675 else if ( adjustString.compare( QLatin1String(
"gap" ), Qt::CaseInsensitive ) == 0 )
3679 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern size adjustment" ).arg( adjustString ) );
3683 const double patternOffset = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
3694 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3699 const long long count = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3701 if ( densified.
isNull() )
3709 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3714 const double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3716 if ( densified.
isNull() )
3725 if ( values.size() == 1 && QgsExpressionUtils::isList( values.at( 0 ) ) )
3727 list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
3734 QVector< QgsGeometry > parts;
3735 parts.reserve( list.size() );
3736 for (
const QVariant &value : std::as_const( list ) )
3738 QgsGeometry part = QgsExpressionUtils::getGeometry( value, parent );
3749 if ( values.count() < 2 || values.count() > 4 )
3751 parent->
setEvalErrorString( QObject::tr(
"Function make_point requires 2-4 arguments" ) );
3755 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3756 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3757 double z = values.count() >= 3 ? QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) : 0.0;
3758 double m = values.count() >= 4 ? QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) : 0.0;
3759 switch ( values.count() )
3773 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3774 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3775 double m = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3781 if ( values.empty() )
3786 QVector<QgsPoint> points;
3787 points.reserve( values.count() );
3789 auto addPoint = [&points](
const QgsGeometry & geom )
3797 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3804 for (
const QVariant &value : values )
3806 if ( value.userType() == QMetaType::Type::QVariantList )
3808 const QVariantList list = value.toList();
3809 for (
const QVariant &v : list )
3811 addPoint( QgsExpressionUtils::getGeometry( v, parent ) );
3816 addPoint( QgsExpressionUtils::getGeometry( value, parent ) );
3820 if ( points.count() < 2 )
3828 if ( values.count() < 1 )
3830 parent->
setEvalErrorString( QObject::tr(
"Function make_polygon requires an argument" ) );
3834 QgsGeometry outerRing = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3842 auto polygon = std::make_unique< QgsPolygon >();
3844 const QgsCurve *exteriorRing = qgsgeometry_cast< const QgsCurve * >( outerRing.
constGet() );
3851 exteriorRing = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
3856 if ( !exteriorRing )
3859 polygon->setExteriorRing( exteriorRing->
segmentize() );
3862 for (
int i = 1; i < values.count(); ++i )
3864 QgsGeometry ringGeom = QgsExpressionUtils::getGeometry( values.at( i ), parent );
3871 const QgsCurve *ring = qgsgeometry_cast< const QgsCurve * >( ringGeom.
constGet() );
3878 ring = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
3886 polygon->addInteriorRing( ring->
segmentize() );
3889 return QVariant::fromValue(
QgsGeometry( std::move( polygon ) ) );
3894 auto tr = std::make_unique<QgsTriangle>();
3895 auto lineString = std::make_unique<QgsLineString>();
3896 lineString->clear();
3898 for (
const QVariant &value : values )
3900 QgsGeometry geom = QgsExpressionUtils::getGeometry( value, parent );
3907 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3914 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3922 lineString->addVertex( *point );
3925 tr->setExteriorRing( lineString.release() );
3927 return QVariant::fromValue(
QgsGeometry( tr.release() ) );
3932 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3939 double radius = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3940 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
3947 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3954 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3962 return QVariant::fromValue(
QgsGeometry( circ.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
3967 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3974 double majorAxis = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3975 double minorAxis = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3976 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3977 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 4 ), parent );
3983 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3990 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3997 QgsEllipse elp( *point, majorAxis, minorAxis, azimuth );
3998 return QVariant::fromValue(
QgsGeometry( elp.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
4004 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4011 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4018 unsigned int nbEdges =
static_cast<unsigned int>( QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) );
4021 parent->
setEvalErrorString( QObject::tr(
"Number of edges/sides must be greater than 2" ) );
4028 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (inscribed) or 1 (circumscribed)" ) );
4032 const QgsPoint *center = qgsgeometry_cast< const QgsPoint * >( pt1.
constGet() );
4039 center = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4046 const QgsPoint *corner = qgsgeometry_cast< const QgsPoint * >( pt2.
constGet() );
4053 corner = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4068 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4074 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4080 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
4081 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
4089 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4095 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4101 QgsGeometry pt3 = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
4110 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (distance) or 1 (projected)" ) );
4113 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
4114 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
4115 const QgsPoint *point3 = qgsgeometry_cast< const QgsPoint *>( pt3.
constGet() );
4134 return QVariant::fromValue( geom.
vertexAt( idx ) );
4142 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4144 const QVariant v = pointAt( geom, idx, parent );
4147 return QVariant( v.value<
QgsPoint>().
x() );
4153 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4155 return fcnOldXat( values, f, parent, node );
4157 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4159 return fcnOldXat( QVariantList() << values[1], f, parent, node );
4162 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4168 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4170 const QVariant v = pointAt( geom, vertexNumber, parent );
4172 return QVariant( v.value<
QgsPoint>().
x() );
4182 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4184 const QVariant v = pointAt( geom, idx, parent );
4187 return QVariant( v.value<
QgsPoint>().
y() );
4193 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4195 return fcnOldYat( values, f, parent, node );
4197 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4199 return fcnOldYat( QVariantList() << values[1], f, parent, node );
4202 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4208 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4210 const QVariant v = pointAt( geom, vertexNumber, parent );
4212 return QVariant( v.value<
QgsPoint>().
y() );
4219 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4225 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4227 const QVariant v = pointAt( geom, vertexNumber, parent );
4229 return QVariant( v.value<
QgsPoint>().
z() );
4236 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4242 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4244 const QVariant v = pointAt( geom, vertexNumber, parent );
4246 return QVariant( v.value<
QgsPoint>().
m() );
4265 return QVariant::fromValue( geom );
4273 QString wkt = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4275 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4281 const QByteArray wkb = QgsExpressionUtils::getBinaryValue( values.at( 0 ), parent );
4287 return !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4292 QString gml = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4299 ogcContext.
layer = mapLayerPtr.data();
4300 ogcContext.
transformContext = context->
variable( QStringLiteral(
"_project_transform_context" ) ).value<QgsCoordinateTransformContext>();
4304 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4319 return QVariant( area );
4323 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating area" ) );
4335 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4340 return QVariant( geom.
area() );
4354 return QVariant( len );
4358 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating length" ) );
4379 return QVariant( len );
4383 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating perimeter" ) );
4389 return f.
geometry().
isNull() ? QVariant( 0 ) : QVariant( f.geometry().constGet()->perimeter() );
4395 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4401 return QVariant( geom.
length() );
4406 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4407 return QVariant( geom.
isNull() ? 0 : geom.constGet()->nCoordinates() );
4412 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4421 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4430 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4445 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon *>( collection->
geometryN( i ) );
4446 if ( !curvePolygon )
4449 return QVariant( curvePolygon->
isEmpty() ? 0 : curvePolygon->numInteriorRings() );
4458 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4465 return QVariant( curvePolygon->
ringCount() );
4467 bool foundPoly =
false;
4475 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon *>( collection->
geometryN( i ) );
4476 if ( !curvePolygon )
4487 return QVariant( ringCount );
4492 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4494 QVariant result = !geomBounds.
isNull() ? QVariant::fromValue( geomBounds ) : QVariant();
4500 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4506 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4512 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4521 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4527 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4533 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4539 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4545 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4553 double max = std::numeric_limits< double >::lowest();
4557 double z = ( *it ).z();
4563 if ( max == std::numeric_limits< double >::lowest() )
4566 return QVariant( max );
4571 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4579 double min = std::numeric_limits< double >::max();
4583 double z = ( *it ).z();
4589 if ( min == std::numeric_limits< double >::max() )
4592 return QVariant( min );
4597 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4605 double min = std::numeric_limits< double >::max();
4609 double m = ( *it ).m();
4615 if ( min == std::numeric_limits< double >::max() )
4618 return QVariant( min );
4623 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4631 double max = std::numeric_limits< double >::lowest();
4635 double m = ( *it ).m();
4641 if ( max == std::numeric_limits< double >::lowest() )
4644 return QVariant( max );
4649 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4650 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom.
constGet() );
4653 parent->
setEvalErrorString( QObject::tr(
"Function `sinuosity` requires a line geometry." ) );
4662 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4666 parent->
setEvalErrorString( QObject::tr(
"Function `straight_distance_2d` requires a line geometry or a multi line geometry with a single part." ) );
4675 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4680 parent->
setEvalErrorString( QObject::tr(
"Function `roundness` requires a polygon geometry or a multi polygon geometry with a single part." ) );
4691 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4695 std::unique_ptr< QgsAbstractGeometry > flipped( geom.
constGet()->
clone() );
4697 return QVariant::fromValue(
QgsGeometry( std::move( flipped ) ) );
4702 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4706 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( fGeom.
constGet() );
4713 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
4721 return QVariant::fromValue( curve->
isClosed() );
4726 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4739 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4740 closedLine->close();
4742 result = QVariant::fromValue(
QgsGeometry( std::move( closedLine ) ) );
4754 if (
const QgsLineString *line = qgsgeometry_cast<const QgsLineString * >( collection->
geometryN( i ) ) )
4756 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4757 closedLine->close();
4759 closed->addGeometry( closedLine.release() );
4762 result = QVariant::fromValue(
QgsGeometry( std::move( closed ) ) );
4770 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4774 return QVariant::fromValue( fGeom.
isEmpty() );
4780 return QVariant::fromValue(
true );
4782 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4783 return QVariant::fromValue( fGeom.
isNull() || fGeom.
isEmpty() );
4788 if ( values.length() < 2 || values.length() > 3 )
4791 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4792 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4799 if ( values.length() == 2 )
4802 QString result = engine->relate( sGeom.
constGet() );
4803 return QVariant::fromValue( result );
4808 QString pattern = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
4809 bool result = engine->relatePattern( sGeom.
constGet(), pattern );
4810 return QVariant::fromValue( result );
4816 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4817 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4822 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4823 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4824 return fGeom.
disjoint( sGeom ) ? TVL_True : TVL_False;
4828 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4829 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4830 return fGeom.
intersects( sGeom ) ? TVL_True : TVL_False;
4834 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4835 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4836 return fGeom.
touches( sGeom ) ? TVL_True : TVL_False;
4840 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4841 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4842 return fGeom.
crosses( sGeom ) ? TVL_True : TVL_False;
4846 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4847 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4848 return fGeom.
contains( sGeom ) ? TVL_True : TVL_False;
4852 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4853 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4854 return fGeom.
overlaps( sGeom ) ? TVL_True : TVL_False;
4858 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4859 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4860 return fGeom.
within( sGeom ) ? TVL_True : TVL_False;
4865 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4866 const double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4867 const int seg = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4868 const QString endCapString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
4869 const QString joinString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
4870 const double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
4873 if ( endCapString.compare( QLatin1String(
"flat" ), Qt::CaseInsensitive ) == 0 )
4875 else if ( endCapString.compare( QLatin1String(
"square" ), Qt::CaseInsensitive ) == 0 )
4879 if ( joinString.compare( QLatin1String(
"miter" ), Qt::CaseInsensitive ) == 0 )
4881 else if ( joinString.compare( QLatin1String(
"bevel" ), Qt::CaseInsensitive ) == 0 )
4885 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4891 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4893 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4898 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4900 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4905 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4907 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4912 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4913 const QgsPoint *pt = qgsgeometry_cast<const QgsPoint *>( fGeom.
constGet() );
4920 pt = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4927 parent->
setEvalErrorString( QObject::tr(
"Function `wedge_buffer` requires a point value for the center." ) );
4931 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4932 double width = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4933 double outerRadius = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4934 double innerRadius = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
4937 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4943 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4946 parent->
setEvalErrorString( QObject::tr(
"Function `tapered_buffer` requires a line geometry." ) );
4950 double startWidth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4951 double endWidth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4952 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) );
4955 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4961 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4964 parent->
setEvalErrorString( QObject::tr(
"Function `buffer_by_m` requires a line geometry." ) );
4968 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) );
4971 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4977 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4978 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4979 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4980 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4981 if ( joinInt < 1 || joinInt > 3 )
4985 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4988 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4994 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4995 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4996 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4998 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4999 if ( joinInt < 1 || joinInt > 3 )
5003 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5006 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5012 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5013 double distStart = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5014 double distEnd = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5017 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5023 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5024 double dx = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5025 double dy = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5027 return QVariant::fromValue( fGeom );
5032 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5033 const double rotation = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5034 const QgsGeometry center = values.at( 2 ).
isValid() ? QgsExpressionUtils::getGeometry( values.at( 2 ), parent )
5036 const bool perPart = values.value( 3 ).toBool();
5043 std::unique_ptr< QgsGeometryCollection > collection( qgsgeometry_cast< QgsGeometryCollection * >( fGeom.
constGet()->
clone() ) );
5046 const QgsPointXY partCenter = ( *it )->boundingBox().center();
5047 QTransform t = QTransform::fromTranslate( partCenter.
x(), partCenter.
y() );
5048 t.rotate( -rotation );
5049 t.translate( -partCenter.
x(), -partCenter.
y() );
5050 ( *it )->transform( t );
5052 return QVariant::fromValue(
QgsGeometry( std::move( collection ) ) );
5064 parent->
setEvalErrorString( QObject::tr(
"Function 'rotate' requires a point value for the center" ) );
5072 fGeom.
rotate( rotation, pt );
5073 return QVariant::fromValue( fGeom );
5079 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5080 const double xScale = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5081 const double yScale = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5082 const QgsGeometry center = values.at( 3 ).isValid() ? QgsExpressionUtils::getGeometry( values.at( 3 ), parent )
5093 parent->
setEvalErrorString( QObject::tr(
"Function 'scale' requires a point value for the center" ) );
5101 QTransform t = QTransform::fromTranslate( pt.
x(), pt.
y() );
5102 t.scale( xScale, yScale );
5103 t.translate( -pt.
x(), -pt.
y() );
5105 return QVariant::fromValue( fGeom );
5110 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5116 const double deltaX = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5117 const double deltaY = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5119 const double rotationZ = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5121 const double scaleX = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
5122 const double scaleY = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
5124 const double deltaZ = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
5125 const double deltaM = QgsExpressionUtils::getDoubleValue( values.at( 7 ), parent );
5126 const double scaleZ = QgsExpressionUtils::getDoubleValue( values.at( 8 ), parent );
5127 const double scaleM = QgsExpressionUtils::getDoubleValue( values.at( 9 ), parent );
5138 QTransform transform;
5139 transform.translate( deltaX, deltaY );
5140 transform.rotate( rotationZ );
5141 transform.scale( scaleX, scaleY );
5142 fGeom.
transform( transform, deltaZ, scaleZ, deltaM, scaleM );
5144 return QVariant::fromValue( fGeom );
5150 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5152 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5157 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5159 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5165 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5166 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5168 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5174 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5176 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5180#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
5185 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5186 const double targetPercent = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5187 const bool allowHoles = values.value( 2 ).toBool();
5189 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5202 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5204 if ( values.length() == 2 )
5205 segments = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5213 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5219 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5221 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5227 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5233 double area,
angle, width, height;
5246 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5247 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5249 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5255 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5262 const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( fGeom.
constGet() );
5267 result = reversed ? QVariant::fromValue(
QgsGeometry( reversed ) ) : QVariant();
5275 if (
const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( collection->
geometryN( i ) ) )
5277 reversed->addGeometry( curve->
reversed() );
5284 result = reversed ? QVariant::fromValue(
QgsGeometry( std::move( reversed ) ) ) : QVariant();
5291 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5302 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->
geometryN( 0 ) );
5311 QVariant result = exterior ? QVariant::fromValue(
QgsGeometry( exterior ) ) : QVariant();
5317 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5318 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5319 return QVariant( fGeom.
distance( sGeom ) );
5324 QgsGeometry g1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5325 QgsGeometry g2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5328 if ( values.length() == 3 && values.at( 2 ).isValid() )
5330 double densify = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5331 densify = std::clamp( densify, 0.0, 1.0 );
5339 return res > -1 ? QVariant( res ) : QVariant();
5344 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5345 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5347 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5352 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5353 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5355 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5360 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5361 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5363 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5369 if ( values.length() < 1 || values.length() > 2 )
5372 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5374 if ( values.length() == 2 )
5375 prec = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5376 QString wkt = fGeom.
asWkt( prec );
5377 return QVariant( wkt );
5382 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5383 return fGeom.
isNull() ? QVariant() : QVariant( fGeom.asWkb() );
5388 if ( values.length() != 2 )
5390 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires exactly two parameters. %n given.",
nullptr, values.length() ) );
5394 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5395 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5397 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5404 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5409 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5416 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5423 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires two points as arguments." ) );
5430 if ( pt1->
y() < pt2->
y() )
5432 else if ( pt1->
y() > pt2->
y() )
5440 if ( pt1->
x() < pt2->
x() )
5442 else if ( pt1->
x() > pt2->
x() )
5443 return M_PI + ( M_PI_2 );
5448 if ( pt1->
x() < pt2->
x() )
5450 if ( pt1->
y() < pt2->
y() )
5452 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) );
5456 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5463 if ( pt1->
y() > pt2->
y() )
5465 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) )
5470 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5471 + ( M_PI + ( M_PI_2 ) );
5478 const QgsGeometry geom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5479 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5481 QString ellipsoid = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
5485 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires two valid point geometries." ) );
5493 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires point geometries or multi point geometries with a single part." ) );
5504 sourceCrs = context->
variable( QStringLiteral(
"_layer_crs" ) ).value<QgsCoordinateReferenceSystem>();
5507 if ( ellipsoid.isEmpty() )
5509 ellipsoid = context->
variable( QStringLiteral(
"project_ellipsoid" ) ).toString();
5515 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires a valid source CRS." ) );
5523 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires a valid ellipsoid acronym or ellipsoid authority ID." ) );
5529 const double bearing = da.
bearing( point1, point2 );
5530 if ( std::isfinite( bearing ) )
5532 return std::fmod( bearing + 2 * M_PI, 2 * M_PI );
5545 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5549 parent->
setEvalErrorString( QStringLiteral(
"'project' requires a point geometry" ) );
5553 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5554 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5555 double inclination = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5558 QgsPoint newPoint = p->
project( distance, 180.0 * azimuth / M_PI, 180.0 * inclination / M_PI );
5565 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5566 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5568 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5575 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5579 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5586 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5594 parent->
setEvalErrorString( QStringLiteral(
"Function 'inclination' requires two points as arguments." ) );
5604 if ( values.length() != 3 )
5607 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5608 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5609 double y = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5613 QVariant result = geom.
constGet() ? QVariant::fromValue( geom ) : QVariant();
5619 if ( values.length() < 2 )
5622 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5625 return values.at( 0 );
5627 QString expString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5628 QVariant cachedExpression;
5633 if ( cachedExpression.isValid() )
5640 bool asc = values.value( 2 ).toBool();
5658 Q_ASSERT( collection );
5662 QgsExpressionSorter sorter( orderBy );
5664 QList<QgsFeature> partFeatures;
5665 partFeatures.reserve( collection->
partCount() );
5666 for (
int i = 0; i < collection->
partCount(); ++i )
5672 sorter.sortFeatures( partFeatures, unconstedContext );
5676 Q_ASSERT( orderedGeom );
5681 for (
const QgsFeature &feature : std::as_const( partFeatures ) )
5686 QVariant result = QVariant::fromValue(
QgsGeometry( orderedGeom ) );
5689 delete unconstedContext;
5696 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5697 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5701 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5707 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5708 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5712 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5718 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5719 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5723 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5729 const QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5730 const double m = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5731 const bool use3DDistance = values.at( 2 ).toBool();
5733 double x, y, z, distance;
5756 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5759 parent->
setEvalErrorString( QObject::tr(
"line_substring requires a curve geometry input" ) );
5765 curve = qgsgeometry_cast< const QgsCurve * >( lineGeom.
constGet() );
5772 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
5779 double startDistance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5780 double endDistance = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5782 std::unique_ptr< QgsCurve > substring( curve->
curveSubstring( startDistance, endDistance ) );
5784 return !result.isNull() ? QVariant::fromValue( result ) : QVariant();
5789 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5790 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5797 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5798 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5803 vertex = count + vertex;
5811 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5812 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5817 vertex = count + vertex;
5825 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5826 QgsGeometry pointGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5830 return distance >= 0 ? distance : QVariant();
5835 const QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5836 const double m = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5837 const bool use3DDistance = values.at( 2 ).toBool();
5839 double x, y, z, distance;
5848 return found ? distance : QVariant();
5853 if ( values.length() == 2 && values.at( 1 ).toInt() != 0 )
5855 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5856 return qgsRound( number, QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
5859 if ( values.length() >= 1 )
5861 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5862 return QVariant( qlonglong( std::round( number ) ) );
5877 const double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5878 const int places = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5879 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5886 const bool omitGroupSeparator = values.value( 3 ).toBool();
5887 const bool trimTrailingZeros = values.value( 4 ).toBool();
5889 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5890 if ( !omitGroupSeparator )
5891 locale.setNumberOptions( locale.numberOptions() & ~QLocale::NumberOption::OmitGroupSeparator );
5893 locale.setNumberOptions( locale.numberOptions() | QLocale::NumberOption::OmitGroupSeparator );
5895 QString res = locale.toString( value,
'f', places );
5897 if ( trimTrailingZeros )
5899#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
5900 const QChar decimal = locale.decimalPoint();
5901 const QChar zeroDigit = locale.zeroDigit();
5903 const QChar decimal = locale.decimalPoint().at( 0 );
5904 const QChar zeroDigit = locale.zeroDigit().at( 0 );
5907 if ( res.contains( decimal ) )
5909 int trimPoint = res.length() - 1;
5911 while ( res.at( trimPoint ) == zeroDigit )
5914 if ( res.at( trimPoint ) == decimal )
5917 res.truncate( trimPoint + 1 );
5926 QDateTime datetime = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
5927 const QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5928 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5931 if ( format.indexOf(
"Z" ) > 0 )
5932 datetime = datetime.toUTC();
5934 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5935 return locale.toString( datetime, format );
5940 const QVariant variant = values.at( 0 );
5942 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
5943 if ( !color.isValid() )
5946 const float alpha = color.alphaF();
5947 if ( color.spec() == QColor::Spec::Cmyk )
5949 const float avg = ( color.cyanF() + color.magentaF() + color.yellowF() ) / 3;
5950 color = QColor::fromCmykF( avg, avg, avg, color.blackF(), alpha );
5954 const float avg = ( color.redF() + color.greenF() + color.blueF() ) / 3;
5955 color.setRgbF( avg, avg, avg, alpha );
5958 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
5965 double ratio = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5970 else if ( ratio < 0 )
5975 int red =
static_cast<int>( color1.red() * ( 1 - ratio ) + color2.red() * ratio );
5976 int green =
static_cast<int>( color1.green() * ( 1 - ratio ) + color2.green() * ratio );
5977 int blue =
static_cast<int>( color1.blue() * ( 1 - ratio ) + color2.blue() * ratio );
5978 int alpha =
static_cast<int>( color1.alpha() * ( 1 - ratio ) + color2.alpha() * ratio );
5980 QColor newColor( red, green, blue, alpha );
5987 const QVariant variant1 = values.at( 0 );
5988 const QVariant variant2 = values.at( 1 );
5990 if ( variant1.userType() != variant2.userType() )
5992 parent->
setEvalErrorString( QObject::tr(
"Both color arguments must have the same type (string or color object)" ) );
5997 const QColor color1 = QgsExpressionUtils::getColorValue( variant1, parent, isQColor );
5998 if ( !color1.isValid() )
6001 const QColor color2 = QgsExpressionUtils::getColorValue( variant2, parent, isQColor );
6002 if ( !color2.isValid() )
6005 if ( ( color1.spec() == QColor::Cmyk ) != ( color2.spec() == QColor::Cmyk ) )
6007 parent->
setEvalErrorString( QObject::tr(
"Both color arguments must have compatible color type (CMYK or RGB/HSV/HSL)" ) );
6011 const float ratio =
static_cast<float>( std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0., 1. ) );
6017 const float alpha = color1.alphaF() * ( 1 - ratio ) + color2.alphaF() * ratio;
6018 if ( color1.spec() == QColor::Spec::Cmyk )
6020 float cyan = color1.cyanF() * ( 1 - ratio ) + color2.cyanF() * ratio;
6021 float magenta = color1.magentaF() * ( 1 - ratio ) + color2.magentaF() * ratio;
6022 float yellow = color1.yellowF() * ( 1 - ratio ) + color2.yellowF() * ratio;
6023 float black = color1.blackF() * ( 1 - ratio ) + color2.blackF() * ratio;
6024 newColor = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6028 float red = color1.redF() * ( 1 - ratio ) + color2.redF() * ratio;
6029 float green = color1.greenF() * ( 1 - ratio ) + color2.greenF() * ratio;
6030 float blue = color1.blueF() * ( 1 - ratio ) + color2.blueF() * ratio;
6031 newColor = QColor::fromRgbF( red, green, blue, alpha );
6036 return isQColor ? QVariant( newColor ) : QVariant(
QgsSymbolLayerUtils::encodeColor( newColor ) );
6041 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
6042 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6043 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6044 QColor color = QColor( red, green, blue );
6045 if ( ! color.isValid() )
6047 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( red ).arg( green ).arg( blue ) );
6048 color = QColor( 0, 0, 0 );
6051 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6056 const float red = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6057 const float green = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6058 const float blue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6059 const float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6060 QColor color = QColor::fromRgbF( red, green, blue, alpha );
6061 if ( ! color.isValid() )
6063 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
6072 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
6073 QVariant value = node->
eval( parent, context );
6077 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
6079 value = node->
eval( parent, context );
6087 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
6089 QVariant value = node->
eval( parent, context );
6091 if ( value.toBool() )
6093 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
6095 value = node->
eval( parent, context );
6100 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
6102 value = node->
eval( parent, context );
6110 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
6111 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6112 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6113 int alpha = QgsExpressionUtils::getNativeIntValue( values.at( 3 ), parent );
6114 QColor color = QColor( red, green, blue, alpha );
6115 if ( ! color.isValid() )
6117 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
6118 color = QColor( 0, 0, 0 );
6127 if ( values.at( 0 ).userType() == qMetaTypeId< QgsGradientColorRamp>() )
6129 expRamp = QgsExpressionUtils::getRamp( values.at( 0 ), parent );
6134 QString rampName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
6112 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent ); {
…}
6138 parent->
setEvalErrorString( QObject::tr(
"\"%1\" is not a valid color ramp" ).arg( rampName ) );
6143 double value = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
6144 QColor color = ramp->
color( value );
6157 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6159 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6161 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6163 QColor color = QColor::fromHslF( hue, saturation, lightness );
6165 if ( ! color.isValid() )
6167 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( lightness ) );
6168 color = QColor( 0, 0, 0 );
6171 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6177 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6179 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6181 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6183 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
6185 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
6186 if ( ! color.isValid() )
6188 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
6189 color = QColor( 0, 0, 0 );
6196 float hue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6197 float saturation = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6198 float lightness = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6199 float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6201 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
6202 if ( ! color.isValid() )
6204 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
6214 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6216 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6218 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6220 QColor color = QColor::fromHsvF( hue, saturation, value );
6222 if ( ! color.isValid() )
6224 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( value ) );
6225 color = QColor( 0, 0, 0 );
6228 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6234 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6236 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6238 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6240 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
6242 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
6243 if ( ! color.isValid() )
6245 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
6246 color = QColor( 0, 0, 0 );
6253 float hue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6254 float saturation = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6255 float value = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6256 float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6257 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
6259 if ( ! color.isValid() )
6261 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
6270 const float cyan = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6271 const float magenta = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6272 const float yellow = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6273 const float black = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6274 const float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ) ), 0.f, 1.f );
6276 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6277 if ( ! color.isValid() )
6279 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
6289 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
6291 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6293 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6295 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
6297 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black );
6299 if ( ! color.isValid() )
6301 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ) );
6302 color = QColor( 0, 0, 0 );
6305 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6311 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
6313 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6315 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6317 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
6319 double alpha = QgsExpressionUtils::getIntValue( values.at( 4 ), parent ) / 255.0;
6321 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6322 if ( ! color.isValid() )
6324 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
6325 color = QColor( 0, 0, 0 );
6332 const QVariant variant = values.at( 0 );
6334 const QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6335 if ( !color.isValid() )
6338 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6339 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6341 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6342 return color.green();
6343 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6344 return color.blue();
6345 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6346 return color.alpha();
6347 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6348 return static_cast< double >( color.hsvHueF() * 360 );
6349 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6350 return static_cast< double >( color.hsvSaturationF() * 100 );
6351 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6352 return static_cast< double >( color.valueF() * 100 );
6353 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6354 return static_cast< double >( color.hslHueF() * 360 );
6355 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6356 return static_cast< double >( color.hslSaturationF() * 100 );
6357 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6358 return static_cast< double >( color.lightnessF() * 100 );
6359 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6360 return static_cast< double >( color.cyanF() * 100 );
6361 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6362 return static_cast< double >( color.magentaF() * 100 );
6363 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6364 return static_cast< double >( color.yellowF() * 100 );
6365 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6366 return static_cast< double >( color.blackF() * 100 );
6368 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6374 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
6377 parent->
setEvalErrorString( QObject::tr(
"A minimum of two colors is required to create a ramp" ) );
6381 QList< QColor > colors;
6383 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
6386 if ( !colors.last().isValid() )
6388 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( it.value().toString() ) );
6392 double step = it.key().toDouble();
6393 if ( it == map.constBegin() )
6398 else if ( it == map.constEnd() )
6408 bool discrete = values.at( 1 ).toBool();
6410 if ( colors.empty() )
6413 return QVariant::fromValue(
QgsGradientColorRamp( colors.first(), colors.last(), discrete, stops ) );
6418 const QVariant variant = values.at( 0 );
6420 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6421 if ( !color.isValid() )
6424 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6425 int value = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6426 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6427 color.setRed( std::clamp( value, 0, 255 ) );
6428 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6429 color.setGreen( std::clamp( value, 0, 255 ) );
6430 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6431 color.setBlue( std::clamp( value, 0, 255 ) );
6432 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6433 color.setAlpha( std::clamp( value, 0, 255 ) );
6434 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6435 color.setHsv( std::clamp( value, 0, 359 ), color.hsvSaturation(), color.value(), color.alpha() );
6436 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6437 color.setHsvF( color.hsvHueF(), std::clamp( value, 0, 100 ) / 100.0, color.valueF(), color.alphaF() );
6438 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6439 color.setHsvF( color.hsvHueF(), color.hsvSaturationF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6440 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6441 color.setHsl( std::clamp( value, 0, 359 ), color.hslSaturation(), color.lightness(), color.alpha() );
6442 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6443 color.setHslF( color.hslHueF(), std::clamp( value, 0, 100 ) / 100.0, color.lightnessF(), color.alphaF() );
6444 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6445 color.setHslF( color.hslHueF(), color.hslSaturationF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6446 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6447 color.setCmykF( std::clamp( value, 0, 100 ) / 100.0, color.magentaF(), color.yellowF(), color.blackF(), color.alphaF() );
6448 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6449 color.setCmykF( color.cyanF(), std::clamp( value, 0, 100 ) / 100.0, color.yellowF(), color.blackF(), color.alphaF() );
6450 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6451 color.setCmykF( color.cyanF(), color.magentaF(), std::clamp( value, 0, 100 ) / 100.0, color.blackF(), color.alphaF() );
6452 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6453 color.setCmykF( color.cyanF(), color.magentaF(), color.yellowF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6456 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6459 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6464 const QVariant variant = values.at( 0 );
6466 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6467 if ( !color.isValid() )
6470 color = color.darker( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6472 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6477 const QVariant variant = values.at( 0 );
6479 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6480 if ( !color.isValid() )
6483 color = color.lighter( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6485 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6490 QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6493 return QVariant::fromValue( geom );
6499 const QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6507 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
6512 return QVariant::fromValue( fGeom );
6515 return QVariant::fromValue( fGeom );
6524 return QVariant::fromValue( fGeom );
6537 bool foundLayer =
false;
6538 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6541 if ( !featureSource || !foundLayer )
6546 const QgsFeatureId fid = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
6559 result = QVariant::fromValue( fet );
6567 bool foundLayer =
false;
6568 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6571 if ( !featureSource || !foundLayer )
6576 QString cacheValueKey;
6577 if ( values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
6579 QVariantMap attributeMap = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
6581 QMap <QString, QVariant>::const_iterator i = attributeMap.constBegin();
6582 QString filterString;
6583 for ( ; i != attributeMap.constEnd(); ++i )
6585 if ( !filterString.isEmpty() )
6587 filterString.append(
" AND " );
6591 cacheValueKey = QStringLiteral(
"getfeature:%1:%2" ).arg( featureSource->id(), filterString );
6600 QString attribute = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6601 int attributeId = featureSource->fields().lookupField( attribute );
6602 if ( attributeId == -1 )
6607 const QVariant &attVal = values.at( 2 );
6609 cacheValueKey = QStringLiteral(
"getfeature:%1:%2:%3" ).arg( featureSource->id(), QString::number( attributeId ), attVal.toString() );
6632 res = QVariant::fromValue( fet );
6647 if ( !values.isEmpty() )
6650 if ( col && ( values.size() == 1 || !values.at( 1 ).isValid() ) )
6651 fieldName = col->
name();
6652 else if ( values.size() == 2 )
6653 fieldName = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6656 QVariant value = values.at( 0 );
6661 if ( fieldIndex == -1 )
6663 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: Field not found %2" ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6669 QgsVectorLayer *layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
6672 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName, value.toString() );
6681 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName );
6699 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: function cannot be evaluated without a context." ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6707 const QVariant data = values.at( 0 );
6708 const QMimeDatabase db;
6709 return db.mimeTypeForData( data.toByteArray() ).name();
6714 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6716 bool foundLayer =
false;
6717 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [layerProperty](
QgsMapLayer * layer )-> QVariant
6723 if ( QString::compare( layerProperty, QStringLiteral(
"name" ), Qt::CaseInsensitive ) == 0 )
6724 return layer->name();
6725 else if ( QString::compare( layerProperty, QStringLiteral(
"id" ), Qt::CaseInsensitive ) == 0 )
6727 else if ( QString::compare( layerProperty, QStringLiteral(
"title" ), Qt::CaseInsensitive ) == 0 )
6728 return !layer->metadata().title().isEmpty() ? layer->metadata().title() : layer->serverProperties()->title();
6729 else if ( QString::compare( layerProperty, QStringLiteral(
"abstract" ), Qt::CaseInsensitive ) == 0 )
6730 return !layer->metadata().abstract().isEmpty() ? layer->metadata().abstract() : layer->serverProperties()->abstract();
6731 else if ( QString::compare( layerProperty, QStringLiteral(
"keywords" ), Qt::CaseInsensitive ) == 0 )
6733 QStringList keywords;
6734 const QgsAbstractMetadataBase::KeywordMap keywordMap = layer->metadata().keywords();
6735 for ( auto it = keywordMap.constBegin(); it != keywordMap.constEnd(); ++it )
6737 keywords.append( it.value() );
6739 if ( !keywords.isEmpty() )
6741 return layer->serverProperties()->keywordList();
6743 else if ( QString::compare( layerProperty, QStringLiteral(
"data_url" ), Qt::CaseInsensitive ) == 0 )
6745 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution" ), Qt::CaseInsensitive ) == 0 )
6747 return !layer->
metadata().
rights().isEmpty() ? QVariant( layer->
metadata().
rights() ) : QVariant( layer->serverProperties()->attribution() );
6749 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution_url" ), Qt::CaseInsensitive ) == 0 )
6751 else if ( QString::compare( layerProperty, QStringLiteral(
"source" ), Qt::CaseInsensitive ) == 0 )
6753 else if ( QString::compare( layerProperty, QStringLiteral(
"min_scale" ), Qt::CaseInsensitive ) == 0 )
6755 else if ( QString::compare( layerProperty, QStringLiteral(
"max_scale" ), Qt::CaseInsensitive ) == 0 )
6757 else if ( QString::compare( layerProperty, QStringLiteral(
"is_editable" ), Qt::CaseInsensitive ) == 0 )
6759 else if ( QString::compare( layerProperty, QStringLiteral(
"crs" ), Qt::CaseInsensitive ) == 0 )
6761 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_definition" ), Qt::CaseInsensitive ) == 0 )
6763 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_description" ), Qt::CaseInsensitive ) == 0 )
6765 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_ellipsoid" ), Qt::CaseInsensitive ) == 0 )
6767 else if ( QString::compare( layerProperty, QStringLiteral(
"extent" ), Qt::CaseInsensitive ) == 0 )
6770 QVariant result = QVariant::fromValue( extentGeom );
6773 else if ( QString::compare( layerProperty, QStringLiteral(
"distance_units" ), Qt::CaseInsensitive ) == 0 )
6775 else if ( QString::compare( layerProperty, QStringLiteral(
"path" ), Qt::CaseInsensitive ) == 0 )
6778 return decodedUri.value( QStringLiteral(
"path" ) );
6780 else if ( QString::compare( layerProperty, QStringLiteral(
"type" ), Qt::CaseInsensitive ) == 0 )
6782 switch ( layer->
type() )
6785 return QCoreApplication::translate(
"expressions",
"Vector" );
6787 return QCoreApplication::translate(
"expressions",
"Raster" );
6789 return QCoreApplication::translate(
"expressions",
"Mesh" );
6791 return QCoreApplication::translate(
"expressions",
"Vector Tile" );
6793 return QCoreApplication::translate(
"expressions",
"Plugin" );
6795 return QCoreApplication::translate(
"expressions",
"Annotation" );
6797 return QCoreApplication::translate(
"expressions",
"Point Cloud" );
6799 return QCoreApplication::translate(
"expressions",
"Group" );
6801 return QCoreApplication::translate(
"expressions",
"Tiled Scene" );
6807 QgsVectorLayer *vLayer = qobject_cast< QgsVectorLayer * >( layer );
6810 if ( QString::compare( layerProperty, QStringLiteral(
"storage_type" ), Qt::CaseInsensitive ) == 0 )
6812 else if ( QString::compare( layerProperty, QStringLiteral(
"geometry_type" ), Qt::CaseInsensitive ) == 0 )
6814 else if ( QString::compare( layerProperty, QStringLiteral(
"feature_count" ), Qt::CaseInsensitive ) == 0 )
6830 const QString uriPart = values.at( 1 ).toString();
6832 bool foundLayer =
false;
6834 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, uriPart](
QgsMapLayer * layer )-> QVariant
6836 if ( !layer->dataProvider() )
6838 parent->setEvalErrorString( QObject::tr(
"Layer %1 has invalid data provider" ).arg( layer->name() ) );
6844 if ( !uriPart.isNull() )
6846 return decodedUri.value( uriPart );
6856 parent->
setEvalErrorString( QObject::tr(
"Function `decode_uri` requires a valid layer." ) );
6867 const int band = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6868 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6870 bool foundLayer =
false;
6871 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, band, layerProperty](
QgsMapLayer * layer )-> QVariant
6873 QgsRasterLayer *rl = qobject_cast< QgsRasterLayer * >( layer );
6877 if ( band < 1 || band > rl->bandCount() )
6879 parent->setEvalErrorString( QObject::tr(
"Invalid band number %1 for layer" ).arg( band ) );
6885 if ( QString::compare( layerProperty, QStringLiteral(
"avg" ), Qt::CaseInsensitive ) == 0 )
6887 else if ( QString::compare( layerProperty, QStringLiteral(
"stdev" ), Qt::CaseInsensitive ) == 0 )
6889 else if ( QString::compare( layerProperty, QStringLiteral(
"min" ), Qt::CaseInsensitive ) == 0 )
6891 else if ( QString::compare( layerProperty, QStringLiteral(
"max" ), Qt::CaseInsensitive ) == 0 )
6893 else if ( QString::compare( layerProperty, QStringLiteral(
"range" ), Qt::CaseInsensitive ) == 0 )
6895 else if ( QString::compare( layerProperty, QStringLiteral(
"sum" ), Qt::CaseInsensitive ) == 0 )
6899 parent->
setEvalErrorString( QObject::tr(
"Invalid raster statistic: '%1'" ).arg( layerProperty ) );
6927 parent->
setEvalErrorString( QObject::tr(
"Function `raster_statistic` requires a valid raster layer." ) );
6944 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6945 bool ascending = values.value( 1 ).toBool();
6946 std::sort( list.begin(), list.end(), [ascending]( QVariant a, QVariant b ) ->
bool { return ( !ascending ? qgsVariantLessThan( b, a ) : qgsVariantLessThan( a, b ) ); } );
6952 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).length();
6957 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).contains( values.at( 1 ) ) );
6962 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).count( values.at( 1 ) ) );
6967 QVariantList listA = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6968 QVariantList listB = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
6970 for (
const auto &item : listB )
6972 if ( listA.contains( item ) )
6976 return QVariant( match == listB.count() );
6981 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).indexOf( values.at( 1 ) );
6986 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6987 const int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6988 if ( pos < list.length() && pos >= 0 )
return list.at( pos );
6989 else if ( pos < 0 && ( list.length() + pos ) >= 0 )
6990 return list.at( list.length() + pos );
6996 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6997 return list.value( 0 );
7002 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7003 return list.value( list.size() - 1 );
7008 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7009 return list.isEmpty() ? QVariant() : *std::min_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
7014 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7015 return list.isEmpty() ? QVariant() : *std::max_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
7020 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7023 for (
const QVariant &item : list )
7025 switch ( item.userType() )
7027 case QMetaType::Int:
7028 case QMetaType::UInt:
7029 case QMetaType::LongLong:
7030 case QMetaType::ULongLong:
7031 case QMetaType::Float:
7032 case QMetaType::Double:
7033 total += item.toDouble();
7038 return i == 0 ? QVariant() : total / i;
7043 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7044 QVariantList numbers;
7045 for (
const auto &item : list )
7047 switch ( item.userType() )
7049 case QMetaType::Int:
7050 case QMetaType::UInt:
7051 case QMetaType::LongLong:
7052 case QMetaType::ULongLong:
7053 case QMetaType::Float:
7054 case QMetaType::Double:
7055 numbers.append( item );
7059 std::sort( numbers.begin(), numbers.end(), []( QVariant a, QVariant b ) ->
bool { return ( qgsVariantLessThan( a, b ) ); } );
7060 const int count = numbers.count();
7065 else if ( count % 2 )
7067 return numbers.at( count / 2 );
7071 return ( numbers.at( count / 2 - 1 ).toDouble() + numbers.at( count / 2 ).toDouble() ) / 2;
7077 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7080 for (
const QVariant &item : list )
7082 switch ( item.userType() )
7084 case QMetaType::Int:
7085 case QMetaType::UInt:
7086 case QMetaType::LongLong:
7087 case QMetaType::ULongLong:
7088 case QMetaType::Float:
7089 case QMetaType::Double:
7090 total += item.toDouble();
7095 return i == 0 ? QVariant() : total;
7098static QVariant convertToSameType(
const QVariant &value, QMetaType::Type type )
7100 QVariant result = value;
7101 result.convert(
static_cast<int>( type ) );
7107 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7108 QHash< QVariant, int > hash;
7109 for (
const auto &item : list )
7113 const QList< int > occurrences = hash.values();
7114 if ( occurrences.empty() )
7115 return QVariantList();
7117 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
7119 const QString option = values.at( 1 ).toString();
7120 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
7122 return convertToSameType( hash.keys( maxValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7124 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
7126 if ( hash.isEmpty() )
7129 return QVariant( hash.key( maxValue ) );
7131 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
7133 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( maxValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) ), context, parent, node );
7135 else if ( option.compare( QLatin1String(
"real_majority" ), Qt::CaseInsensitive ) == 0 )
7137 if ( maxValue * 2 <= list.size() )
7140 return QVariant( hash.key( maxValue ) );
7151 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7152 QHash< QVariant, int > hash;
7153 for (
const auto &item : list )
7157 const QList< int > occurrences = hash.values();
7158 if ( occurrences.empty() )
7159 return QVariantList();
7161 const int minValue = *std::min_element( occurrences.constBegin(), occurrences.constEnd() );
7163 const QString option = values.at( 1 ).toString();
7164 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
7166 return convertToSameType( hash.keys( minValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7168 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
7170 if ( hash.isEmpty() )
7173 return QVariant( hash.key( minValue ) );
7175 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
7177 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( minValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) ), context, parent, node );
7179 else if ( option.compare( QLatin1String(
"real_minority" ), Qt::CaseInsensitive ) == 0 )
7181 if ( hash.isEmpty() )
7185 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
7186 if ( maxValue * 2 > list.size() )
7187 hash.remove( hash.key( maxValue ) );
7189 return convertToSameType( hash.keys(),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7200 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7201 list.append( values.at( 1 ) );
7202 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7207 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7208 list.prepend( values.at( 1 ) );
7209 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7214 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7215 list.insert( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), values.at( 2 ) );
7216 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7221 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7222 int position = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7224 position = position + list.length();
7225 if ( position >= 0 && position < list.length() )
7226 list.removeAt( position );
7227 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7235 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7237 const QVariant toRemove = values.at( 1 );
7240 list.erase( std::remove_if( list.begin(), list.end(), [](
const QVariant & element )
7242 return QgsVariantUtils::isNull( element );
7247 list.removeAll( toRemove );
7249 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7254 if ( values.count() == 2 && values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
7256 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
7258 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7259 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
7261 int index = list.indexOf( it.key() );
7262 while ( index >= 0 )
7264 list.replace( index, it.value() );
7265 index = list.indexOf( it.key() );
7269 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7271 else if ( values.count() == 3 )
7273 QVariantList before;
7275 bool isSingleReplacement =
false;
7277 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).userType() != QMetaType::Type::QStringList )
7279 before = QVariantList() << values.at( 1 );
7283 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
7286 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
7288 after = QVariantList() << values.at( 2 );
7289 isSingleReplacement =
true;
7293 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
7296 if ( !isSingleReplacement && before.length() != after.length() )
7298 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
7302 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7303 for (
int i = 0; i < before.length(); i++ )
7305 int index = list.indexOf( before.at( i ) );
7306 while ( index >= 0 )
7308 list.replace( index, after.at( isSingleReplacement ? 0 : i ) );
7309 index = list.indexOf( before.at( i ) );
7313 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7317 parent->
setEvalErrorString( QObject::tr(
"Function array_replace requires 2 or 3 arguments" ) );
7324 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7325 QVariantList list_new;
7327 for (
const QVariant &cur :
QgsExpressionUtils::getListValue( values.at( 1 ), parent ) )
7329 while ( list.removeOne( cur ) )
7331 list_new.append( cur );
7335 list_new.append( list );
7337 return convertToSameType( list_new,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7343 for (
const QVariant &cur : values )
7345 list += QgsExpressionUtils::getListValue( cur, parent );
7347 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7352 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7353 int start_pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7354 const int end_pos = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
7355 int slice_length = 0;
7357 if ( start_pos < 0 )
7359 start_pos = list.length() + start_pos;
7363 slice_length = end_pos - start_pos + 1;
7367 slice_length = list.length() + end_pos - start_pos + 1;
7370 if ( slice_length < 0 )
7374 list = list.mid( start_pos, slice_length );
7380 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7381 std::reverse( list.begin(), list.end() );
7387 const QVariantList array1 = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7388 const QVariantList array2 = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
7389 for (
const QVariant &cur : array2 )
7391 if ( array1.contains( cur ) )
7392 return QVariant(
true );
7394 return QVariant(
false );
7399 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7401 QVariantList distinct;
7403 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7405 if ( !distinct.contains( *it ) )
7407 distinct += ( *it );
7416 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7417 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7418 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7422 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7424 str += ( !( *it ).toString().isEmpty() ) ? ( *it ).toString() : empty;
7425 if ( it != ( array.constEnd() - 1 ) )
7431 return QVariant( str );
7436 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7437 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7438 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7440 QStringList list = str.split( delimiter );
7443 for ( QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
7445 array += ( !( *it ).isEmpty() ) ? *it : empty;
7453 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7454 QJsonDocument document = QJsonDocument::fromJson( str.toUtf8() );
7455 if ( document.isNull() )
7458 return document.toVariant();
7464 QJsonDocument document = QJsonDocument::fromVariant( values.at( 0 ) );
7465 return QString( document.toJson( QJsonDocument::Compact ) );
7470 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7471 if ( str.isEmpty() )
7472 return QVariantMap();
7473 str = str.trimmed();
7480 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7487 for (
int i = 0; i + 1 < values.length(); i += 2 )
7489 result.insert( QgsExpressionUtils::getStringValue( values.at( i ), parent ), values.at( i + 1 ) );
7496 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7497 const QString prefix = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7498 QVariantMap resultMap;
7500 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7502 resultMap.insert( QString( it.key() ).prepend( prefix ), it.value() );
7510 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).value( values.at( 1 ).toString() );
7515 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).contains( values.at( 1 ).toString() );
7520 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7521 map.remove( values.at( 1 ).toString() );
7527 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7528 map.insert( values.at( 1 ).toString(), values.at( 2 ) );
7535 for (
const QVariant &cur : values )
7537 const QVariantMap curMap = QgsExpressionUtils::getMapValue( cur, parent );
7538 for ( QVariantMap::const_iterator it = curMap.constBegin(); it != curMap.constEnd(); ++it )
7539 result.insert( it.key(), it.value() );
7546 return QStringList( QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).keys() );
7551 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).values();
7556 const QString envVarName = values.at( 0 ).toString();
7557 if ( !QProcessEnvironment::systemEnvironment().contains( envVarName ) )
7560 return QProcessEnvironment::systemEnvironment().value( envVarName );
7565 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7568 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"base_file_name" ) ) );
7571 return QFileInfo( file ).completeBaseName();
7576 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7579 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_suffix" ) ) );
7582 return QFileInfo( file ).completeSuffix();
7587 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7590 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_exists" ) ) );
7593 return QFileInfo::exists( file );
7598 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7601 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_name" ) ) );
7604 return QFileInfo( file ).fileName();
7609 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7612 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_file" ) ) );
7615 return QFileInfo( file ).isFile();
7620 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7623 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_directory" ) ) );
7626 return QFileInfo( file ).isDir();
7631 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7634 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_path" ) ) );
7637 return QDir::toNativeSeparators( QFileInfo( file ).path() );
7642 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7645 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_size" ) ) );
7648 return QFileInfo( file ).size();
7651static QVariant fcnHash(
const QString &str,
const QCryptographicHash::Algorithm
algorithm )
7653 return QString( QCryptographicHash::hash( str.toUtf8(),
algorithm ).toHex() );
7659 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7660 QString method = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).toLower();
7662 if ( method == QLatin1String(
"md4" ) )
7664 hash = fcnHash( str, QCryptographicHash::Md4 );
7666 else if ( method == QLatin1String(
"md5" ) )
7668 hash = fcnHash( str, QCryptographicHash::Md5 );
7670 else if ( method == QLatin1String(
"sha1" ) )
7672 hash = fcnHash( str, QCryptographicHash::Sha1 );
7674 else if ( method == QLatin1String(
"sha224" ) )
7676 hash = fcnHash( str, QCryptographicHash::Sha224 );
7678 else if ( method == QLatin1String(
"sha256" ) )
7680 hash = fcnHash( str, QCryptographicHash::Sha256 );
7682 else if ( method == QLatin1String(
"sha384" ) )
7684 hash = fcnHash( str, QCryptographicHash::Sha384 );
7686 else if ( method == QLatin1String(
"sha512" ) )
7688 hash = fcnHash( str, QCryptographicHash::Sha512 );
7690 else if ( method == QLatin1String(
"sha3_224" ) )
7692 hash = fcnHash( str, QCryptographicHash::Sha3_224 );
7694 else if ( method == QLatin1String(
"sha3_256" ) )
7696 hash = fcnHash( str, QCryptographicHash::Sha3_256 );
7698 else if ( method == QLatin1String(
"sha3_384" ) )
7700 hash = fcnHash( str, QCryptographicHash::Sha3_384 );
7702 else if ( method == QLatin1String(
"sha3_512" ) )
7704 hash = fcnHash( str, QCryptographicHash::Sha3_512 );
7706 else if ( method == QLatin1String(
"keccak_224" ) )
7708 hash = fcnHash( str, QCryptographicHash::Keccak_224 );
7710 else if ( method == QLatin1String(
"keccak_256" ) )
7712 hash = fcnHash( str, QCryptographicHash::Keccak_256 );
7714 else if ( method == QLatin1String(
"keccak_384" ) )
7716 hash = fcnHash( str, QCryptographicHash::Keccak_384 );
7718 else if ( method == QLatin1String(
"keccak_512" ) )
7720 hash = fcnHash( str, QCryptographicHash::Keccak_512 );
7724 parent->
setEvalErrorString( QObject::tr(
"Hash method %1 is not available on this system." ).arg( str ) );
7731 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Md5 );
7736 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Sha256 );
7741 const QByteArray input = values.at( 0 ).toByteArray();
7742 return QVariant( QString( input.toBase64() ) );
7747 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7749 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7751 query.addQueryItem( it.key(), it.value().toString() );
7753 return query.toString( QUrl::ComponentFormattingOption::FullyEncoded );
7758 const QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7759 const QByteArray base64 = value.toLocal8Bit();
7760 const QByteArray decoded = QByteArray::fromBase64( base64 );
7761 return QVariant( decoded );
7766static 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 )
7771 parent->
setEvalErrorString( QStringLiteral(
"This function was called without an expression context." ) );
7775 const QVariant sourceLayerRef = context->
variable( QStringLiteral(
"layer" ) );
7778 QgsVectorLayer *sourceLayer = QgsExpressionUtils::getVectorLayer( sourceLayerRef, context, parent );
7787 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
7790 const bool layerCanBeCached = node->
isStatic( parent, context );
7791 QVariant targetLayerValue = node->
eval( parent, context );
7795 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
7797 QString subExpString = node->dump();
7799 bool testOnly = ( subExpString ==
"NULL" );
7802 QgsVectorLayer *targetLayer = QgsExpressionUtils::getVectorLayer( targetLayerValue, context, parent );
7806 parent->
setEvalErrorString( QObject::tr(
"Layer '%1' could not be loaded." ).arg( targetLayerValue.toString() ) );
7811 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
7813 QString filterString = node->dump();
7814 if ( filterString !=
"NULL" )
7816 request.setFilterExpression( filterString );
7820 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
7822 QVariant limitValue = node->eval( parent, context );
7824 qlonglong limit = QgsExpressionUtils::getIntValue( limitValue, parent );
7827 double max_distance = 0;
7828 if ( isNearestFunc )
7830 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
7832 QVariant distanceValue = node->eval( parent, context );
7834 max_distance = QgsExpressionUtils::getDoubleValue( distanceValue, parent );
7838 node = QgsExpressionUtils::getNode( values.at( isNearestFunc ? 5 : 4 ), parent );
7840 QVariant cacheValue = node->eval( parent, context );
7842 bool cacheEnabled = cacheValue.toBool();
7848 double minOverlap { -1 };
7849 double minInscribedCircleRadius { -1 };
7850 bool returnDetails =
false;
7851 bool sortByMeasure =
false;
7852 bool sortAscending =
false;
7853 bool requireMeasures =
false;
7854 bool overlapOrRadiusFilter =
false;
7855 if ( isIntersectsFunc )
7858 node = QgsExpressionUtils::getNode( values.at( 5 ), parent );
7860 const QVariant minOverlapValue = node->eval( parent, context );
7862 minOverlap = QgsExpressionUtils::getDoubleValue( minOverlapValue, parent );
7863 node = QgsExpressionUtils::getNode( values.at( 6 ), parent );
7865 const QVariant minInscribedCircleRadiusValue = node->eval( parent, context );
7867 minInscribedCircleRadius = QgsExpressionUtils::getDoubleValue( minInscribedCircleRadiusValue, parent );
7868 node = QgsExpressionUtils::getNode( values.at( 7 ), parent );
7870 returnDetails = !testOnly && node->eval( parent, context ).toBool();
7871 node = QgsExpressionUtils::getNode( values.at( 8 ), parent );
7873 const QString sorting { node->eval( parent, context ).toString().toLower() };
7874 sortByMeasure = !testOnly && ( sorting.startsWith(
"asc" ) || sorting.startsWith(
"des" ) );
7875 sortAscending = sorting.startsWith(
"asc" );
7876 requireMeasures = sortByMeasure || returnDetails;
7877 overlapOrRadiusFilter = minInscribedCircleRadius != -1 || minOverlap != -1;
7884 if ( sourceLayer && targetLayer->crs() != sourceLayer->crs() )
7887 request.setDestinationCrs( sourceLayer->crs(), TransformContext );
7890 bool sameLayers = ( sourceLayer && sourceLayer->id() == targetLayer->id() );
7893 if ( bboxGrow != 0 )
7895 intDomain.
grow( bboxGrow );
7898 const QString cacheBase { QStringLiteral(
"%1:%2:%3" ).arg( targetLayer->id(), subExpString, filterString ) };
7904 QList<QgsFeature> features;
7905 if ( isNearestFunc || ( layerCanBeCached && cacheEnabled ) )
7909 const QString cacheLayer { QStringLiteral(
"ovrlaylyr:%1" ).arg( cacheBase ) };
7910 const QString cacheIndex { QStringLiteral(
"ovrlayidx:%1" ).arg( cacheBase ) };
7914 cachedTarget = targetLayer->
materialize( request );
7915 if ( layerCanBeCached )
7916 context->
setCachedValue( cacheLayer, QVariant::fromValue( cachedTarget ) );
7926 if ( layerCanBeCached )
7927 context->
setCachedValue( cacheIndex, QVariant::fromValue( spatialIndex ) );
7934 QList<QgsFeatureId> fidsList;
7935 if ( isNearestFunc )
7937 fidsList = spatialIndex.
nearestNeighbor( geometry, sameLayers ? limit + 1 : limit, max_distance );
7941 fidsList = spatialIndex.
intersects( intDomain );
7944 QListIterator<QgsFeatureId> i( fidsList );
7945 while ( i.hasNext() )
7948 if ( sameLayers && feat.
id() == fId2 )
7950 features.append( cachedTarget->
getFeature( fId2 ) );
7958 request.setFilterRect( intDomain );
7963 if ( sameLayers && feat.
id() == feat2.
id() )
7965 features.append( feat2 );
7973 const QString expCacheKey { QStringLiteral(
"exp:%1" ).arg( cacheBase ) };
7974 const QString ctxCacheKey { QStringLiteral(
"ctx:%1" ).arg( cacheBase ) };
7980 subExpression.
prepare( &subContext );
7993 auto testLinestring = [ = ](
const QgsGeometry intersection,
double & overlapValue ) ->
bool
7995 bool testResult {
false };
7997 QVector<double> overlapValues;
8001 const QgsCurve *geom = qgsgeometry_cast< const QgsCurve * >( *it );
8003 if ( minOverlap != -1 || requireMeasures )
8005 overlapValue = geom->
length();
8006 overlapValues.append( overlapValue );
8007 if ( minOverlap != -1 )
8009 if ( overlapValue >= minOverlap )
8021 if ( ! overlapValues.isEmpty() )
8023 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
8030 auto testPolygon = [ = ](
const QgsGeometry intersection,
double & radiusValue,
double & overlapValue ) ->
bool
8033 bool testResult {
false };
8035 QVector<double> overlapValues;
8036 QVector<double> radiusValues;
8039 const QgsCurvePolygon *geom = qgsgeometry_cast< const QgsCurvePolygon * >( *it );
8041 if ( minOverlap != -1 || requireMeasures )
8043 overlapValue = geom->
area();
8044 overlapValues.append( geom->
area() );
8045 if ( minOverlap != - 1 )
8047 if ( overlapValue >= minOverlap )
8059 if ( minInscribedCircleRadius != -1 || requireMeasures )
8062 const double width = bbox.
width();
8063 const double height = bbox.
height();
8064 const double size = width > height ? width : height;
8065 const double tolerance = size / 100.0;
8067 testResult = radiusValue >= minInscribedCircleRadius;
8068 radiusValues.append( radiusValues );
8073 if ( !radiusValues.isEmpty() )
8075 radiusValue = *std::max_element( radiusValues.cbegin(), radiusValues.cend() );
8078 if ( ! overlapValues.isEmpty() )
8080 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
8090 QVariantList results;
8092 QListIterator<QgsFeature> i( features );
8093 while ( i.hasNext() && ( sortByMeasure || limit == -1 || foundCount < limit ) )
8099 if ( ! relationFunction || ( geometry.*relationFunction )( feat2.
geometry() ) )
8102 double overlapValue = -1;
8103 double radiusValue = -1;
8105 if ( isIntersectsFunc && ( requireMeasures || overlapOrRadiusFilter ) )
8118 for (
const auto &geom : std::as_const( geometries ) )
8120 switch ( geom.type() )
8124 poly.append( geom.asPolygon() );
8129 line.append( geom.asPolyline() );
8134 point.append( geom.asPoint() );
8145 switch ( geometry.
type() )
8173 switch ( intersection.
type() )
8180 bool testResult { testPolygon( intersection, radiusValue, overlapValue ) };
8182 if ( ! testResult && overlapOrRadiusFilter )
8195 if ( minInscribedCircleRadius != -1 )
8201 const bool testResult { testLinestring( intersection, overlapValue ) };
8203 if ( ! testResult && overlapOrRadiusFilter )
8216 if ( minInscribedCircleRadius != -1 )
8221 bool testResult {
false };
8222 if ( minOverlap != -1 || requireMeasures )
8242 testResult = testLinestring( feat2.
geometry(), overlapValue );
8247 testResult = testPolygon( feat2.
geometry(), radiusValue, overlapValue );
8253 if ( ! testResult && overlapOrRadiusFilter )
8281 const QVariant expResult = subExpression.
evaluate( &subContext );
8283 if ( requireMeasures )
8285 QVariantMap resultRecord;
8286 resultRecord.insert( QStringLiteral(
"id" ), feat2.
id() );
8287 resultRecord.insert( QStringLiteral(
"result" ), expResult );
8289 resultRecord.insert( QStringLiteral(
"overlap" ), overlapValue );
8291 if ( radiusValue != -1 )
8293 resultRecord.insert( QStringLiteral(
"radius" ), radiusValue );
8295 results.append( resultRecord );
8299 results.append( expResult );
8305 results.append( feat2.
id() );
8319 if ( requireMeasures )
8321 if ( sortByMeasure )
8323 std::sort( results.begin(), results.end(), [ sortAscending ](
const QVariant & recordA,
const QVariant & recordB ) ->
bool
8325 return sortAscending ?
8326 recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble()
8327 : recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble();
8331 if ( limit > 0 && results.size() > limit )
8333 results.erase( results.begin() + limit );
8336 if ( ! returnDetails )
8338 QVariantList expResults;
8339 for (
auto it = results.constBegin(); it != results.constEnd(); ++it )
8341 expResults.append( it->toMap().value( QStringLiteral(
"result" ) ) );
8351 QVariantList disjoint_results;
8360 if ( !results.contains( feat2.
id() ) )
8363 disjoint_results.append( subExpression.
evaluate( &subContext ) );
8366 return disjoint_results;
8409 return executeGeomOverlay( values, context, parent,
nullptr,
false, 0,
true );
8418 QMutexLocker locker( &sFunctionsMutex );
8420 QList<QgsExpressionFunction *> &functions = *sFunctions();
8422 if ( functions.isEmpty() )
8460 functions << randFunc;
8464 functions << randfFunc;
8467 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max" ), -1, fcnMax, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8468 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min" ), -1, fcnMin, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8475 <<
new QgsStaticExpressionFunction( QStringLiteral(
"pi" ), 0, fcnPi, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$pi" ) )
8480 <<
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" ) )
8481 <<
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" ) )
8482 <<
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" ) )
8487 <<
new QgsStaticExpressionFunction( QStringLiteral(
"coalesce" ), -1, fcnCoalesce, QStringLiteral(
"Conditionals" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8501 QStringLiteral(
"Aggregates" ),
8510 if ( !node->
args() )
8513 QSet<QString> referencedVars;
8525 return referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() );
8534 if ( !node->
args() )
8535 return QSet<QString>();
8537 QSet<QString> referencedCols;
8538 QSet<QString> referencedVars;
8553 if ( referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() ) )
8556 return referencedCols;
8569 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count" ), aggParams, fcnAggregateCount, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8570 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_distinct" ), aggParams, fcnAggregateCountDistinct, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8571 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_missing" ), aggParams, fcnAggregateCountMissing, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8572 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minimum" ), aggParams, fcnAggregateMin, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8573 <<
new QgsStaticExpressionFunction( QStringLiteral(
"maximum" ), aggParams, fcnAggregateMax, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8574 <<
new QgsStaticExpressionFunction( QStringLiteral(
"sum" ), aggParams, fcnAggregateSum, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8575 <<
new QgsStaticExpressionFunction( QStringLiteral(
"mean" ), aggParams, fcnAggregateMean, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8576 <<
new QgsStaticExpressionFunction( QStringLiteral(
"median" ), aggParams, fcnAggregateMedian, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8577 <<
new QgsStaticExpressionFunction( QStringLiteral(
"stdev" ), aggParams, fcnAggregateStdev, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8578 <<
new QgsStaticExpressionFunction( QStringLiteral(
"range" ), aggParams, fcnAggregateRange, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8579 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minority" ), aggParams, fcnAggregateMinority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8580 <<
new QgsStaticExpressionFunction( QStringLiteral(
"majority" ), aggParams, fcnAggregateMajority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8581 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q1" ), aggParams, fcnAggregateQ1, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8582 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q3" ), aggParams, fcnAggregateQ3, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8583 <<
new QgsStaticExpressionFunction( QStringLiteral(
"iqr" ), aggParams, fcnAggregateIQR, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8584 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min_length" ), aggParams, fcnAggregateMinLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8585 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max_length" ), aggParams, fcnAggregateMaxLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8586 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect" ), aggParams, fcnAggregateCollectGeometry, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8587 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate" ), aggParamsConcat, fcnAggregateStringConcat, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8588 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate_unique" ), aggParamsConcat, fcnAggregateStringConcatUnique, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8589 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array_agg" ), aggParamsArray, fcnAggregateArray, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8594 <<
new QgsStaticExpressionFunction( QStringLiteral(
"now" ), 0, fcnNow, QStringLiteral(
"Date and Time" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$now" ) )
8597 fcnAge, QStringLiteral(
"Date and Time" ) )
8611 fcnMakeDate, QStringLiteral(
"Date and Time" ) )
8615 fcnMakeTime, QStringLiteral(
"Date and Time" ) )
8622 fcnMakeDateTime, QStringLiteral(
"Date and Time" ) )
8630 fcnMakeInterval, QStringLiteral(
"Date and Time" ) )
8655 false, QSet< QString >(),
false, QStringList(), true )
8656 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concat" ), -1, fcnConcat, QStringLiteral(
"String" ), QString(),
false, QSet<QString>(),
false, QStringList(), true )
8674 fcnColorMixRgb, QStringLiteral(
"Color" ) )
8678 fcnColorMix, QStringLiteral(
"Color" ) )
8682 fcnColorRgb, QStringLiteral(
"Color" ) )
8687 fcnColorRgbF, QStringLiteral(
"Color" ) )
8692 fncColorRgba, QStringLiteral(
"Color" ) )
8701 fcnCreateRamp, QStringLiteral(
"Color" ) )
8705 fcnColorHsl, QStringLiteral(
"Color" ) )
8710 fncColorHsla, QStringLiteral(
"Color" ) )
8715 fcnColorHslF, QStringLiteral(
"Color" ) )
8719 fcnColorHsv, QStringLiteral(
"Color" ) )
8724 fncColorHsva, QStringLiteral(
"Color" ) )
8729 fcnColorHsvF, QStringLiteral(
"Color" ) )
8734 fcnColorCmyk, QStringLiteral(
"Color" ) )
8740 fncColorCmyka, QStringLiteral(
"Color" ) )
8746 fcnColorCmykF, QStringLiteral(
"Color" ) )
8749 fncColorPart, QStringLiteral(
"Color" ) )
8752 fncDarker, QStringLiteral(
"Color" ) )
8755 fncLighter, QStringLiteral(
"Color" ) )
8760 fcnBaseFileName, QStringLiteral(
"Files and Paths" ) )
8762 fcnFileSuffix, QStringLiteral(
"Files and Paths" ) )
8764 fcnFileExists, QStringLiteral(
"Files and Paths" ) )
8766 fcnFileName, QStringLiteral(
"Files and Paths" ) )
8768 fcnPathIsFile, QStringLiteral(
"Files and Paths" ) )
8770 fcnPathIsDir, QStringLiteral(
"Files and Paths" ) )
8772 fcnFilePath, QStringLiteral(
"Files and Paths" ) )
8774 fcnFileSize, QStringLiteral(
"Files and Paths" ) )
8777 fcnExif, QStringLiteral(
"Files and Paths" ) )
8779 fcnExifGeoTag, QStringLiteral(
"GeometryGroup" ) )
8783 fcnGenericHash, QStringLiteral(
"Conversions" ) )
8785 fcnHashMd5, QStringLiteral(
"Conversions" ) )
8787 fcnHashSha256, QStringLiteral(
"Conversions" ) )
8791 fcnToBase64, QStringLiteral(
"Conversions" ) )
8793 fcnFromBase64, QStringLiteral(
"Conversions" ) )
8799 geomFunc->setIsStatic(
false );
8800 functions << geomFunc;
8804 functions << areaFunc;
8810 functions << lengthFunc;
8814 functions << perimeterFunc;
8820 fcnRoundness, QStringLiteral(
"GeometryGroup" ) );
8834 QMap< QString, QgsExpressionFunction::FcnEval > geometry_overlay_definitions
8836 { QStringLiteral(
"overlay_intersects" ), fcnGeomOverlayIntersects },
8837 { QStringLiteral(
"overlay_contains" ), fcnGeomOverlayContains },
8838 { QStringLiteral(
"overlay_crosses" ), fcnGeomOverlayCrosses },
8839 { QStringLiteral(
"overlay_equals" ), fcnGeomOverlayEquals },
8840 { QStringLiteral(
"overlay_touches" ), fcnGeomOverlayTouches },
8841 { QStringLiteral(
"overlay_disjoint" ), fcnGeomOverlayDisjoint },
8842 { QStringLiteral(
"overlay_within" ), fcnGeomOverlayWithin },
8844 QMapIterator< QString, QgsExpressionFunction::FcnEval > i( geometry_overlay_definitions );
8845 while ( i.hasNext() )
8862 functions << fcnGeomOverlayFunc;
8875 functions << fcnGeomOverlayNearestFunc;
8888 fcnNodesToPoints, QStringLiteral(
"GeometryGroup" ) )
8890 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect_geometries" ), -1, fcnCollectGeometries, QStringLiteral(
"GeometryGroup" ) )
8895 fcnMakePointM, QStringLiteral(
"GeometryGroup" ) )
8901 fcnMakeTriangle, QStringLiteral(
"GeometryGroup" ) )
8906 fcnMakeCircle, QStringLiteral(
"GeometryGroup" ) )
8913 fcnMakeEllipse, QStringLiteral(
"GeometryGroup" ) )
8919 fcnMakeRegularPolygon, QStringLiteral(
"GeometryGroup" ) )
8923 fcnMakeSquare, QStringLiteral(
"GeometryGroup" ) )
8929 fcnMakeRectangleFrom3Points, QStringLiteral(
"GeometryGroup" ) )
8933#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
8939 }, fcnGeomMakeValid, QStringLiteral(
"GeometryGroup" ) );
8948 functions << xAtFunc;
8953 functions << yAtFunc;
8969 fcnDisjoint, QStringLiteral(
"GeometryGroup" ) )
8972 fcnIntersects, QStringLiteral(
"GeometryGroup" ) )
8975 fcnTouches, QStringLiteral(
"GeometryGroup" ) )
8978 fcnCrosses, QStringLiteral(
"GeometryGroup" ) )
8981 fcnContains, QStringLiteral(
"GeometryGroup" ) )
8984 fcnOverlaps, QStringLiteral(
"GeometryGroup" ) )
8987 fcnWithin, QStringLiteral(
"GeometryGroup" ) )
8991 fcnTranslate, QStringLiteral(
"GeometryGroup" ) )
8996 fcnRotate, QStringLiteral(
"GeometryGroup" ) )
9001 fcnScale, QStringLiteral(
"GeometryGroup" ) )
9012 fcnAffineTransform, QStringLiteral(
"GeometryGroup" ) )
9019 fcnBuffer, QStringLiteral(
"GeometryGroup" ) )
9021 fcnForceRHR, QStringLiteral(
"GeometryGroup" ) )
9023 fcnForcePolygonCW, QStringLiteral(
"GeometryGroup" ) )
9025 fcnForcePolygonCCW, QStringLiteral(
"GeometryGroup" ) )
9035 , fcnTaperedBuffer, QStringLiteral(
"GeometryGroup" ) )
9038 , fcnBufferByM, QStringLiteral(
"GeometryGroup" ) )
9044 fcnOffsetCurve, QStringLiteral(
"GeometryGroup" ) )
9050 fcnSingleSidedBuffer, QStringLiteral(
"GeometryGroup" ) )
9054 fcnExtend, QStringLiteral(
"GeometryGroup" ) )
9063 fcnInteriorRingN, QStringLiteral(
"GeometryGroup" ) )
9066 fcnGeometryN, QStringLiteral(
"GeometryGroup" ) )
9073 }, fcnSharedPaths, QStringLiteral(
"GeometryGroup" ) )
9087 }, fcnTriangularWave, QStringLiteral(
"GeometryGroup" ) )
9096 }, fcnTriangularWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9103 }, fcnSquareWave, QStringLiteral(
"GeometryGroup" ) )
9112 }, fcnSquareWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9119 }, fcnRoundWave, QStringLiteral(
"GeometryGroup" ) )
9128 }, fcnRoundWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9137 }, fcnApplyDashPattern, QStringLiteral(
"GeometryGroup" ) )
9142 }, fcnDensifyByCount, QStringLiteral(
"GeometryGroup" ) )
9147 }, fcnDensifyByDistance, QStringLiteral(
"GeometryGroup" ) )
9159#
if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
9166 fcnOrientedBBox, QStringLiteral(
"GeometryGroup" ) )
9169 fcnMainAngle, QStringLiteral(
"GeometryGroup" ) )
9173 fcnMinimalCircle, QStringLiteral(
"GeometryGroup" ) )
9176 fcnDifference, QStringLiteral(
"GeometryGroup" ) )
9179 fcnDistance, QStringLiteral(
"GeometryGroup" ) )
9182 fcnHausdorffDistance, QStringLiteral(
"GeometryGroup" ) )
9185 fcnIntersection, QStringLiteral(
"GeometryGroup" ) )
9188 fcnSymDifference, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"symDifference" ) )
9191 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
9194 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
9197 fcnGeomToWKT, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"geomToWKT" ) )
9199 fcnGeomToWKB, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false )
9204 fcnTransformGeometry, QStringLiteral(
"GeometryGroup" ) )
9208 fcnExtrude, QStringLiteral(
"GeometryGroup" ), QString() )
9210 fcnGeomIsMultipart, QStringLiteral(
"GeometryGroup" ) )
9212 fcnZMax, QStringLiteral(
"GeometryGroup" ) )
9214 fcnZMin, QStringLiteral(
"GeometryGroup" ) )
9216 fcnMMax, QStringLiteral(
"GeometryGroup" ) )
9218 fcnMMin, QStringLiteral(
"GeometryGroup" ) )
9220 fcnSinuosity, QStringLiteral(
"GeometryGroup" ) )
9222 fcnStraightDistance2d, QStringLiteral(
"GeometryGroup" ) );
9228 fcnOrderParts, QStringLiteral(
"GeometryGroup" ), QString() );
9233 const QList< QgsExpressionNode *> argList = node->
args()->list();
9236 if ( !argNode->isStatic( parent, context ) )
9244 QString expString = argNode->
eval( parent, context ).toString();
9248 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9260 QString
expression = argNode->
eval( parent, context ).toString();
9262 e.prepare( context );
9268 functions << orderPartsFunc;
9273 fcnClosestPoint, QStringLiteral(
"GeometryGroup" ) )
9276 fcnShortestLine, QStringLiteral(
"GeometryGroup" ) )
9281 fcnLineInterpolatePointByM, QStringLiteral(
"GeometryGroup" ) )
9288 fcnLineLocateM, QStringLiteral(
"GeometryGroup" ) )
9301 functions << idFunc;
9305 functions << currentFeatureFunc;
9307 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" ) );
9309 functions << uuidFunc;
9316 fcnGetFeature, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"QgsExpressionUtils::getFeature" ) )
9319 fcnGetFeatureById, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false );
9324 functions << attributesFunc;
9328 functions << representAttributesFunc;
9336 functions << validateFeature;
9345 functions << validateAttribute;
9348 QStringLiteral(
"maptip" ),
9351 QStringLiteral(
"Record and Attributes" ),
9357 functions << maptipFunc;
9360 QStringLiteral(
"display_expression" ),
9362 fcnFeatureDisplayExpression,
9363 QStringLiteral(
"Record and Attributes" ),
9369 functions << displayFunc;
9372 QStringLiteral(
"is_selected" ),
9375 QStringLiteral(
"Record and Attributes" ),
9381 functions << isSelectedFunc;
9385 QStringLiteral(
"num_selected" ),
9388 QStringLiteral(
"Record and Attributes" ),
9396 QStringLiteral(
"sqlite_fetch_and_increment" ),
9404 fcnSqliteFetchAndIncrement,
9405 QStringLiteral(
"Record and Attributes" )
9429 parent->
setEvalErrorString( tr(
"If represent_value is called with 1 parameter, it must be an attribute." ) );
9439 parent->
setEvalErrorString( tr(
"represent_value must be called with exactly 1 or 2 parameters." ) );
9445 functions << representValueFunc;
9451 fcnGetLayerProperty, QStringLiteral(
"Map Layers" ) )
9456 fcnDecodeUri, QStringLiteral(
"Map Layers" ) )
9460 fcnMimeType, QStringLiteral(
"General" ) )
9477 QgsExpressionNode *argNode = node->args()->at( 0 );
9479 if ( !argNode->isStatic( parent, context ) )
9482 const QString varName = argNode->eval( parent, context ).toString();
9483 if ( varName == QLatin1String(
"feature" ) || varName == QLatin1String(
"id" ) || varName == QLatin1String(
"geometry" ) )
9486 const QgsExpressionContextScope *scope = context->activeScopeForVariable( varName );
9487 return scope ? scope->isStatic( varName ) : false;
9495 if ( node && node->
args()->
count() > 0 )
9500 if ( literal->value() == QLatin1String(
"geometry" ) || literal->value() == QLatin1String(
"feature" ) )
9517 QgsExpressionNode *argNode = node->args()->at( 0 );
9519 if ( argNode->isStatic( parent, context ) )
9521 QString expString = argNode->eval( parent, context ).toString();
9523 QgsExpression e( expString );
9525 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9532 functions << evalTemplateFunction;
9540 QgsExpressionNode *argNode = node->args()->at( 0 );
9542 if ( argNode->isStatic( parent, context ) )
9544 QString expString = argNode->eval( parent, context ).toString();
9546 QgsExpression e( expString );
9548 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9556 functions << evalFunc;
9562 const QList< QgsExpressionNode *> argList = node->
args()->list();
9565 if ( !argNode->
isStatic( parent, context ) )
9577 functions << attributeFunc;
9588 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array" ), -1, fcnArray, QStringLiteral(
"Arrays" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
9637 fcnMapPrefixKeys, QStringLiteral(
"Maps" ) )
9639 fcnMapToHtmlTable, QStringLiteral(
"Maps" ) )
9641 fcnMapToHtmlDefinitionList, QStringLiteral(
"Maps" ) )
9643 fcnToFormUrlEncode, QStringLiteral(
"Maps" ) )
9652 *sOwnedFunctions() << func;
9653 *sBuiltinFunctions() << func->name();
9654 sBuiltinFunctions()->append( func->aliases() );
9668 QMutexLocker locker( &sFunctionsMutex );
9669 sFunctions()->append( function );
9670 if ( transferOwnership )
9671 sOwnedFunctions()->append( function );
9686 QMutexLocker locker( &sFunctionsMutex );
9687 sFunctions()->removeAt( fnIdx );
9688 sFunctionIndexMap.clear();
9696 qDeleteAll( *sOwnedFunctions() );
9697 sOwnedFunctions()->clear();
9702 if ( sBuiltinFunctions()->isEmpty() )
9706 return *sBuiltinFunctions();
9713 QStringLiteral(
"Arrays" ) )
9724 if ( args->
count() < 2 )
9727 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9737 QVariantList result;
9739 if ( args->
count() < 2 )
9743 QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9746 std::unique_ptr< QgsExpressionContext > tempContext;
9749 tempContext = std::make_unique< QgsExpressionContext >();
9750 subContext = tempContext.get();
9757 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it, ++i )
9761 result << args->
at( 1 )->
eval( parent, subContext );
9786 if ( args->
count() < 2 )
9790 args->
at( 0 )->
prepare( parent, context );
9794 subContext = *context;
9801 args->
at( 1 )->
prepare( parent, &subContext );
9811 QStringLiteral(
"Arrays" ) )
9822 if ( args->
count() < 2 )
9825 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9835 QVariantList result;
9837 if ( args->
count() < 2 )
9841 const QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9844 std::unique_ptr< QgsExpressionContext > tempContext;
9847 tempContext = std::make_unique< QgsExpressionContext >();
9848 subContext = tempContext.get();
9855 if ( args->
count() >= 3 )
9857 const QVariant limitVar = args->
at( 2 )->
eval( parent, context );
9859 if ( QgsExpressionUtils::isIntSafe( limitVar ) )
9861 limit = limitVar.toInt();
9869 for (
const QVariant &value : array )
9872 if ( args->
at( 1 )->
eval( parent, subContext ).toBool() )
9876 if ( limit > 0 && limit == result.size() )
9876 if ( limit > 0 && limit == result.size() ) {
…}
9903 if ( args->
count() < 2 )
9907 args->
at( 0 )->
prepare( parent, context );
9911 subContext = *context;
9917 args->
at( 1 )->
prepare( parent, &subContext );
9926 QStringLiteral(
"General" ) )
9937 if ( args->
count() < 3 )
9941 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9943 QVariant
name = args->
at( 0 )->
eval( parent, context );
9944 QVariant value = args->
at( 1 )->
eval( parent, context );
9947 appendTemporaryVariable( context,
name.toString(), value );
9948 if ( args->
at( 2 )->
isStatic( parent, context ) )
9950 popTemporaryVariable( context );
9961 if ( args->
count() < 3 )
9965 QVariant
name = args->
at( 0 )->
eval( parent, context );
9966 QVariant value = args->
at( 1 )->
eval( parent, context );
9969 std::unique_ptr< QgsExpressionContext > tempContext;
9970 if ( !updatedContext )
9972 tempContext = std::make_unique< QgsExpressionContext >();
9973 updatedContext = tempContext.get();
9976 appendTemporaryVariable( updatedContext,
name.toString(), value );
9977 result = args->
at( 2 )->
eval( parent, updatedContext );
9980 popTemporaryVariable( updatedContext );
10001 if ( args->
count() < 3 )
10006 QVariant value = args->
at( 1 )->
prepare( parent, context );
10009 std::unique_ptr< QgsExpressionContext > tempContext;
10010 if ( !updatedContext )
10012 tempContext = std::make_unique< QgsExpressionContext >();
10013 updatedContext = tempContext.get();
10016 appendTemporaryVariable( updatedContext,
name.toString(), value );
10017 args->
at( 2 )->
prepare( parent, updatedContext );
10020 popTemporaryVariable( updatedContext );
10025void QgsWithVariableExpressionFunction::popTemporaryVariable(
const QgsExpressionContext *context )
const
10028 delete updatedContext->
popScope();
10031void 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...
@ GeometryCollection
GeometryCollection.
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).
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.
static QgsGeometry fromMultiPolylineXY(const QgsMultiPolylineXY &multiline)
Creates a new geometry from a QgsMultiPolylineXY object.
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.
static QgsGeometry fromMultiPointXY(const QgsMultiPointXY &multipoint)
Creates a new geometry from a QgsMultiPointXY object.
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 ...
static QgsGeometry fromMultiPolygonXY(const QgsMultiPolygonXY &multipoly)
Creates a new geometry from a QgsMultiPolygonXY.
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, and 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, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
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.
void grow(double delta)
Grows the rectangle in place by the specified amount.
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< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
QVector< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
QLineF segment(int index, QRectF rect, double radius)
const QgsCoordinateReferenceSystem & crs
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.