68#include <QMimeDatabase>
69#include <QProcessEnvironment>
70#include <QCryptographicHash>
71#include <QRegularExpression>
94 QVariantList argValues;
98 const QList< QgsExpressionNode * > argList = args->
list();
99 argValues.reserve( argList.size() );
106 v = QVariant::fromValue( n );
110 v = n->eval( parent, context );
112 bool defaultParamIsNull = mParameterList.count() > arg && mParameterList.at( arg ).optional() && !mParameterList.at( arg ).defaultValue().isValid();
113 if ( QgsExpressionUtils::isNull( v ) && !defaultParamIsNull && !
handlesNull() )
116 argValues.append( v );
121 return func( argValues, context, parent, node );
132 return QStringList();
159 return mGroups.isEmpty() ? false : mGroups.contains( QStringLiteral(
"deprecated" ) );
164 return ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 );
176 const QString &group,
177 const QString &helpText,
181 const QStringList &aliases,
185 , mAliases( aliases )
186 , mUsesGeometry( false )
187 , mUsesGeometryFunc( usesGeometry )
188 , mReferencedColumnsFunc( referencedColumns )
200 if ( mUsesGeometryFunc )
201 return mUsesGeometryFunc( node );
203 return mUsesGeometry;
213 if ( mReferencedColumnsFunc )
214 return mReferencedColumnsFunc( node );
216 return mReferencedColumns;
222 return mIsStaticFunc( node, parent, context );
230 return mPrepareFunc( node, parent, context );
242 mIsStaticFunc =
nullptr;
248 mPrepareFunc = prepareFunc;
253 if ( node && node->
args() )
255 const QList< QgsExpressionNode * > argList = node->
args()->
list();
258 if ( !argNode->isStatic( parent, context ) )
268 double start = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
269 double stop = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
270 double step = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
272 if ( step == 0.0 || ( step > 0.0 && start > stop ) || ( step < 0.0 && start < stop ) )
279 double current = start + step;
280 while ( ( ( step > 0.0 && current <= stop ) || ( step < 0.0 && current >= stop ) ) && length <= 1000000 )
295 const QString name = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
297 if ( name == QLatin1String(
"feature" ) )
299 return context->
hasFeature() ? QVariant::fromValue( context->
feature() ) : QVariant();
301 else if ( name == QLatin1String(
"id" ) )
303 return context->
hasFeature() ? QVariant::fromValue( context->
feature().
id() ) : QVariant();
305 else if ( name == QLatin1String(
"geometry" ) )
321 QString templateString = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
330 QString expString = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
332 return expression.evaluate( context );
337 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
338 return QVariant( std::sqrt( x ) );
343 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
344 return QVariant( std::fabs( val ) );
349 double deg = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
350 return ( deg * M_PI ) / 180;
354 double rad = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
355 return ( 180 * rad ) / M_PI;
359 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
360 return QVariant( std::sin( x ) );
364 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
365 return QVariant( std::cos( x ) );
369 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
370 return QVariant( std::tan( x ) );
374 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
375 return QVariant( std::asin( x ) );
379 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
380 return QVariant( std::acos( x ) );
384 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
385 return QVariant( std::atan( x ) );
389 double y = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
390 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
391 return QVariant( std::atan2( y, x ) );
395 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
396 return QVariant( std::exp( x ) );
400 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
403 return QVariant( std::log( x ) );
407 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
410 return QVariant( log10( x ) );
414 double b = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
415 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
416 if ( x <= 0 || b <= 0 )
418 return QVariant( std::log( x ) / std::log( b ) );
422 double min = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
423 double max = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
427 std::random_device rd;
428 std::mt19937_64 generator( rd() );
430 if ( !QgsExpressionUtils::isNull( values.at( 2 ) ) )
433 if ( QgsExpressionUtils::isIntSafe( values.at( 2 ) ) )
436 seed = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
441 QString seedStr = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
442 std::hash<std::string> hasher;
443 seed = hasher( seedStr.toStdString() );
445 generator.seed( seed );
449 double f =
static_cast< double >( generator() ) /
static_cast< double >( std::mt19937_64::max() );
450 return QVariant( min + f * ( max - min ) );
454 qlonglong min = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
455 qlonglong max = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
459 std::random_device rd;
460 std::mt19937_64 generator( rd() );
462 if ( !QgsExpressionUtils::isNull( values.at( 2 ) ) )
465 if ( QgsExpressionUtils::isIntSafe( values.at( 2 ) ) )
468 seed = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
473 QString seedStr = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
474 std::hash<std::string> hasher;
475 seed = hasher( seedStr.toStdString() );
477 generator.seed( seed );
480 qint64 randomInteger = min + ( generator() % ( max - min + 1 ) );
481 if ( randomInteger > std::numeric_limits<int>::max() || randomInteger < -std::numeric_limits<int>::max() )
482 return QVariant( randomInteger );
485 return QVariant(
int( randomInteger ) );
490 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
491 double domainMin = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
492 double domainMax = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
493 double rangeMin = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
494 double rangeMax = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
496 if ( domainMin >= domainMax )
498 parent->
setEvalErrorString( QObject::tr(
"Domain max must be greater than domain min" ) );
503 if ( val >= domainMax )
507 else if ( val <= domainMin )
513 double m = ( rangeMax - rangeMin ) / ( domainMax - domainMin );
514 double c = rangeMin - ( domainMin * m );
517 return QVariant( m * val +
c );
522 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
523 double domainMin = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
524 double domainMax = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
525 double rangeMin = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
526 double rangeMax = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
527 double exponent = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
529 if ( domainMin >= domainMax )
531 parent->
setEvalErrorString( QObject::tr(
"Domain max must be greater than domain min" ) );
541 if ( val >= domainMax )
545 else if ( val <= domainMin )
551 return QVariant( ( ( rangeMax - rangeMin ) / std::pow( domainMax - domainMin, exponent ) ) * std::pow( val - domainMin, exponent ) + rangeMin );
556 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
557 double domainMin = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
558 double domainMax = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
559 double rangeMin = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
560 double rangeMax = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
561 double exponent = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
563 if ( domainMin >= domainMax )
565 parent->
setEvalErrorString( QObject::tr(
"Domain max must be greater than domain min" ) );
575 if ( val >= domainMax )
579 else if ( val <= domainMin )
585 double ratio = ( std::pow( exponent, val - domainMin ) - 1 ) / ( std::pow( exponent, domainMax - domainMin ) - 1 );
586 return QVariant( ( rangeMax - rangeMin ) * ratio + rangeMin );
592 double maxVal = std::numeric_limits<double>::quiet_NaN();
593 for (
const QVariant &val : values )
596 if ( std::isnan( maxVal ) )
600 else if ( !std::isnan( testVal ) )
602 maxVal = std::max( maxVal, testVal );
606 if ( !std::isnan( maxVal ) )
608 result = QVariant( maxVal );
616 double minVal = std::numeric_limits<double>::quiet_NaN();
617 for (
const QVariant &val : values )
620 if ( std::isnan( minVal ) )
624 else if ( !std::isnan( testVal ) )
626 minVal = std::min( minVal, testVal );
630 if ( !std::isnan( minVal ) )
632 result = QVariant( minVal );
644 QVariant value = node->
eval( parent, context );
649 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( value, context, parent );
653 parent->
setEvalErrorString( QObject::tr(
"Cannot find layer with name or ID '%1'" ).arg( value.toString() ) );
658 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
660 value = node->
eval( parent, context );
666 parent->
setEvalErrorString( QObject::tr(
"No such aggregate '%1'" ).arg( value.toString() ) );
671 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
673 QString subExpression = node->
dump();
677 if ( values.count() > 3 )
679 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
682 if ( !nl || nl->value().isValid() )
687 if ( values.count() > 4 )
689 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
691 value = node->
eval( parent, context );
698 if ( values.count() > 5 )
700 node = QgsExpressionUtils::getNode( values.at( 5 ), parent );
703 if ( !nl || nl->value().isValid() )
705 orderBy = node->
dump();
710 QString aggregateError;
718 const QSet< QString > filterVars = filterExp.referencedVariables();
719 const QSet< QString > subExpVars = subExp.referencedVariables();
720 QSet<QString> allVars = filterVars + subExpVars;
722 bool isStatic =
true;
723 if ( filterVars.contains( QStringLiteral(
"parent" ) )
724 || filterVars.contains( QString() )
725 || subExpVars.contains( QStringLiteral(
"parent" ) )
726 || subExpVars.contains( QString() ) )
732 for (
const QString &varName : allVars )
735 if ( scope && !scope->
isStatic( varName ) )
743 if ( isStatic && ! parameters.
orderBy.isEmpty() )
745 for (
const auto &orderByClause : std::as_const( parameters.orderBy ) )
748 if ( orderByExpression.referencedVariables().contains( QStringLiteral(
"parent" ) ) || orderByExpression.referencedVariables().contains( QString() ) )
759 const QString contextHash = context->
uniqueHash( ok, allVars );
762 cacheKey = QStringLiteral(
"aggfcn:%1:%2:%3:%4:%5:%6" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter,
763 orderBy, contextHash );
768 cacheKey = QStringLiteral(
"aggfcn:%1:%2:%3:%4:%5" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter, orderBy );
779 subContext.appendScope( subScope );
780 result = vl->aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &aggregateError );
782 if ( ok && !cacheKey.isEmpty() )
792 result = vl->aggregate( aggregate, subExpression, parameters,
nullptr, &ok,
nullptr,
nullptr, &aggregateError );
796 if ( !aggregateError.isEmpty() )
797 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, aggregateError ) );
799 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
810 parent->
setEvalErrorString( QObject::tr(
"Cannot use relation aggregate function in this context" ) );
818 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
822 parent->
setEvalErrorString( QObject::tr(
"Cannot use relation aggregate function in this context" ) );
831 QVariant value = node->
eval( parent, context );
833 QString relationId = value.toString();
840 if ( relations.isEmpty() || relations.at( 0 ).referencedLayer() != vl )
842 parent->
setEvalErrorString( QObject::tr(
"Cannot find relation with id '%1'" ).arg( relationId ) );
847 relation = relations.at( 0 );
854 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
856 value = node->
eval( parent, context );
862 parent->
setEvalErrorString( QObject::tr(
"No such aggregate '%1'" ).arg( value.toString() ) );
867 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
869 QString subExpression = node->
dump();
873 if ( values.count() > 3 )
875 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
877 value = node->
eval( parent, context );
884 if ( values.count() > 4 )
886 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
889 if ( !nl || nl->value().isValid() )
891 orderBy = node->
dump();
902 const QString cacheKey = QStringLiteral(
"relagg:%1%:%2:%3:%4:%5:%6" ).arg( relationId, vl->id(),
903 QString::number(
static_cast< int >( aggregate ) ),
916 result = childLayer->
aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &error );
920 if ( !error.isEmpty() )
921 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, error ) );
923 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
937 parent->
setEvalErrorString( QObject::tr(
"Cannot use aggregate function in this context" ) );
945 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
949 parent->
setEvalErrorString( QObject::tr(
"Cannot use aggregate function in this context" ) );
958 QString subExpression = node->
dump();
962 if ( values.count() > 1 )
964 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
967 if ( !nl || nl->value().isValid() )
968 groupBy = node->
dump();
972 if ( values.count() > 2 )
974 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
977 if ( !nl || nl->value().isValid() )
983 if ( orderByPos >= 0 && values.count() > orderByPos )
985 node = QgsExpressionUtils::getNode( values.at( orderByPos ), parent );
988 if ( !nl || nl->value().isValid() )
990 orderBy = node->
dump();
998 if ( !groupBy.isEmpty() )
1001 QVariant groupByValue = groupByExp.evaluate( context );
1002 QString groupByClause = QStringLiteral(
"%1 %2 %3" ).arg( groupBy,
1005 if ( !parameters.
filter.isEmpty() )
1006 parameters.
filter = QStringLiteral(
"(%1) AND (%2)" ).arg( parameters.
filter, groupByClause );
1008 parameters.
filter = groupByClause;
1014 bool isStatic =
true;
1015 const QSet<QString> refVars = filterExp.referencedVariables() + subExp.referencedVariables();
1016 for (
const QString &varName : refVars )
1019 if ( scope && !scope->
isStatic( varName ) )
1030 const QString contextHash = context->
uniqueHash( ok, refVars );
1033 cacheKey = QStringLiteral(
"agg:%1:%2:%3:%4:%5:%6" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter,
1034 orderBy, contextHash );
1039 cacheKey = QStringLiteral(
"agg:%1:%2:%3:%4:%5" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter, orderBy );
1051 subContext.appendScope( subScope );
1053 result = vl->aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &error );
1057 if ( !error.isEmpty() )
1058 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, error ) );
1060 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
1165 if ( values.count() > 3 )
1167 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
1169 QVariant value = node->
eval( parent, context );
1171 parameters.
delimiter = value.toString();
1182 if ( values.count() > 3 )
1184 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
1186 QVariant value = node->
eval( parent, context );
1188 parameters.
delimiter = value.toString();
1204 QVariant scale = context->
variable( QStringLiteral(
"map_scale" ) );
1209 const double v = scale.toDouble( &ok );
1217 double minValue = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1218 double testValue = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1219 double maxValue = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1222 if ( testValue <= minValue )
1224 return QVariant( minValue );
1226 else if ( testValue >= maxValue )
1228 return QVariant( maxValue );
1232 return QVariant( testValue );
1238 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1239 return QVariant( std::floor( x ) );
1244 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1245 return QVariant( std::ceil( x ) );
1250 const QVariant value = values.at( 0 );
1251 if ( QgsExpressionUtils::isNull( value.isValid() ) )
1253 return QVariant(
false );
1255 else if ( value.userType() == QMetaType::QString )
1258 return QVariant( !value.toString().isEmpty() );
1260 else if ( QgsExpressionUtils::isList( value ) )
1262 return !value.toList().isEmpty();
1264 return QVariant( value.toBool() );
1268 return QVariant( QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) );
1272 return QVariant( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) );
1276 return QVariant( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ) );
1281 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1282 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1283 if ( format.isEmpty() && !language.isEmpty() )
1285 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to DateTime when the language is specified" ) );
1286 return QVariant( QDateTime() );
1289 if ( format.isEmpty() && language.isEmpty() )
1290 return QVariant( QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent ) );
1292 QString datetimestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1293 QLocale locale = QLocale();
1294 if ( !language.isEmpty() )
1296 locale = QLocale( language );
1299 QDateTime datetime = locale.toDateTime( datetimestring, format );
1300 if ( !datetime.isValid() )
1302 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to DateTime" ).arg( datetimestring ) );
1303 datetime = QDateTime();
1305 return QVariant( datetime );
1310 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1311 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1312 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1314 const QDate date( year, month, day );
1315 if ( !date.isValid() )
1317 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1320 return QVariant( date );
1325 const int hours = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1326 const int minutes = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1327 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1329 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1330 if ( !time.isValid() )
1332 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1335 return QVariant( time );
1340 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1341 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1342 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1343 const int hours = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
1344 const int minutes = QgsExpressionUtils::getIntValue( values.at( 4 ), parent );
1345 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1347 const QDate date( year, month, day );
1348 if ( !date.isValid() )
1350 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1353 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1354 if ( !time.isValid() )
1356 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1359 return QVariant( QDateTime( date, time ) );
1364 const double years = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1365 const double months = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1366 const double weeks = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1367 const double days = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
1368 const double hours = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
1369 const double minutes = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1370 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
1372 return QVariant::fromValue(
QgsInterval( years, months, weeks, days, hours, minutes, seconds ) );
1377 for (
const QVariant &value : values )
1388 const QVariant val1 = values.at( 0 );
1389 const QVariant val2 = values.at( 1 );
1399 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1400 return QVariant( str.toLower() );
1404 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1405 return QVariant( str.toUpper() );
1409 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1410 QStringList elems = str.split(
' ' );
1411 for (
int i = 0; i < elems.size(); i++ )
1413 if ( elems[i].size() > 1 )
1414 elems[i] = elems[i].at( 0 ).toUpper() + elems[i].mid( 1 ).toLower();
1416 return QVariant( elems.join( QLatin1Char(
' ' ) ) );
1421 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1422 return QVariant( str.trimmed() );
1427 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1429 const QString characters = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1431 const QRegularExpression re( QStringLiteral(
"^([%1]*)" ).arg( QRegularExpression::escape( characters ) ) );
1432 str.replace( re, QString() );
1433 return QVariant( str );
1438 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1440 const QString characters = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1442 const QRegularExpression re( QStringLiteral(
"([%1]*)$" ).arg( QRegularExpression::escape( characters ) ) );
1443 str.replace( re, QString() );
1444 return QVariant( str );
1449 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1450 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1456 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1457 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1463 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1464 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1466 return ( dist < 0 ? QVariant() : QVariant(
QgsStringUtils::hammingDistance( string1, string2, true ) ) );
1471 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1477 QChar character = QChar( QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent ) );
1478 return QVariant( QString( character ) );
1483 QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1485 if ( value.isEmpty() )
1490 int res = value.at( 0 ).unicode();
1491 return QVariant( res );
1496 if ( values.length() == 2 || values.length() == 3 )
1498 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1499 qlonglong wrap = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1501 QString customdelimiter = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1514 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent,
true );
1518 return QVariant( geom.
length() );
1524 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1525 return QVariant( str.length() );
1530 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
1535 double totalLength = 0;
1538 if (
const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( *it ) )
1540 totalLength += line->length3D();
1544 std::unique_ptr< QgsLineString > segmentized( qgsgeometry_cast< const QgsCurve * >( *it )->curveToLine() );
1545 totalLength += segmentized->length3D();
1555 const QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1556 const qlonglong number = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1557 return string.repeated( std::max(
static_cast< int >( number ), 0 ) );
1562 if ( values.count() == 2 && values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
1564 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1565 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
1566 QVector< QPair< QString, QString > > mapItems;
1568 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
1570 mapItems.append( qMakePair( it.key(), it.value().toString() ) );
1574 std::sort( mapItems.begin(),
1576 [](
const QPair< QString, QString > &pair1,
1577 const QPair< QString, QString > &pair2 )
1579 return ( pair1.first.length() > pair2.first.length() );
1582 for (
auto it = mapItems.constBegin(); it != mapItems.constEnd(); ++it )
1584 str = str.replace( it->first, it->second );
1587 return QVariant( str );
1589 else if ( values.count() == 3 )
1591 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1592 QVariantList before;
1594 bool isSingleReplacement =
false;
1596 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).userType() != QMetaType::Type::QStringList )
1598 before = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1602 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
1605 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
1607 after = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1608 isSingleReplacement =
true;
1612 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
1615 if ( !isSingleReplacement && before.length() != after.length() )
1617 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
1621 for (
int i = 0; i < before.length(); i++ )
1623 str = str.replace( before.at( i ).toString(), after.at( isSingleReplacement ? 0 : i ).toString() );
1626 return QVariant( str );
1630 parent->
setEvalErrorString( QObject::tr(
"Function replace requires 2 or 3 arguments" ) );
1637 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1638 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1639 QString after = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1641 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1642 if ( !re.isValid() )
1644 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1647 return QVariant( str.replace( re, after ) );
1652 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1653 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1655 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1656 if ( !re.isValid() )
1658 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1661 return QVariant( ( str.indexOf( re ) + 1 ) );
1666 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1667 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1668 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1670 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1671 if ( !re.isValid() )
1673 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1677 QRegularExpressionMatch matches = re.match( str );
1678 if ( matches.hasMatch() )
1681 QStringList list = matches.capturedTexts();
1684 for ( QStringList::const_iterator it = ++list.constBegin(); it != list.constEnd(); ++it )
1686 array += ( !( *it ).isEmpty() ) ? *it : empty;
1689 return QVariant( array );
1699 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1700 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1702 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1703 if ( !re.isValid() )
1705 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1710 QRegularExpressionMatch match = re.match( str );
1711 if ( match.hasMatch() )
1714 if ( match.lastCapturedIndex() > 0 )
1717 return QVariant( match.captured( 1 ) );
1722 return QVariant( match.captured( 0 ) );
1727 return QVariant(
"" );
1733 QString uuid = QUuid::createUuid().toString();
1734 if ( values.at( 0 ).toString().compare( QStringLiteral(
"WithoutBraces" ), Qt::CaseInsensitive ) == 0 )
1735 uuid = QUuid::createUuid().toString( QUuid::StringFormat::WithoutBraces );
1736 else if ( values.at( 0 ).toString().compare( QStringLiteral(
"Id128" ), Qt::CaseInsensitive ) == 0 )
1737 uuid = QUuid::createUuid().toString( QUuid::StringFormat::Id128 );
1743 if ( !values.at( 0 ).isValid() || !values.at( 1 ).isValid() )
1746 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1747 int from = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1750 if ( values.at( 2 ).isValid() )
1751 len = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
1757 from = str.size() + from;
1763 else if ( from > 0 )
1771 len = str.size() + len - from;
1778 return QVariant( str.mid( from, len ) );
1783 return QVariant( f.
id() );
1788 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1789 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
1790 bool foundLayer =
false;
1791 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, geom](
QgsMapLayer * mapLayer )
1793 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer * >( mapLayer );
1794 if ( !layer || !layer->dataProvider() )
1796 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1800 if ( bandNb < 1 || bandNb > layer->bandCount() )
1802 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster band number." ) );
1808 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid point geometry." ) );
1816 if ( multiPoint.count() == 1 )
1818 point = multiPoint[0];
1827 double value = layer->dataProvider()->sample( point, bandNb );
1828 return std::isnan( value ) ? QVariant() : value;
1834 parent->
setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1845 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1846 const double value = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1848 bool foundLayer =
false;
1849 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, value](
QgsMapLayer * mapLayer )-> QVariant
1851 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer *>( mapLayer );
1852 if ( !layer || !layer->dataProvider() )
1854 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1858 if ( bandNb < 1 || bandNb > layer->bandCount() )
1860 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster band number." ) );
1864 if ( std::isnan( value ) )
1866 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster value." ) );
1870 if ( ! layer->dataProvider()->attributeTable( bandNb ) )
1875 const QVariantList data = layer->dataProvider()->attributeTable( bandNb )->row( value );
1876 if ( data.isEmpty() )
1882 const QList<QgsRasterAttributeTable::Field> fields { layer->dataProvider()->attributeTable( bandNb )->fields() };
1883 for (
int idx = 0; idx < static_cast<int>( fields.count( ) ) && idx < static_cast<int>( data.count() ); ++idx )
1886 if ( field.isColor() || field.isRamp() )
1890 result.insert( fields.at( idx ).name, data.at( idx ) );
1898 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1919 if ( values.size() == 1 )
1921 attr = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1924 else if ( values.size() == 2 )
1926 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
1927 attr = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1931 parent->
setEvalErrorString( QObject::tr(
"Function `attribute` requires one or two parameters. %n given.",
nullptr, values.length() ) );
1940 QString table { R
"html(
1943 <tr><th>%1</th></tr>
1946 <tr><td>%2</td></tr>
1950 if ( values.size() == 1 )
1952 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1956 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_table` requires one parameter. %n given.",
nullptr, values.length() ) );
1960 if ( dict.isEmpty() )
1965 QStringList headers;
1968 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
1970 headers.push_back( it.key().toHtmlEscaped() );
1971 cells.push_back( it.value().toString( ).toHtmlEscaped() );
1974 return table.arg( headers.join( QLatin1String(
"</th><th>" ) ), cells.join( QLatin1String(
"</td><td>" ) ) );
1979 QString table { R
"html(
1984 if ( values.size() == 1 )
1986 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1990 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_dl` requires one parameter. %n given.",
nullptr, values.length() ) );
1994 if ( dict.isEmpty() )
2001 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
2003 rows.append( QStringLiteral(
"<dt>%1</dt><dd>%2</dd>" ).arg( it.key().toHtmlEscaped(), it.value().toString().toHtmlEscaped() ) );
2006 return table.arg( rows );
2014 layer = context->
variable( QStringLiteral(
"layer" ) );
2019 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
2021 layer = node->
eval( parent, context );
2032 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2036 const QString strength = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).toLower();
2037 if ( strength == QLatin1String(
"hard" ) )
2041 else if ( strength == QLatin1String(
"soft" ) )
2046 bool foundLayer =
false;
2047 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
2049 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2052 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2058 for (
int i = 0; i < fields.
size(); i++ )
2073 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2085 layer = context->
variable( QStringLiteral(
"layer" ) );
2090 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
2092 layer = node->
eval( parent, context );
2103 feature = QgsExpressionUtils::getFeature( values.at( 2 ), parent );
2107 const QString strength = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).toLower();
2108 if ( strength == QLatin1String(
"hard" ) )
2112 else if ( strength == QLatin1String(
"soft" ) )
2117 const QString attributeName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2119 bool foundLayer =
false;
2120 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, attributeName, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
2122 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2129 if ( fieldIndex == -1 )
2131 parent->
setEvalErrorString( QObject::tr(
"The attribute name did not match any field for the given feature" ) );
2142 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2158 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2163 for (
int i = 0; i < fields.
count(); ++i )
2177 if ( values.isEmpty() )
2180 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2182 else if ( values.size() == 1 )
2184 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2185 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2187 else if ( values.size() == 2 )
2189 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2190 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2194 parent->
setEvalErrorString( QObject::tr(
"Function `represent_attributes` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2201 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: layer could not be resolved." ) );
2207 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: feature could not be resolved." ) );
2213 for (
int fieldIndex = 0; fieldIndex < fields.
count(); ++fieldIndex )
2215 const QString fieldName { fields.
at( fieldIndex ).
name() };
2216 const QVariant attributeVal = feature.
attribute( fieldIndex );
2217 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer->
id(), fieldName, attributeVal.toString() );
2220 result.insert( fieldName, context->
cachedValue( cacheValueKey ) );
2229 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer->
id(), fieldName );
2241 QString value( fieldFormatter->
representValue( layer, fieldIndex, setup.
config(), cache, attributeVal ) );
2243 result.insert( fields.
at( fieldIndex ).
name(), value );
2259 bool evaluate =
true;
2263 if ( values.isEmpty() )
2266 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2268 else if ( values.size() == 1 )
2270 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2271 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2273 else if ( values.size() == 2 )
2275 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2276 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2278 else if ( values.size() == 3 )
2280 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2281 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2282 evaluate = values.value( 2 ).toBool();
2288 parent->
setEvalErrorString( QObject::tr(
"Function `maptip` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2292 parent->
setEvalErrorString( QObject::tr(
"Function `display` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2324 subContext.setFeature( feature );
2333 exp.prepare( &subContext );
2334 return exp.evaluate( &subContext ).toString();
2340 return fcnCoreFeatureMaptipDisplay( values, context, parent,
false );
2345 return fcnCoreFeatureMaptipDisplay( values, context, parent,
true );
2352 if ( values.isEmpty() )
2355 layer = context->
variable( QStringLiteral(
"layer" ) );
2357 else if ( values.size() == 1 )
2359 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2360 layer = context->
variable( QStringLiteral(
"layer" ) );
2362 else if ( values.size() == 2 )
2364 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2365 layer = values.at( 0 );
2369 parent->
setEvalErrorString( QObject::tr(
"Function `is_selected` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2373 bool foundLayer =
false;
2374 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [feature](
QgsMapLayer * mapLayer ) -> QVariant
2376 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2377 if ( !layer || !feature.
isValid() )
2394 if ( values.isEmpty() )
2395 layer = context->
variable( QStringLiteral(
"layer" ) );
2396 else if ( values.count() == 1 )
2397 layer = values.at( 0 );
2400 parent->
setEvalErrorString( QObject::tr(
"Function `num_selected` requires no more than one parameter. %n given.",
nullptr, values.length() ) );
2404 bool foundLayer =
false;
2405 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [](
QgsMapLayer * mapLayer ) -> QVariant
2407 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2423 static QMap<QString, qlonglong> counterCache;
2424 QVariant functionResult;
2426 auto fetchAndIncrementFunc = [ values, parent, &functionResult ](
QgsMapLayer * mapLayer,
const QString & databaseArgument )
2430 const QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( mapLayer );
2435 database = decodedUri.value( QStringLiteral(
"path" ) ).toString();
2436 if ( database.isEmpty() )
2438 parent->
setEvalErrorString( QObject::tr(
"Could not extract file path from layer `%1`." ).arg( layer->
name() ) );
2443 database = databaseArgument;
2446 const QString table = values.at( 1 ).toString();
2447 const QString idColumn = values.at( 2 ).toString();
2448 const QString filterAttribute = values.at( 3 ).toString();
2449 const QVariant filterValue = values.at( 4 ).toString();
2450 const QVariantMap defaultValues = values.at( 5 ).toMap();
2456 if ( sqliteDb.
open_v2( database, SQLITE_OPEN_READWRITE,
nullptr ) != SQLITE_OK )
2459 functionResult = QVariant();
2463 QString errorMessage;
2464 QString currentValSql;
2466 qlonglong nextId = 0;
2467 bool cachedMode =
false;
2468 bool valueRetrieved =
false;
2470 QString cacheString = QStringLiteral(
"%1:%2:%3:%4:%5" ).arg( database, table, idColumn, filterAttribute, filterValue.toString() );
2477 auto cachedCounter = counterCache.find( cacheString );
2479 if ( cachedCounter != counterCache.end() )
2481 qlonglong &cachedValue = cachedCounter.value();
2482 nextId = cachedValue;
2484 cachedValue = nextId;
2485 valueRetrieved =
true;
2490 if ( !cachedMode || !valueRetrieved )
2492 int result = SQLITE_ERROR;
2495 if ( !filterAttribute.isNull() )
2500 sqliteStatement = sqliteDb.
prepare( currentValSql, result );
2502 if ( result == SQLITE_OK )
2505 if ( sqliteStatement.
step() == SQLITE_ROW )
2511 if ( cachedMode && result == SQLITE_OK )
2513 counterCache.insert( cacheString, nextId );
2517 counterCache.remove( cacheString );
2520 valueRetrieved =
true;
2524 if ( valueRetrieved )
2533 if ( !filterAttribute.isNull() )
2539 for ( QVariantMap::const_iterator iter = defaultValues.constBegin(); iter != defaultValues.constEnd(); ++iter )
2542 vals << iter.value().toString();
2545 upsertSql += QLatin1String(
" (" ) + cols.join(
',' ) +
')';
2546 upsertSql += QLatin1String(
" VALUES " );
2547 upsertSql +=
'(' + vals.join(
',' ) +
')';
2549 int result = SQLITE_ERROR;
2553 if ( transaction->
executeSql( upsertSql, errorMessage ) )
2560 result = sqliteDb.
exec( upsertSql, errorMessage );
2562 if ( result == SQLITE_OK )
2564 functionResult = QVariant( nextId );
2569 parent->
setEvalErrorString( QStringLiteral(
"Could not increment value: SQLite error: \"%1\" (%2)." ).arg( errorMessage, QString::number( result ) ) );
2570 functionResult = QVariant();
2575 functionResult = QVariant();
2578 bool foundLayer =
false;
2579 QgsExpressionUtils::executeLambdaForMapLayer( values.at( 0 ), context, parent, [&fetchAndIncrementFunc](
QgsMapLayer * layer )
2581 fetchAndIncrementFunc( layer, QString() );
2585 const QString databasePath = values.at( 0 ).toString();
2588 fetchAndIncrementFunc(
nullptr, databasePath );
2592 return functionResult;
2605 QString definition = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2610 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to cordinate reference system" ).arg( definition ) );
2613 return QVariant::fromValue(
crs );
2619 for (
const QVariant &value : values )
2622 concat += QgsExpressionUtils::getStringValue( value, parent );
2629 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2630 return string.indexOf( QgsExpressionUtils::getStringValue( values.at( 1 ), parent ) ) + 1;
2635 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2636 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2637 return string.right( pos );
2642 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2643 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2644 return string.left( pos );
2649 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2650 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2651 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2652 return string.leftJustified( length, fill.at( 0 ),
true );
2657 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2658 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2659 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2660 return string.rightJustified( length, fill.at( 0 ),
true );
2665 if ( values.size() < 1 )
2667 parent->
setEvalErrorString( QObject::tr(
"Function format requires at least 1 argument" ) );
2671 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2672 for (
int n = 1; n < values.length(); n++ )
2674 string =
string.arg( QgsExpressionUtils::getStringValue( values.at( n ), parent ) );
2682 return QVariant( QDateTime::currentDateTime() );
2687 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2688 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2689 if ( format.isEmpty() && !language.isEmpty() )
2691 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Date when the language is specified" ) );
2692 return QVariant( QDate() );
2695 if ( format.isEmpty() && language.isEmpty() )
2696 return QVariant( QgsExpressionUtils::getDateValue( values.at( 0 ), parent ) );
2698 QString datestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2699 QLocale locale = QLocale();
2700 if ( !language.isEmpty() )
2702 locale = QLocale( language );
2705 QDate date = locale.toDate( datestring, format );
2706 if ( !date.isValid() )
2708 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Date" ).arg( datestring ) );
2711 return QVariant( date );
2716 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2717 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2718 if ( format.isEmpty() && !language.isEmpty() )
2720 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Time when the language is specified" ) );
2721 return QVariant( QTime() );
2724 if ( format.isEmpty() && language.isEmpty() )
2725 return QVariant( QgsExpressionUtils::getTimeValue( values.at( 0 ), parent ) );
2727 QString timestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2728 QLocale locale = QLocale();
2729 if ( !language.isEmpty() )
2731 locale = QLocale( language );
2734 QTime time = locale.toTime( timestring, format );
2735 if ( !time.isValid() )
2737 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Time" ).arg( timestring ) );
2740 return QVariant( time );
2745 return QVariant::fromValue( QgsExpressionUtils::getInterval( values.at( 0 ), parent ) );
2754 double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
2755 QString axis = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2756 int precision = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
2758 QString formatString;
2759 if ( values.count() > 3 )
2760 formatString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
2763 if ( formatString.compare( QLatin1String(
"suffix" ), Qt::CaseInsensitive ) == 0 )
2767 else if ( formatString.compare( QLatin1String(
"aligned" ), Qt::CaseInsensitive ) == 0 )
2771 else if ( ! formatString.isEmpty() )
2773 parent->
setEvalErrorString( QObject::tr(
"Invalid formatting parameter: '%1'. It must be empty, or 'suffix' or 'aligned'." ).arg( formatString ) );
2777 if ( axis.compare( QLatin1String(
"x" ), Qt::CaseInsensitive ) == 0 )
2781 else if ( axis.compare( QLatin1String(
"y" ), Qt::CaseInsensitive ) == 0 )
2787 parent->
setEvalErrorString( QObject::tr(
"Invalid axis name: '%1'. It must be either 'x' or 'y'." ).arg( axis ) );
2795 return floatToDegreeFormat( format, values, context, parent, node );
2802 value = QgsCoordinateUtils::dmsToDecimal( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), &ok );
2804 return ok ? QVariant( value ) : QVariant();
2810 return floatToDegreeFormat( format, values, context, parent, node );
2815 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2816 QDateTime d2 = QgsExpressionUtils::getDateTimeValue( values.at( 1 ), parent );
2817 qint64 seconds = d2.secsTo( d1 );
2818 return QVariant::fromValue(
QgsInterval( seconds ) );
2823 if ( !values.at( 0 ).canConvert<QDate>() )
2826 QDate date = QgsExpressionUtils::getDateValue( values.at( 0 ), parent );
2827 if ( !date.isValid() )
2832 return date.dayOfWeek() % 7;
2837 QVariant value = values.at( 0 );
2838 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2841 return QVariant( inter.
days() );
2845 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2846 return QVariant( d1.date().day() );
2852 QVariant value = values.at( 0 );
2853 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2856 return QVariant( inter.
years() );
2860 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2861 return QVariant( d1.date().year() );
2867 QVariant value = values.at( 0 );
2868 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2871 return QVariant( inter.
months() );
2875 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2876 return QVariant( d1.date().month() );
2882 QVariant value = values.at( 0 );
2883 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2886 return QVariant( inter.
weeks() );
2890 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2891 return QVariant( d1.date().weekNumber() );
2897 QVariant value = values.at( 0 );
2898 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2901 return QVariant( inter.
hours() );
2905 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2906 return QVariant( t1.hour() );
2912 QVariant value = values.at( 0 );
2913 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2916 return QVariant( inter.
minutes() );
2920 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2921 return QVariant( t1.minute() );
2927 QVariant value = values.at( 0 );
2928 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2931 return QVariant( inter.
seconds() );
2935 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2936 return QVariant( t1.second() );
2942 QDateTime dt = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2945 return QVariant( dt.toMSecsSinceEpoch() );
2955 long long millisecs_since_epoch = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
2957 return QVariant( QDateTime::fromMSecsSinceEpoch( millisecs_since_epoch ) );
2962 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2965 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif" ) ) );
2968 QString tag = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2974 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2977 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif_geotag" ) ) );
2984#define ENSURE_GEOM_TYPE(f, g, geomtype) \
2985 if ( !(f).hasGeometry() ) \
2986 return QVariant(); \
2987 QgsGeometry g = (f).geometry(); \
2988 if ( (g).type() != (geomtype) ) \
2995 if ( g.isMultipart() )
2997 return g.asMultiPoint().at( 0 ).x();
3001 return g.asPoint().x();
3009 if ( g.isMultipart() )
3011 return g.asMultiPoint().at( 0 ).y();
3015 return g.asPoint().y();
3029 if ( g.isEmpty() || !abGeom->
is3D() )
3034 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( g.constGet() );
3040 if (
const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( g.constGet() ) )
3042 if ( collection->numGeometries() > 0 )
3044 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3055 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3061 return QVariant( isValid );
3066 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3070 const QString methodString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).trimmed();
3071#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
3076 if ( methodString.compare( QLatin1String(
"linework" ), Qt::CaseInsensitive ) == 0 )
3078 else if ( methodString.compare( QLatin1String(
"structure" ), Qt::CaseInsensitive ) == 0 )
3081 const bool keepCollapsed = values.value( 2 ).toBool();
3086 valid = geom.
makeValid( method, keepCollapsed );
3090 parent->
setEvalErrorString( QObject::tr(
"The make_valid parameters require a newer GEOS library version" ) );
3094 return QVariant::fromValue( valid );
3099 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3105 for (
int i = 0; i < multiGeom.size(); ++i )
3107 array += QVariant::fromValue( multiGeom.at( i ) );
3115 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3127 QVariant result( centroid.
asPoint().
x() );
3133 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3145 QVariant result( centroid.
asPoint().
y() );
3151 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3161 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3169 if ( collection->numGeometries() == 1 )
3171 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3182 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3192 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3200 if ( collection->numGeometries() == 1 )
3202 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3213 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3218 int idx = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
3245 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3262 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3279 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3284 bool ignoreClosing =
false;
3285 if ( values.length() > 1 )
3287 ignoreClosing = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3297 bool skipLast =
false;
3298 if ( ignoreClosing && ring.count() > 2 && ring.first() == ring.last() )
3303 for (
int i = 0; i < ( skipLast ? ring.count() - 1 : ring.count() ); ++ i )
3315 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3326 for (
int i = 0; i < line->numPoints() - 1; ++i )
3330 << line->pointN( i )
3331 << line->pointN( i + 1 ) );
3342 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3352 if ( collection->numGeometries() == 1 )
3354 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->geometryN( 0 ) );
3359 if ( !curvePolygon )
3363 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3369 QVariant result = curve ? QVariant::fromValue(
QgsGeometry( curve ) ) : QVariant();
3375 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3385 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3391 QVariant result = part ? QVariant::fromValue(
QgsGeometry( part ) ) : QVariant();
3397 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3406 return QVariant::fromValue(
QgsGeometry( boundary ) );
3411 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3420 return QVariant::fromValue( merged );
3425 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3429 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3434 if ( sharedPaths.
isNull() )
3437 return QVariant::fromValue( sharedPaths );
3443 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3448 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3451 if ( simplified.
isNull() )
3459 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3464 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3469 if ( simplified.
isNull() )
3477 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3482 int iterations = std::min( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), 10 );
3483 double offset = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0.0, 0.5 );
3484 double minLength = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3485 double maxAngle = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ), 0.0, 180.0 );
3487 QgsGeometry smoothed = geom.
smooth(
static_cast<unsigned int>( iterations ), offset, minLength, maxAngle );
3496 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3501 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3502 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3503 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3514 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3519 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3520 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3521 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3522 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3523 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3526 minAmplitude, maxAmplitude, seed );
3535 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3540 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3541 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3542 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3553 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3558 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3559 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3560 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3561 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3562 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3565 minAmplitude, maxAmplitude, seed );
3574 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3579 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3580 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3581 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3592 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3597 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3598 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3599 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3600 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3601 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3604 minAmplitude, maxAmplitude, seed );
3613 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3618 const QVariantList pattern = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
3619 QVector< double > dashPattern;
3620 dashPattern.reserve( pattern.size() );
3621 for (
const QVariant &value : std::as_const( pattern ) )
3624 double v = value.toDouble( &ok );
3631 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must be an array of numbers" ) );
3636 if ( dashPattern.size() % 2 != 0 )
3638 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must contain an even number of elements" ) );
3642 const QString startRuleString = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).trimmed();
3644 if ( startRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3646 else if ( startRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3648 else if ( startRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3650 else if ( startRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3652 else if ( startRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3656 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( startRuleString ) );
3660 const QString endRuleString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
3662 if ( endRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3664 else if ( endRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3666 else if ( endRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3668 else if ( endRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3670 else if ( endRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3674 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( endRuleString ) );
3678 const QString adjustString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
3680 if ( adjustString.compare( QLatin1String(
"both" ), Qt::CaseInsensitive ) == 0 )
3682 else if ( adjustString.compare( QLatin1String(
"dash" ), Qt::CaseInsensitive ) == 0 )
3684 else if ( adjustString.compare( QLatin1String(
"gap" ), Qt::CaseInsensitive ) == 0 )
3688 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern size adjustment" ).arg( adjustString ) );
3692 const double patternOffset = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
3703 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3708 const long long count = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3710 if ( densified.
isNull() )
3718 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3723 const double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3725 if ( densified.
isNull() )
3734 if ( values.size() == 1 && QgsExpressionUtils::isList( values.at( 0 ) ) )
3736 list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
3743 QVector< QgsGeometry > parts;
3744 parts.reserve( list.size() );
3745 for (
const QVariant &value : std::as_const( list ) )
3747 QgsGeometry part = QgsExpressionUtils::getGeometry( value, parent );
3758 if ( values.count() < 2 || values.count() > 4 )
3760 parent->
setEvalErrorString( QObject::tr(
"Function make_point requires 2-4 arguments" ) );
3764 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3765 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3766 double z = values.count() >= 3 ? QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) : 0.0;
3767 double m = values.count() >= 4 ? QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) : 0.0;
3768 switch ( values.count() )
3782 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3783 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3784 double m = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3790 if ( values.empty() )
3795 QVector<QgsPoint> points;
3796 points.reserve( values.count() );
3798 auto addPoint = [&points](
const QgsGeometry & geom )
3806 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3813 for (
const QVariant &value : values )
3815 if ( value.userType() == QMetaType::Type::QVariantList )
3817 const QVariantList list = value.toList();
3818 for (
const QVariant &v : list )
3820 addPoint( QgsExpressionUtils::getGeometry( v, parent ) );
3825 addPoint( QgsExpressionUtils::getGeometry( value, parent ) );
3829 if ( points.count() < 2 )
3837 if ( values.count() < 1 )
3839 parent->
setEvalErrorString( QObject::tr(
"Function make_polygon requires an argument" ) );
3843 QgsGeometry outerRing = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3851 auto polygon = std::make_unique< QgsPolygon >();
3853 const QgsCurve *exteriorRing = qgsgeometry_cast< const QgsCurve * >( outerRing.
constGet() );
3860 exteriorRing = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
3865 if ( !exteriorRing )
3868 polygon->setExteriorRing( exteriorRing->
segmentize() );
3871 for (
int i = 1; i < values.count(); ++i )
3873 QgsGeometry ringGeom = QgsExpressionUtils::getGeometry( values.at( i ), parent );
3880 const QgsCurve *ring = qgsgeometry_cast< const QgsCurve * >( ringGeom.
constGet() );
3887 ring = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
3895 polygon->addInteriorRing( ring->
segmentize() );
3898 return QVariant::fromValue(
QgsGeometry( std::move( polygon ) ) );
3903 auto tr = std::make_unique<QgsTriangle>();
3904 auto lineString = std::make_unique<QgsLineString>();
3905 lineString->clear();
3907 for (
const QVariant &value : values )
3909 QgsGeometry geom = QgsExpressionUtils::getGeometry( value, parent );
3916 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3923 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3931 lineString->addVertex( *point );
3934 tr->setExteriorRing( lineString.release() );
3936 return QVariant::fromValue(
QgsGeometry( tr.release() ) );
3941 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3948 double radius = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3949 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
3956 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3963 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3971 return QVariant::fromValue(
QgsGeometry( circ.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
3976 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3983 double majorAxis = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3984 double minorAxis = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3985 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3986 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 4 ), parent );
3992 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3999 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4006 QgsEllipse elp( *point, majorAxis, minorAxis, azimuth );
4007 return QVariant::fromValue(
QgsGeometry( elp.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
4013 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4020 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4027 unsigned int nbEdges =
static_cast<unsigned int>( QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) );
4030 parent->
setEvalErrorString( QObject::tr(
"Number of edges/sides must be greater than 2" ) );
4037 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (inscribed) or 1 (circumscribed)" ) );
4041 const QgsPoint *center = qgsgeometry_cast< const QgsPoint * >( pt1.
constGet() );
4048 center = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4055 const QgsPoint *corner = qgsgeometry_cast< const QgsPoint * >( pt2.
constGet() );
4062 corner = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4077 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4083 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4089 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
4090 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
4098 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4104 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4110 QgsGeometry pt3 = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
4119 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (distance) or 1 (projected)" ) );
4122 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
4123 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
4124 const QgsPoint *point3 = qgsgeometry_cast< const QgsPoint *>( pt3.
constGet() );
4143 return QVariant::fromValue( geom.
vertexAt( idx ) );
4151 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4153 const QVariant v = pointAt( geom, idx, parent );
4156 return QVariant( v.value<
QgsPoint>().
x() );
4162 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4164 return fcnOldXat( values, f, parent, node );
4166 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4168 return fcnOldXat( QVariantList() << values[1], f, parent, node );
4171 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4177 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4179 const QVariant v = pointAt( geom, vertexNumber, parent );
4181 return QVariant( v.value<
QgsPoint>().
x() );
4191 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4193 const QVariant v = pointAt( geom, idx, parent );
4196 return QVariant( v.value<
QgsPoint>().
y() );
4202 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4204 return fcnOldYat( values, f, parent, node );
4206 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4208 return fcnOldYat( QVariantList() << values[1], f, parent, node );
4211 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4217 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4219 const QVariant v = pointAt( geom, vertexNumber, parent );
4221 return QVariant( v.value<
QgsPoint>().
y() );
4228 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4234 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4236 const QVariant v = pointAt( geom, vertexNumber, parent );
4238 return QVariant( v.value<
QgsPoint>().
z() );
4245 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4251 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4253 const QVariant v = pointAt( geom, vertexNumber, parent );
4255 return QVariant( v.value<
QgsPoint>().
m() );
4274 return QVariant::fromValue( geom );
4282 QString wkt = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4284 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4290 const QByteArray wkb = QgsExpressionUtils::getBinaryValue( values.at( 0 ), parent );
4296 return !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4301 QString gml = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4308 ogcContext.
layer = mapLayerPtr.data();
4309 ogcContext.
transformContext = context->
variable( QStringLiteral(
"_project_transform_context" ) ).value<QgsCoordinateTransformContext>();
4313 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4328 return QVariant( area );
4332 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating area" ) );
4344 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4349 return QVariant( geom.
area() );
4363 return QVariant( len );
4367 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating length" ) );
4388 return QVariant( len );
4392 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating perimeter" ) );
4398 return f.
geometry().
isNull() ? QVariant( 0 ) : QVariant( f.geometry().constGet()->perimeter() );
4404 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4410 return QVariant( geom.
length() );
4415 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4416 return QVariant( geom.
isNull() ? 0 : geom.constGet()->nCoordinates() );
4421 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4430 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4439 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4454 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon *>( collection->
geometryN( i ) );
4455 if ( !curvePolygon )
4458 return QVariant( curvePolygon->
isEmpty() ? 0 : curvePolygon->numInteriorRings() );
4467 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4474 return QVariant( curvePolygon->
ringCount() );
4476 bool foundPoly =
false;
4484 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon *>( collection->
geometryN( i ) );
4485 if ( !curvePolygon )
4496 return QVariant( ringCount );
4501 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4503 QVariant result = !geomBounds.
isNull() ? QVariant::fromValue( geomBounds ) : QVariant();
4509 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4515 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4521 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4530 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4536 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4542 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4548 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4554 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4562 double max = std::numeric_limits< double >::lowest();
4566 double z = ( *it ).z();
4572 if ( max == std::numeric_limits< double >::lowest() )
4575 return QVariant( max );
4580 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4588 double min = std::numeric_limits< double >::max();
4592 double z = ( *it ).z();
4598 if ( min == std::numeric_limits< double >::max() )
4601 return QVariant( min );
4606 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4614 double min = std::numeric_limits< double >::max();
4618 double m = ( *it ).m();
4624 if ( min == std::numeric_limits< double >::max() )
4627 return QVariant( min );
4632 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4640 double max = std::numeric_limits< double >::lowest();
4644 double m = ( *it ).m();
4650 if ( max == std::numeric_limits< double >::lowest() )
4653 return QVariant( max );
4658 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4659 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom.
constGet() );
4662 parent->
setEvalErrorString( QObject::tr(
"Function `sinuosity` requires a line geometry." ) );
4671 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4675 parent->
setEvalErrorString( QObject::tr(
"Function `straight_distance_2d` requires a line geometry or a multi line geometry with a single part." ) );
4684 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4689 parent->
setEvalErrorString( QObject::tr(
"Function `roundness` requires a polygon geometry or a multi polygon geometry with a single part." ) );
4700 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4704 std::unique_ptr< QgsAbstractGeometry > flipped( geom.
constGet()->
clone() );
4706 return QVariant::fromValue(
QgsGeometry( std::move( flipped ) ) );
4711 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4715 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( fGeom.
constGet() );
4722 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
4730 return QVariant::fromValue( curve->
isClosed() );
4735 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4748 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4749 closedLine->close();
4751 result = QVariant::fromValue(
QgsGeometry( std::move( closedLine ) ) );
4763 if (
const QgsLineString *line = qgsgeometry_cast<const QgsLineString * >( collection->
geometryN( i ) ) )
4765 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4766 closedLine->close();
4768 closed->addGeometry( closedLine.release() );
4771 result = QVariant::fromValue(
QgsGeometry( std::move( closed ) ) );
4779 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4783 return QVariant::fromValue( fGeom.
isEmpty() );
4789 return QVariant::fromValue(
true );
4791 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4792 return QVariant::fromValue( fGeom.
isNull() || fGeom.
isEmpty() );
4797 if ( values.length() < 2 || values.length() > 3 )
4800 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4801 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4808 if ( values.length() == 2 )
4811 QString result = engine->relate( sGeom.
constGet() );
4812 return QVariant::fromValue( result );
4817 QString pattern = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
4818 bool result = engine->relatePattern( sGeom.
constGet(), pattern );
4819 return QVariant::fromValue( result );
4825 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4826 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4831 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4832 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4833 return fGeom.
disjoint( sGeom ) ? TVL_True : TVL_False;
4837 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4838 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4839 return fGeom.
intersects( sGeom ) ? TVL_True : TVL_False;
4843 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4844 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4845 return fGeom.
touches( sGeom ) ? TVL_True : TVL_False;
4849 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4850 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4851 return fGeom.
crosses( sGeom ) ? TVL_True : TVL_False;
4855 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4856 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4857 return fGeom.
contains( sGeom ) ? TVL_True : TVL_False;
4861 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4862 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4863 return fGeom.
overlaps( sGeom ) ? TVL_True : TVL_False;
4867 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4868 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4869 return fGeom.
within( sGeom ) ? TVL_True : TVL_False;
4874 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4875 const double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4876 const int seg = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4877 const QString endCapString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
4878 const QString joinString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
4879 const double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
4882 if ( endCapString.compare( QLatin1String(
"flat" ), Qt::CaseInsensitive ) == 0 )
4884 else if ( endCapString.compare( QLatin1String(
"square" ), Qt::CaseInsensitive ) == 0 )
4888 if ( joinString.compare( QLatin1String(
"miter" ), Qt::CaseInsensitive ) == 0 )
4890 else if ( joinString.compare( QLatin1String(
"bevel" ), Qt::CaseInsensitive ) == 0 )
4894 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4900 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4902 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4907 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4909 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4914 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4916 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4921 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4922 const QgsPoint *pt = qgsgeometry_cast<const QgsPoint *>( fGeom.
constGet() );
4929 pt = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4936 parent->
setEvalErrorString( QObject::tr(
"Function `wedge_buffer` requires a point value for the center." ) );
4940 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4941 double width = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4942 double outerRadius = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4943 double innerRadius = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
4946 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4952 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4955 parent->
setEvalErrorString( QObject::tr(
"Function `tapered_buffer` requires a line geometry." ) );
4959 double startWidth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4960 double endWidth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4961 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) );
4964 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4970 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4973 parent->
setEvalErrorString( QObject::tr(
"Function `buffer_by_m` requires a line geometry." ) );
4977 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) );
4980 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4986 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4987 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4988 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4989 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4990 if ( joinInt < 1 || joinInt > 3 )
4994 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4997 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5003 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5004 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5005 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
5007 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
5008 if ( joinInt < 1 || joinInt > 3 )
5012 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5015 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5021 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5022 double distStart = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5023 double distEnd = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5026 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5032 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5033 double dx = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5034 double dy = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5036 return QVariant::fromValue( fGeom );
5041 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5042 const double rotation = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5043 const QgsGeometry center = values.at( 2 ).
isValid() ? QgsExpressionUtils::getGeometry( values.at( 2 ), parent )
5045 const bool perPart = values.value( 3 ).toBool();
5052 std::unique_ptr< QgsGeometryCollection > collection( qgsgeometry_cast< QgsGeometryCollection * >( fGeom.
constGet()->
clone() ) );
5055 const QgsPointXY partCenter = ( *it )->boundingBox().center();
5056 QTransform t = QTransform::fromTranslate( partCenter.
x(), partCenter.
y() );
5057 t.rotate( -rotation );
5058 t.translate( -partCenter.
x(), -partCenter.
y() );
5059 ( *it )->transform( t );
5061 return QVariant::fromValue(
QgsGeometry( std::move( collection ) ) );
5073 parent->
setEvalErrorString( QObject::tr(
"Function 'rotate' requires a point value for the center" ) );
5081 fGeom.
rotate( rotation, pt );
5082 return QVariant::fromValue( fGeom );
5088 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5089 const double xScale = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5090 const double yScale = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5091 const QgsGeometry center = values.at( 3 ).isValid() ? QgsExpressionUtils::getGeometry( values.at( 3 ), parent )
5102 parent->
setEvalErrorString( QObject::tr(
"Function 'scale' requires a point value for the center" ) );
5110 QTransform t = QTransform::fromTranslate( pt.
x(), pt.
y() );
5111 t.scale( xScale, yScale );
5112 t.translate( -pt.
x(), -pt.
y() );
5114 return QVariant::fromValue( fGeom );
5119 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5125 const double deltaX = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5126 const double deltaY = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5128 const double rotationZ = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5130 const double scaleX = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
5131 const double scaleY = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
5133 const double deltaZ = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
5134 const double deltaM = QgsExpressionUtils::getDoubleValue( values.at( 7 ), parent );
5135 const double scaleZ = QgsExpressionUtils::getDoubleValue( values.at( 8 ), parent );
5136 const double scaleM = QgsExpressionUtils::getDoubleValue( values.at( 9 ), parent );
5147 QTransform transform;
5148 transform.translate( deltaX, deltaY );
5149 transform.rotate( rotationZ );
5150 transform.scale( scaleX, scaleY );
5151 fGeom.
transform( transform, deltaZ, scaleZ, deltaM, scaleM );
5153 return QVariant::fromValue( fGeom );
5159 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5161 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5166 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5168 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5174 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5175 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5177 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5183 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5185 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5189#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
5194 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5195 const double targetPercent = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5196 const bool allowHoles = values.value( 2 ).toBool();
5198 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5211 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5213 if ( values.length() == 2 )
5214 segments = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5222 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5228 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5230 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5236 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5242 double area,
angle, width, height;
5255 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5256 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5258 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5269 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent,
true );
5275 const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( fGeom.
constGet() );
5280 result = reversed ? QVariant::fromValue(
QgsGeometry( reversed ) ) : QVariant();
5288 if (
const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( collection->
geometryN( i ) ) )
5290 reversed->addGeometry( curve->
reversed() );
5297 result = reversed ? QVariant::fromValue(
QgsGeometry( std::move( reversed ) ) ) : QVariant();
5303 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
5304 std::reverse(
string.begin(),
string.end() );
5310 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5321 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->
geometryN( 0 ) );
5330 QVariant result = exterior ? QVariant::fromValue(
QgsGeometry( exterior ) ) : QVariant();
5336 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5337 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5338 return QVariant( fGeom.
distance( sGeom ) );
5343 QgsGeometry g1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5344 QgsGeometry g2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5347 if ( values.length() == 3 && values.at( 2 ).isValid() )
5349 double densify = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5350 densify = std::clamp( densify, 0.0, 1.0 );
5358 return res > -1 ? QVariant( res ) : QVariant();
5363 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5364 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5366 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5371 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5372 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5374 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5379 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5380 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5382 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5388 if ( values.length() < 1 || values.length() > 2 )
5391 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5393 if ( values.length() == 2 )
5394 prec = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5395 QString wkt = fGeom.
asWkt( prec );
5396 return QVariant( wkt );
5401 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5402 return fGeom.
isNull() ? QVariant() : QVariant( fGeom.asWkb() );
5407 if ( values.length() != 2 )
5409 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires exactly two parameters. %n given.",
nullptr, values.length() ) );
5413 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5414 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5416 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5423 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5428 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5435 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5442 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires two points as arguments." ) );
5449 if ( pt1->
y() < pt2->
y() )
5451 else if ( pt1->
y() > pt2->
y() )
5459 if ( pt1->
x() < pt2->
x() )
5461 else if ( pt1->
x() > pt2->
x() )
5462 return M_PI + ( M_PI_2 );
5467 if ( pt1->
x() < pt2->
x() )
5469 if ( pt1->
y() < pt2->
y() )
5471 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) );
5475 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5482 if ( pt1->
y() > pt2->
y() )
5484 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) )
5489 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5490 + ( M_PI + ( M_PI_2 ) );
5497 const QgsGeometry geom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5498 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5500 QString ellipsoid = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
5504 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires two valid point geometries." ) );
5512 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires point geometries or multi point geometries with a single part." ) );
5523 sourceCrs = context->
variable( QStringLiteral(
"_layer_crs" ) ).value<QgsCoordinateReferenceSystem>();
5526 if ( ellipsoid.isEmpty() )
5528 ellipsoid = context->
variable( QStringLiteral(
"project_ellipsoid" ) ).toString();
5534 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires a valid source CRS." ) );
5542 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires a valid ellipsoid acronym or ellipsoid authority ID." ) );
5548 const double bearing = da.
bearing( point1, point2 );
5549 if ( std::isfinite( bearing ) )
5551 return std::fmod( bearing + 2 * M_PI, 2 * M_PI );
5564 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5568 parent->
setEvalErrorString( QStringLiteral(
"'project' requires a point geometry" ) );
5572 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5573 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5574 double inclination = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5577 QgsPoint newPoint = p->
project( distance, 180.0 * azimuth / M_PI, 180.0 * inclination / M_PI );
5584 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5585 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5587 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5594 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5598 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5605 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5613 parent->
setEvalErrorString( QStringLiteral(
"Function 'inclination' requires two points as arguments." ) );
5623 if ( values.length() != 3 )
5626 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5627 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5628 double y = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5632 QVariant result = geom.
constGet() ? QVariant::fromValue( geom ) : QVariant();
5638 if ( values.length() < 2 )
5641 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5644 return values.at( 0 );
5646 QString expString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5647 QVariant cachedExpression;
5652 if ( cachedExpression.isValid() )
5659 bool asc = values.value( 2 ).toBool();
5677 Q_ASSERT( collection );
5681 QgsExpressionSorter sorter( orderBy );
5683 QList<QgsFeature> partFeatures;
5684 partFeatures.reserve( collection->
partCount() );
5685 for (
int i = 0; i < collection->
partCount(); ++i )
5691 sorter.sortFeatures( partFeatures, unconstedContext );
5695 Q_ASSERT( orderedGeom );
5700 for (
const QgsFeature &feature : std::as_const( partFeatures ) )
5705 QVariant result = QVariant::fromValue(
QgsGeometry( orderedGeom ) );
5708 delete unconstedContext;
5715 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5716 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5720 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5726 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5727 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5731 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5737 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5738 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5742 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5748 const QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5749 const double m = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5750 const bool use3DDistance = values.at( 2 ).toBool();
5752 double x, y, z, distance;
5775 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5778 parent->
setEvalErrorString( QObject::tr(
"line_substring requires a curve geometry input" ) );
5784 curve = qgsgeometry_cast< const QgsCurve * >( lineGeom.
constGet() );
5791 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
5798 double startDistance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5799 double endDistance = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5801 std::unique_ptr< QgsCurve > substring( curve->
curveSubstring( startDistance, endDistance ) );
5803 return !result.isNull() ? QVariant::fromValue( result ) : QVariant();
5808 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5809 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5816 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5817 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5822 vertex = count + vertex;
5830 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5831 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5836 vertex = count + vertex;
5844 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5845 QgsGeometry pointGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5849 return distance >= 0 ? distance : QVariant();
5854 const QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5855 const double m = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5856 const bool use3DDistance = values.at( 2 ).toBool();
5858 double x, y, z, distance;
5867 return found ? distance : QVariant();
5872 if ( values.length() == 2 && values.at( 1 ).toInt() != 0 )
5874 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5875 return qgsRound( number, QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
5878 if ( values.length() >= 1 )
5880 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5881 return QVariant( qlonglong( std::round( number ) ) );
5896 const double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5897 const int places = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5898 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5905 const bool omitGroupSeparator = values.value( 3 ).toBool();
5906 const bool trimTrailingZeros = values.value( 4 ).toBool();
5908 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5909 if ( !omitGroupSeparator )
5910 locale.setNumberOptions( locale.numberOptions() & ~QLocale::NumberOption::OmitGroupSeparator );
5912 locale.setNumberOptions( locale.numberOptions() | QLocale::NumberOption::OmitGroupSeparator );
5914 QString res = locale.toString( value,
'f', places );
5916 if ( trimTrailingZeros )
5918#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
5919 const QChar decimal = locale.decimalPoint();
5920 const QChar zeroDigit = locale.zeroDigit();
5922 const QChar decimal = locale.decimalPoint().at( 0 );
5923 const QChar zeroDigit = locale.zeroDigit().at( 0 );
5926 if ( res.contains( decimal ) )
5928 int trimPoint = res.length() - 1;
5930 while ( res.at( trimPoint ) == zeroDigit )
5933 if ( res.at( trimPoint ) == decimal )
5936 res.truncate( trimPoint + 1 );
5945 QDateTime datetime = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
5946 const QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5947 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5950 if ( format.indexOf(
"Z" ) > 0 )
5951 datetime = datetime.toUTC();
5953 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5954 return locale.toString( datetime, format );
5959 const QVariant variant = values.at( 0 );
5961 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
5962 if ( !color.isValid() )
5965 const float alpha = color.alphaF();
5966 if ( color.spec() == QColor::Spec::Cmyk )
5968 const float avg = ( color.cyanF() + color.magentaF() + color.yellowF() ) / 3;
5969 color = QColor::fromCmykF( avg, avg, avg, color.blackF(), alpha );
5973 const float avg = ( color.redF() + color.greenF() + color.blueF() ) / 3;
5974 color.setRgbF( avg, avg, avg, alpha );
5977 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
5984 double ratio = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5989 else if ( ratio < 0 )
5994 int red =
static_cast<int>( color1.red() * ( 1 - ratio ) + color2.red() * ratio );
5995 int green =
static_cast<int>( color1.green() * ( 1 - ratio ) + color2.green() * ratio );
5996 int blue =
static_cast<int>( color1.blue() * ( 1 - ratio ) + color2.blue() * ratio );
5997 int alpha =
static_cast<int>( color1.alpha() * ( 1 - ratio ) + color2.alpha() * ratio );
5999 QColor newColor( red, green, blue, alpha );
6006 const QVariant variant1 = values.at( 0 );
6007 const QVariant variant2 = values.at( 1 );
6009 if ( variant1.userType() != variant2.userType() )
6011 parent->
setEvalErrorString( QObject::tr(
"Both color arguments must have the same type (string or color object)" ) );
6016 const QColor color1 = QgsExpressionUtils::getColorValue( variant1, parent, isQColor );
6017 if ( !color1.isValid() )
6020 const QColor color2 = QgsExpressionUtils::getColorValue( variant2, parent, isQColor );
6021 if ( !color2.isValid() )
6024 if ( ( color1.spec() == QColor::Cmyk ) != ( color2.spec() == QColor::Cmyk ) )
6026 parent->
setEvalErrorString( QObject::tr(
"Both color arguments must have compatible color type (CMYK or RGB/HSV/HSL)" ) );
6030 const float ratio =
static_cast<float>( std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0., 1. ) );
6036 const float alpha = color1.alphaF() * ( 1 - ratio ) + color2.alphaF() * ratio;
6037 if ( color1.spec() == QColor::Spec::Cmyk )
6039 float cyan = color1.cyanF() * ( 1 - ratio ) + color2.cyanF() * ratio;
6040 float magenta = color1.magentaF() * ( 1 - ratio ) + color2.magentaF() * ratio;
6041 float yellow = color1.yellowF() * ( 1 - ratio ) + color2.yellowF() * ratio;
6042 float black = color1.blackF() * ( 1 - ratio ) + color2.blackF() * ratio;
6043 newColor = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6047 float red = color1.redF() * ( 1 - ratio ) + color2.redF() * ratio;
6048 float green = color1.greenF() * ( 1 - ratio ) + color2.greenF() * ratio;
6049 float blue = color1.blueF() * ( 1 - ratio ) + color2.blueF() * ratio;
6050 newColor = QColor::fromRgbF( red, green, blue, alpha );
6055 return isQColor ? QVariant( newColor ) : QVariant(
QgsSymbolLayerUtils::encodeColor( newColor ) );
6060 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
6061 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6062 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6063 QColor color = QColor( red, green, blue );
6064 if ( ! color.isValid() )
6066 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( red ).arg( green ).arg( blue ) );
6067 color = QColor( 0, 0, 0 );
6070 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6075 const float red = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6076 const float green = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6077 const float blue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6078 const float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6079 QColor color = QColor::fromRgbF( red, green, blue, alpha );
6080 if ( ! color.isValid() )
6082 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
6091 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
6092 QVariant value = node->
eval( parent, context );
6096 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
6098 value = node->
eval( parent, context );
6106 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
6108 QVariant value = node->
eval( parent, context );
6110 if ( value.toBool() )
6112 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
6114 value = node->
eval( parent, context );
6119 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
6121 value = node->
eval( parent, context );
6129 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
6130 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6131 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6132 int alpha = QgsExpressionUtils::getNativeIntValue( values.at( 3 ), parent );
6133 QColor color = QColor( red, green, blue, alpha );
6134 if ( ! color.isValid() )
6136 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
6137 color = QColor( 0, 0, 0 );
6146 if ( values.at( 0 ).userType() == qMetaTypeId< QgsGradientColorRamp>() )
6148 expRamp = QgsExpressionUtils::getRamp( values.at( 0 ), parent );
6153 QString rampName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
6131 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent ); {
…}
6157 parent->
setEvalErrorString( QObject::tr(
"\"%1\" is not a valid color ramp" ).arg( rampName ) );
6162 double value = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
6163 QColor color = ramp->
color( value );
6176 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6178 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6180 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6182 QColor color = QColor::fromHslF( hue, saturation, lightness );
6184 if ( ! color.isValid() )
6186 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( lightness ) );
6187 color = QColor( 0, 0, 0 );
6190 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6196 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6198 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6200 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6202 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
6204 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
6205 if ( ! color.isValid() )
6207 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
6208 color = QColor( 0, 0, 0 );
6215 float hue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6216 float saturation = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6217 float lightness = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6218 float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6220 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
6221 if ( ! color.isValid() )
6223 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
6233 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6235 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6237 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6239 QColor color = QColor::fromHsvF( hue, saturation, value );
6241 if ( ! color.isValid() )
6243 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( value ) );
6244 color = QColor( 0, 0, 0 );
6247 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6253 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6255 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6257 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6259 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
6261 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
6262 if ( ! color.isValid() )
6264 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
6265 color = QColor( 0, 0, 0 );
6272 float hue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6273 float saturation = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6274 float value = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6275 float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6276 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
6278 if ( ! color.isValid() )
6280 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
6289 const float cyan = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6290 const float magenta = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6291 const float yellow = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6292 const float black = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6293 const float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ) ), 0.f, 1.f );
6295 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6296 if ( ! color.isValid() )
6298 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
6308 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
6310 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6312 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6314 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
6316 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black );
6318 if ( ! color.isValid() )
6320 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ) );
6321 color = QColor( 0, 0, 0 );
6324 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6330 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
6332 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6334 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6336 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
6338 double alpha = QgsExpressionUtils::getIntValue( values.at( 4 ), parent ) / 255.0;
6340 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6341 if ( ! color.isValid() )
6343 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
6344 color = QColor( 0, 0, 0 );
6351 const QVariant variant = values.at( 0 );
6353 const QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6354 if ( !color.isValid() )
6357 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6358 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6360 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6361 return color.green();
6362 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6363 return color.blue();
6364 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6365 return color.alpha();
6366 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6367 return static_cast< double >( color.hsvHueF() * 360 );
6368 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6369 return static_cast< double >( color.hsvSaturationF() * 100 );
6370 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6371 return static_cast< double >( color.valueF() * 100 );
6372 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6373 return static_cast< double >( color.hslHueF() * 360 );
6374 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6375 return static_cast< double >( color.hslSaturationF() * 100 );
6376 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6377 return static_cast< double >( color.lightnessF() * 100 );
6378 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6379 return static_cast< double >( color.cyanF() * 100 );
6380 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6381 return static_cast< double >( color.magentaF() * 100 );
6382 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6383 return static_cast< double >( color.yellowF() * 100 );
6384 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6385 return static_cast< double >( color.blackF() * 100 );
6387 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6393 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
6396 parent->
setEvalErrorString( QObject::tr(
"A minimum of two colors is required to create a ramp" ) );
6400 QList< QColor > colors;
6402 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
6405 if ( !colors.last().isValid() )
6407 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( it.value().toString() ) );
6411 double step = it.key().toDouble();
6412 if ( it == map.constBegin() )
6417 else if ( it == map.constEnd() )
6427 bool discrete = values.at( 1 ).toBool();
6429 if ( colors.empty() )
6432 return QVariant::fromValue(
QgsGradientColorRamp( colors.first(), colors.last(), discrete, stops ) );
6437 const QVariant variant = values.at( 0 );
6439 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6440 if ( !color.isValid() )
6443 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6444 int value = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6445 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6446 color.setRed( std::clamp( value, 0, 255 ) );
6447 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6448 color.setGreen( std::clamp( value, 0, 255 ) );
6449 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6450 color.setBlue( std::clamp( value, 0, 255 ) );
6451 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6452 color.setAlpha( std::clamp( value, 0, 255 ) );
6453 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6454 color.setHsv( std::clamp( value, 0, 359 ), color.hsvSaturation(), color.value(), color.alpha() );
6455 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6456 color.setHsvF( color.hsvHueF(), std::clamp( value, 0, 100 ) / 100.0, color.valueF(), color.alphaF() );
6457 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6458 color.setHsvF( color.hsvHueF(), color.hsvSaturationF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6459 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6460 color.setHsl( std::clamp( value, 0, 359 ), color.hslSaturation(), color.lightness(), color.alpha() );
6461 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6462 color.setHslF( color.hslHueF(), std::clamp( value, 0, 100 ) / 100.0, color.lightnessF(), color.alphaF() );
6463 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6464 color.setHslF( color.hslHueF(), color.hslSaturationF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6465 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6466 color.setCmykF( std::clamp( value, 0, 100 ) / 100.0, color.magentaF(), color.yellowF(), color.blackF(), color.alphaF() );
6467 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6468 color.setCmykF( color.cyanF(), std::clamp( value, 0, 100 ) / 100.0, color.yellowF(), color.blackF(), color.alphaF() );
6469 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6470 color.setCmykF( color.cyanF(), color.magentaF(), std::clamp( value, 0, 100 ) / 100.0, color.blackF(), color.alphaF() );
6471 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6472 color.setCmykF( color.cyanF(), color.magentaF(), color.yellowF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6475 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6478 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6483 const QVariant variant = values.at( 0 );
6485 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6486 if ( !color.isValid() )
6489 color = color.darker( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6491 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6496 const QVariant variant = values.at( 0 );
6498 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6499 if ( !color.isValid() )
6502 color = color.lighter( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6504 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6509 QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6512 return QVariant::fromValue( geom );
6518 const QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6526 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
6531 return QVariant::fromValue( fGeom );
6534 return QVariant::fromValue( fGeom );
6543 return QVariant::fromValue( fGeom );
6556 bool foundLayer =
false;
6557 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6560 if ( !featureSource || !foundLayer )
6565 const QgsFeatureId fid = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
6578 result = QVariant::fromValue( fet );
6586 bool foundLayer =
false;
6587 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6590 if ( !featureSource || !foundLayer )
6595 QString cacheValueKey;
6596 if ( values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
6598 QVariantMap attributeMap = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
6600 QMap <QString, QVariant>::const_iterator i = attributeMap.constBegin();
6601 QString filterString;
6602 for ( ; i != attributeMap.constEnd(); ++i )
6604 if ( !filterString.isEmpty() )
6606 filterString.append(
" AND " );
6610 cacheValueKey = QStringLiteral(
"getfeature:%1:%2" ).arg( featureSource->id(), filterString );
6619 QString attribute = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6620 int attributeId = featureSource->fields().lookupField( attribute );
6621 if ( attributeId == -1 )
6626 const QVariant &attVal = values.at( 2 );
6628 cacheValueKey = QStringLiteral(
"getfeature:%1:%2:%3" ).arg( featureSource->id(), QString::number( attributeId ), attVal.toString() );
6651 res = QVariant::fromValue( fet );
6666 if ( !values.isEmpty() )
6669 if ( col && ( values.size() == 1 || !values.at( 1 ).isValid() ) )
6670 fieldName = col->
name();
6671 else if ( values.size() == 2 )
6672 fieldName = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6675 QVariant value = values.at( 0 );
6680 if ( fieldIndex == -1 )
6682 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: Field not found %2" ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6688 QgsVectorLayer *layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
6691 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName, value.toString() );
6700 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName );
6718 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: function cannot be evaluated without a context." ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6726 const QVariant data = values.at( 0 );
6727 const QMimeDatabase db;
6728 return db.mimeTypeForData( data.toByteArray() ).name();
6733 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6735 bool foundLayer =
false;
6736 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [layerProperty](
QgsMapLayer * layer )-> QVariant
6742 if ( QString::compare( layerProperty, QStringLiteral(
"name" ), Qt::CaseInsensitive ) == 0 )
6743 return layer->name();
6744 else if ( QString::compare( layerProperty, QStringLiteral(
"id" ), Qt::CaseInsensitive ) == 0 )
6746 else if ( QString::compare( layerProperty, QStringLiteral(
"title" ), Qt::CaseInsensitive ) == 0 )
6747 return !layer->metadata().title().isEmpty() ? layer->metadata().title() : layer->serverProperties()->title();
6748 else if ( QString::compare( layerProperty, QStringLiteral(
"abstract" ), Qt::CaseInsensitive ) == 0 )
6749 return !layer->metadata().abstract().isEmpty() ? layer->metadata().abstract() : layer->serverProperties()->abstract();
6750 else if ( QString::compare( layerProperty, QStringLiteral(
"keywords" ), Qt::CaseInsensitive ) == 0 )
6752 QStringList keywords;
6753 const QgsAbstractMetadataBase::KeywordMap keywordMap = layer->metadata().keywords();
6754 for ( auto it = keywordMap.constBegin(); it != keywordMap.constEnd(); ++it )
6756 keywords.append( it.value() );
6758 if ( !keywords.isEmpty() )
6760 return layer->serverProperties()->keywordList();
6762 else if ( QString::compare( layerProperty, QStringLiteral(
"data_url" ), Qt::CaseInsensitive ) == 0 )
6764 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution" ), Qt::CaseInsensitive ) == 0 )
6766 return !layer->
metadata().
rights().isEmpty() ? QVariant( layer->
metadata().
rights() ) : QVariant( layer->serverProperties()->attribution() );
6768 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution_url" ), Qt::CaseInsensitive ) == 0 )
6770 else if ( QString::compare( layerProperty, QStringLiteral(
"source" ), Qt::CaseInsensitive ) == 0 )
6772 else if ( QString::compare( layerProperty, QStringLiteral(
"min_scale" ), Qt::CaseInsensitive ) == 0 )
6774 else if ( QString::compare( layerProperty, QStringLiteral(
"max_scale" ), Qt::CaseInsensitive ) == 0 )
6776 else if ( QString::compare( layerProperty, QStringLiteral(
"is_editable" ), Qt::CaseInsensitive ) == 0 )
6778 else if ( QString::compare( layerProperty, QStringLiteral(
"crs" ), Qt::CaseInsensitive ) == 0 )
6780 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_definition" ), Qt::CaseInsensitive ) == 0 )
6782 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_description" ), Qt::CaseInsensitive ) == 0 )
6784 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_ellipsoid" ), Qt::CaseInsensitive ) == 0 )
6786 else if ( QString::compare( layerProperty, QStringLiteral(
"extent" ), Qt::CaseInsensitive ) == 0 )
6789 QVariant result = QVariant::fromValue( extentGeom );
6792 else if ( QString::compare( layerProperty, QStringLiteral(
"distance_units" ), Qt::CaseInsensitive ) == 0 )
6794 else if ( QString::compare( layerProperty, QStringLiteral(
"path" ), Qt::CaseInsensitive ) == 0 )
6797 return decodedUri.value( QStringLiteral(
"path" ) );
6799 else if ( QString::compare( layerProperty, QStringLiteral(
"type" ), Qt::CaseInsensitive ) == 0 )
6801 switch ( layer->
type() )
6804 return QCoreApplication::translate(
"expressions",
"Vector" );
6806 return QCoreApplication::translate(
"expressions",
"Raster" );
6808 return QCoreApplication::translate(
"expressions",
"Mesh" );
6810 return QCoreApplication::translate(
"expressions",
"Vector Tile" );
6812 return QCoreApplication::translate(
"expressions",
"Plugin" );
6814 return QCoreApplication::translate(
"expressions",
"Annotation" );
6816 return QCoreApplication::translate(
"expressions",
"Point Cloud" );
6818 return QCoreApplication::translate(
"expressions",
"Group" );
6820 return QCoreApplication::translate(
"expressions",
"Tiled Scene" );
6826 QgsVectorLayer *vLayer = qobject_cast< QgsVectorLayer * >( layer );
6829 if ( QString::compare( layerProperty, QStringLiteral(
"storage_type" ), Qt::CaseInsensitive ) == 0 )
6831 else if ( QString::compare( layerProperty, QStringLiteral(
"geometry_type" ), Qt::CaseInsensitive ) == 0 )
6833 else if ( QString::compare( layerProperty, QStringLiteral(
"feature_count" ), Qt::CaseInsensitive ) == 0 )
6849 const QString uriPart = values.at( 1 ).toString();
6851 bool foundLayer =
false;
6853 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, uriPart](
QgsMapLayer * layer )-> QVariant
6855 if ( !layer->dataProvider() )
6857 parent->setEvalErrorString( QObject::tr(
"Layer %1 has invalid data provider" ).arg( layer->name() ) );
6863 if ( !uriPart.isNull() )
6865 return decodedUri.value( uriPart );
6875 parent->
setEvalErrorString( QObject::tr(
"Function `decode_uri` requires a valid layer." ) );
6886 const int band = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6887 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6889 bool foundLayer =
false;
6890 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, band, layerProperty](
QgsMapLayer * layer )-> QVariant
6892 QgsRasterLayer *rl = qobject_cast< QgsRasterLayer * >( layer );
6896 if ( band < 1 || band > rl->bandCount() )
6898 parent->setEvalErrorString( QObject::tr(
"Invalid band number %1 for layer" ).arg( band ) );
6904 if ( QString::compare( layerProperty, QStringLiteral(
"avg" ), Qt::CaseInsensitive ) == 0 )
6906 else if ( QString::compare( layerProperty, QStringLiteral(
"stdev" ), Qt::CaseInsensitive ) == 0 )
6908 else if ( QString::compare( layerProperty, QStringLiteral(
"min" ), Qt::CaseInsensitive ) == 0 )
6910 else if ( QString::compare( layerProperty, QStringLiteral(
"max" ), Qt::CaseInsensitive ) == 0 )
6912 else if ( QString::compare( layerProperty, QStringLiteral(
"range" ), Qt::CaseInsensitive ) == 0 )
6914 else if ( QString::compare( layerProperty, QStringLiteral(
"sum" ), Qt::CaseInsensitive ) == 0 )
6918 parent->
setEvalErrorString( QObject::tr(
"Invalid raster statistic: '%1'" ).arg( layerProperty ) );
6946 parent->
setEvalErrorString( QObject::tr(
"Function `raster_statistic` requires a valid raster layer." ) );
6963 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6964 bool ascending = values.value( 1 ).toBool();
6965 std::sort( list.begin(), list.end(), [ascending]( QVariant a, QVariant b ) ->
bool { return ( !ascending ? qgsVariantLessThan( b, a ) : qgsVariantLessThan( a, b ) ); } );
6971 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).length();
6976 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).contains( values.at( 1 ) ) );
6981 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).count( values.at( 1 ) ) );
6986 QVariantList listA = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6987 QVariantList listB = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
6989 for (
const auto &item : listB )
6991 if ( listA.contains( item ) )
6995 return QVariant( match == listB.count() );
7000 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).indexOf( values.at( 1 ) );
7005 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7006 const int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7007 if ( pos < list.length() && pos >= 0 )
return list.at( pos );
7008 else if ( pos < 0 && ( list.length() + pos ) >= 0 )
7009 return list.at( list.length() + pos );
7015 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7016 return list.value( 0 );
7021 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7022 return list.value( list.size() - 1 );
7027 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7028 return list.isEmpty() ? QVariant() : *std::min_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
7033 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7034 return list.isEmpty() ? QVariant() : *std::max_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
7039 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7042 for (
const QVariant &item : list )
7044 switch ( item.userType() )
7046 case QMetaType::Int:
7047 case QMetaType::UInt:
7048 case QMetaType::LongLong:
7049 case QMetaType::ULongLong:
7050 case QMetaType::Float:
7051 case QMetaType::Double:
7052 total += item.toDouble();
7057 return i == 0 ? QVariant() : total / i;
7062 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7063 QVariantList numbers;
7064 for (
const auto &item : list )
7066 switch ( item.userType() )
7068 case QMetaType::Int:
7069 case QMetaType::UInt:
7070 case QMetaType::LongLong:
7071 case QMetaType::ULongLong:
7072 case QMetaType::Float:
7073 case QMetaType::Double:
7074 numbers.append( item );
7078 std::sort( numbers.begin(), numbers.end(), []( QVariant a, QVariant b ) ->
bool { return ( qgsVariantLessThan( a, b ) ); } );
7079 const int count = numbers.count();
7084 else if ( count % 2 )
7086 return numbers.at( count / 2 );
7090 return ( numbers.at( count / 2 - 1 ).toDouble() + numbers.at( count / 2 ).toDouble() ) / 2;
7096 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7099 for (
const QVariant &item : list )
7101 switch ( item.userType() )
7103 case QMetaType::Int:
7104 case QMetaType::UInt:
7105 case QMetaType::LongLong:
7106 case QMetaType::ULongLong:
7107 case QMetaType::Float:
7108 case QMetaType::Double:
7109 total += item.toDouble();
7114 return i == 0 ? QVariant() : total;
7117static QVariant convertToSameType(
const QVariant &value, QMetaType::Type type )
7119 QVariant result = value;
7120 result.convert(
static_cast<int>( type ) );
7126 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7127 QHash< QVariant, int > hash;
7128 for (
const auto &item : list )
7132 const QList< int > occurrences = hash.values();
7133 if ( occurrences.empty() )
7134 return QVariantList();
7136 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
7138 const QString option = values.at( 1 ).toString();
7139 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
7141 return convertToSameType( hash.keys( maxValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7143 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
7145 if ( hash.isEmpty() )
7148 return QVariant( hash.key( maxValue ) );
7150 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
7152 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( maxValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) ), context, parent, node );
7154 else if ( option.compare( QLatin1String(
"real_majority" ), Qt::CaseInsensitive ) == 0 )
7156 if ( maxValue * 2 <= list.size() )
7159 return QVariant( hash.key( maxValue ) );
7170 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7171 QHash< QVariant, int > hash;
7172 for (
const auto &item : list )
7176 const QList< int > occurrences = hash.values();
7177 if ( occurrences.empty() )
7178 return QVariantList();
7180 const int minValue = *std::min_element( occurrences.constBegin(), occurrences.constEnd() );
7182 const QString option = values.at( 1 ).toString();
7183 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
7185 return convertToSameType( hash.keys( minValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7187 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
7189 if ( hash.isEmpty() )
7192 return QVariant( hash.key( minValue ) );
7194 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
7196 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( minValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) ), context, parent, node );
7198 else if ( option.compare( QLatin1String(
"real_minority" ), Qt::CaseInsensitive ) == 0 )
7200 if ( hash.isEmpty() )
7204 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
7205 if ( maxValue * 2 > list.size() )
7206 hash.remove( hash.key( maxValue ) );
7208 return convertToSameType( hash.keys(),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7219 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7220 list.append( values.at( 1 ) );
7221 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7226 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7227 list.prepend( values.at( 1 ) );
7228 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7233 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7234 list.insert( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), values.at( 2 ) );
7235 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7240 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7241 int position = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7243 position = position + list.length();
7244 if ( position >= 0 && position < list.length() )
7245 list.removeAt( position );
7246 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7254 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7256 const QVariant toRemove = values.at( 1 );
7259 list.erase( std::remove_if( list.begin(), list.end(), [](
const QVariant & element )
7261 return QgsVariantUtils::isNull( element );
7266 list.removeAll( toRemove );
7268 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7273 if ( values.count() == 2 && values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
7275 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
7277 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7278 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
7280 int index = list.indexOf( it.key() );
7281 while ( index >= 0 )
7283 list.replace( index, it.value() );
7284 index = list.indexOf( it.key() );
7288 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7290 else if ( values.count() == 3 )
7292 QVariantList before;
7294 bool isSingleReplacement =
false;
7296 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).userType() != QMetaType::Type::QStringList )
7298 before = QVariantList() << values.at( 1 );
7302 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
7305 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
7307 after = QVariantList() << values.at( 2 );
7308 isSingleReplacement =
true;
7312 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
7315 if ( !isSingleReplacement && before.length() != after.length() )
7317 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
7321 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7322 for (
int i = 0; i < before.length(); i++ )
7324 int index = list.indexOf( before.at( i ) );
7325 while ( index >= 0 )
7327 list.replace( index, after.at( isSingleReplacement ? 0 : i ) );
7328 index = list.indexOf( before.at( i ) );
7332 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7336 parent->
setEvalErrorString( QObject::tr(
"Function array_replace requires 2 or 3 arguments" ) );
7343 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7344 QVariantList list_new;
7346 for (
const QVariant &cur :
QgsExpressionUtils::getListValue( values.at( 1 ), parent ) )
7348 while ( list.removeOne( cur ) )
7350 list_new.append( cur );
7354 list_new.append( list );
7356 return convertToSameType( list_new,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7362 for (
const QVariant &cur : values )
7364 list += QgsExpressionUtils::getListValue( cur, parent );
7366 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7371 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7372 int start_pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7373 const int end_pos = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
7374 int slice_length = 0;
7376 if ( start_pos < 0 )
7378 start_pos = list.length() + start_pos;
7382 slice_length = end_pos - start_pos + 1;
7386 slice_length = list.length() + end_pos - start_pos + 1;
7389 if ( slice_length < 0 )
7393 list = list.mid( start_pos, slice_length );
7399 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7400 std::reverse( list.begin(), list.end() );
7406 const QVariantList array1 = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7407 const QVariantList array2 = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
7408 for (
const QVariant &cur : array2 )
7410 if ( array1.contains( cur ) )
7411 return QVariant(
true );
7413 return QVariant(
false );
7418 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7420 QVariantList distinct;
7422 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7424 if ( !distinct.contains( *it ) )
7426 distinct += ( *it );
7435 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7436 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7437 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7441 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7443 str += ( !( *it ).toString().isEmpty() ) ? ( *it ).toString() : empty;
7444 if ( it != ( array.constEnd() - 1 ) )
7450 return QVariant( str );
7455 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7456 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7457 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7459 QStringList list = str.split( delimiter );
7462 for ( QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
7464 array += ( !( *it ).isEmpty() ) ? *it : empty;
7472 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7473 QJsonDocument document = QJsonDocument::fromJson( str.toUtf8() );
7474 if ( document.isNull() )
7477 return document.toVariant();
7483 QJsonDocument document = QJsonDocument::fromVariant( values.at( 0 ) );
7484 return QString( document.toJson( QJsonDocument::Compact ) );
7489 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7490 if ( str.isEmpty() )
7491 return QVariantMap();
7492 str = str.trimmed();
7499 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7506 for (
int i = 0; i + 1 < values.length(); i += 2 )
7508 result.insert( QgsExpressionUtils::getStringValue( values.at( i ), parent ), values.at( i + 1 ) );
7515 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7516 const QString prefix = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7517 QVariantMap resultMap;
7519 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7521 resultMap.insert( QString( it.key() ).prepend( prefix ), it.value() );
7529 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).value( values.at( 1 ).toString() );
7534 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).contains( values.at( 1 ).toString() );
7539 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7540 map.remove( values.at( 1 ).toString() );
7546 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7547 map.insert( values.at( 1 ).toString(), values.at( 2 ) );
7554 for (
const QVariant &cur : values )
7556 const QVariantMap curMap = QgsExpressionUtils::getMapValue( cur, parent );
7557 for ( QVariantMap::const_iterator it = curMap.constBegin(); it != curMap.constEnd(); ++it )
7558 result.insert( it.key(), it.value() );
7565 return QStringList( QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).keys() );
7570 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).values();
7575 const QString envVarName = values.at( 0 ).toString();
7576 if ( !QProcessEnvironment::systemEnvironment().contains( envVarName ) )
7579 return QProcessEnvironment::systemEnvironment().value( envVarName );
7584 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7587 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"base_file_name" ) ) );
7590 return QFileInfo( file ).completeBaseName();
7595 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7598 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_suffix" ) ) );
7601 return QFileInfo( file ).completeSuffix();
7606 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7609 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_exists" ) ) );
7612 return QFileInfo::exists( file );
7617 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7620 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_name" ) ) );
7623 return QFileInfo( file ).fileName();
7628 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7631 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_file" ) ) );
7634 return QFileInfo( file ).isFile();
7639 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7642 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_directory" ) ) );
7645 return QFileInfo( file ).isDir();
7650 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7653 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_path" ) ) );
7656 return QDir::toNativeSeparators( QFileInfo( file ).path() );
7661 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7664 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_size" ) ) );
7667 return QFileInfo( file ).size();
7670static QVariant fcnHash(
const QString &str,
const QCryptographicHash::Algorithm
algorithm )
7672 return QString( QCryptographicHash::hash( str.toUtf8(),
algorithm ).toHex() );
7678 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7679 QString method = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).toLower();
7681 if ( method == QLatin1String(
"md4" ) )
7683 hash = fcnHash( str, QCryptographicHash::Md4 );
7685 else if ( method == QLatin1String(
"md5" ) )
7687 hash = fcnHash( str, QCryptographicHash::Md5 );
7689 else if ( method == QLatin1String(
"sha1" ) )
7691 hash = fcnHash( str, QCryptographicHash::Sha1 );
7693 else if ( method == QLatin1String(
"sha224" ) )
7695 hash = fcnHash( str, QCryptographicHash::Sha224 );
7697 else if ( method == QLatin1String(
"sha256" ) )
7699 hash = fcnHash( str, QCryptographicHash::Sha256 );
7701 else if ( method == QLatin1String(
"sha384" ) )
7703 hash = fcnHash( str, QCryptographicHash::Sha384 );
7705 else if ( method == QLatin1String(
"sha512" ) )
7707 hash = fcnHash( str, QCryptographicHash::Sha512 );
7709 else if ( method == QLatin1String(
"sha3_224" ) )
7711 hash = fcnHash( str, QCryptographicHash::Sha3_224 );
7713 else if ( method == QLatin1String(
"sha3_256" ) )
7715 hash = fcnHash( str, QCryptographicHash::Sha3_256 );
7717 else if ( method == QLatin1String(
"sha3_384" ) )
7719 hash = fcnHash( str, QCryptographicHash::Sha3_384 );
7721 else if ( method == QLatin1String(
"sha3_512" ) )
7723 hash = fcnHash( str, QCryptographicHash::Sha3_512 );
7725 else if ( method == QLatin1String(
"keccak_224" ) )
7727 hash = fcnHash( str, QCryptographicHash::Keccak_224 );
7729 else if ( method == QLatin1String(
"keccak_256" ) )
7731 hash = fcnHash( str, QCryptographicHash::Keccak_256 );
7733 else if ( method == QLatin1String(
"keccak_384" ) )
7735 hash = fcnHash( str, QCryptographicHash::Keccak_384 );
7737 else if ( method == QLatin1String(
"keccak_512" ) )
7739 hash = fcnHash( str, QCryptographicHash::Keccak_512 );
7743 parent->
setEvalErrorString( QObject::tr(
"Hash method %1 is not available on this system." ).arg( str ) );
7750 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Md5 );
7755 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Sha256 );
7760 const QByteArray input = values.at( 0 ).toByteArray();
7761 return QVariant( QString( input.toBase64() ) );
7766 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7768 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7770 query.addQueryItem( it.key(), it.value().toString() );
7772 return query.toString( QUrl::ComponentFormattingOption::FullyEncoded );
7777 const QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7778 const QByteArray base64 = value.toLocal8Bit();
7779 const QByteArray decoded = QByteArray::fromBase64( base64 );
7780 return QVariant( decoded );
7785static 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 )
7790 parent->
setEvalErrorString( QStringLiteral(
"This function was called without an expression context." ) );
7794 const QVariant sourceLayerRef = context->
variable( QStringLiteral(
"layer" ) );
7797 QgsVectorLayer *sourceLayer = QgsExpressionUtils::getVectorLayer( sourceLayerRef, context, parent );
7806 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
7809 const bool layerCanBeCached = node->
isStatic( parent, context );
7810 QVariant targetLayerValue = node->
eval( parent, context );
7814 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
7816 QString subExpString = node->dump();
7818 bool testOnly = ( subExpString ==
"NULL" );
7821 QgsVectorLayer *targetLayer = QgsExpressionUtils::getVectorLayer( targetLayerValue, context, parent );
7825 parent->
setEvalErrorString( QObject::tr(
"Layer '%1' could not be loaded." ).arg( targetLayerValue.toString() ) );
7830 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
7832 QString filterString = node->dump();
7833 if ( filterString !=
"NULL" )
7835 request.setFilterExpression( filterString );
7839 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
7841 QVariant limitValue = node->eval( parent, context );
7843 qlonglong limit = QgsExpressionUtils::getIntValue( limitValue, parent );
7846 double max_distance = 0;
7847 if ( isNearestFunc )
7849 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
7851 QVariant distanceValue = node->eval( parent, context );
7853 max_distance = QgsExpressionUtils::getDoubleValue( distanceValue, parent );
7857 node = QgsExpressionUtils::getNode( values.at( isNearestFunc ? 5 : 4 ), parent );
7859 QVariant cacheValue = node->eval( parent, context );
7861 bool cacheEnabled = cacheValue.toBool();
7867 double minOverlap { -1 };
7868 double minInscribedCircleRadius { -1 };
7869 bool returnDetails =
false;
7870 bool sortByMeasure =
false;
7871 bool sortAscending =
false;
7872 bool requireMeasures =
false;
7873 bool overlapOrRadiusFilter =
false;
7874 if ( isIntersectsFunc )
7877 node = QgsExpressionUtils::getNode( values.at( 5 ), parent );
7879 const QVariant minOverlapValue = node->eval( parent, context );
7881 minOverlap = QgsExpressionUtils::getDoubleValue( minOverlapValue, parent );
7882 node = QgsExpressionUtils::getNode( values.at( 6 ), parent );
7884 const QVariant minInscribedCircleRadiusValue = node->eval( parent, context );
7886 minInscribedCircleRadius = QgsExpressionUtils::getDoubleValue( minInscribedCircleRadiusValue, parent );
7887 node = QgsExpressionUtils::getNode( values.at( 7 ), parent );
7889 returnDetails = !testOnly && node->eval( parent, context ).toBool();
7890 node = QgsExpressionUtils::getNode( values.at( 8 ), parent );
7892 const QString sorting { node->eval( parent, context ).toString().toLower() };
7893 sortByMeasure = !testOnly && ( sorting.startsWith(
"asc" ) || sorting.startsWith(
"des" ) );
7894 sortAscending = sorting.startsWith(
"asc" );
7895 requireMeasures = sortByMeasure || returnDetails;
7896 overlapOrRadiusFilter = minInscribedCircleRadius != -1 || minOverlap != -1;
7903 if ( sourceLayer && targetLayer->crs() != sourceLayer->crs() )
7906 request.setDestinationCrs( sourceLayer->crs(), TransformContext );
7909 bool sameLayers = ( sourceLayer && sourceLayer->id() == targetLayer->id() );
7912 if ( bboxGrow != 0 )
7914 intDomain.
grow( bboxGrow );
7917 const QString cacheBase { QStringLiteral(
"%1:%2:%3" ).arg( targetLayer->id(), subExpString, filterString ) };
7923 QList<QgsFeature> features;
7924 if ( isNearestFunc || ( layerCanBeCached && cacheEnabled ) )
7928 const QString cacheLayer { QStringLiteral(
"ovrlaylyr:%1" ).arg( cacheBase ) };
7929 const QString cacheIndex { QStringLiteral(
"ovrlayidx:%1" ).arg( cacheBase ) };
7933 cachedTarget = targetLayer->
materialize( request );
7934 if ( layerCanBeCached )
7935 context->
setCachedValue( cacheLayer, QVariant::fromValue( cachedTarget ) );
7945 if ( layerCanBeCached )
7946 context->
setCachedValue( cacheIndex, QVariant::fromValue( spatialIndex ) );
7953 QList<QgsFeatureId> fidsList;
7954 if ( isNearestFunc )
7956 fidsList = spatialIndex.
nearestNeighbor( geometry, sameLayers ? limit + 1 : limit, max_distance );
7960 fidsList = spatialIndex.
intersects( intDomain );
7963 QListIterator<QgsFeatureId> i( fidsList );
7964 while ( i.hasNext() )
7967 if ( sameLayers && feat.
id() == fId2 )
7969 features.append( cachedTarget->
getFeature( fId2 ) );
7977 request.setFilterRect( intDomain );
7982 if ( sameLayers && feat.
id() == feat2.
id() )
7984 features.append( feat2 );
7992 const QString expCacheKey { QStringLiteral(
"exp:%1" ).arg( cacheBase ) };
7993 const QString ctxCacheKey { QStringLiteral(
"ctx:%1" ).arg( cacheBase ) };
7999 subExpression.
prepare( &subContext );
8012 auto testLinestring = [ = ](
const QgsGeometry intersection,
double & overlapValue ) ->
bool
8014 bool testResult {
false };
8016 QVector<double> overlapValues;
8020 const QgsCurve *geom = qgsgeometry_cast< const QgsCurve * >( *it );
8022 if ( minOverlap != -1 || requireMeasures )
8024 overlapValue = geom->
length();
8025 overlapValues.append( overlapValue );
8026 if ( minOverlap != -1 )
8028 if ( overlapValue >= minOverlap )
8040 if ( ! overlapValues.isEmpty() )
8042 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
8049 auto testPolygon = [ = ](
const QgsGeometry intersection,
double & radiusValue,
double & overlapValue ) ->
bool
8052 bool testResult {
false };
8054 QVector<double> overlapValues;
8055 QVector<double> radiusValues;
8058 const QgsCurvePolygon *geom = qgsgeometry_cast< const QgsCurvePolygon * >( *it );
8060 if ( minOverlap != -1 || requireMeasures )
8062 overlapValue = geom->
area();
8063 overlapValues.append( geom->
area() );
8064 if ( minOverlap != - 1 )
8066 if ( overlapValue >= minOverlap )
8078 if ( minInscribedCircleRadius != -1 || requireMeasures )
8081 const double width = bbox.
width();
8082 const double height = bbox.
height();
8083 const double size = width > height ? width : height;
8084 const double tolerance = size / 100.0;
8086 testResult = radiusValue >= minInscribedCircleRadius;
8087 radiusValues.append( radiusValues );
8092 if ( !radiusValues.isEmpty() )
8094 radiusValue = *std::max_element( radiusValues.cbegin(), radiusValues.cend() );
8097 if ( ! overlapValues.isEmpty() )
8099 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
8109 QVariantList results;
8111 QListIterator<QgsFeature> i( features );
8112 while ( i.hasNext() && ( sortByMeasure || limit == -1 || foundCount < limit ) )
8118 if ( ! relationFunction || ( geometry.*relationFunction )( feat2.
geometry() ) )
8121 double overlapValue = -1;
8122 double radiusValue = -1;
8124 if ( isIntersectsFunc && ( requireMeasures || overlapOrRadiusFilter ) )
8137 for (
const auto &geom : std::as_const( geometries ) )
8139 switch ( geom.type() )
8143 poly.append( geom.asPolygon() );
8148 line.append( geom.asPolyline() );
8153 point.append( geom.asPoint() );
8164 switch ( geometry.
type() )
8192 switch ( intersection.
type() )
8199 bool testResult { testPolygon( intersection, radiusValue, overlapValue ) };
8201 if ( ! testResult && overlapOrRadiusFilter )
8214 if ( minInscribedCircleRadius != -1 )
8220 const bool testResult { testLinestring( intersection, overlapValue ) };
8222 if ( ! testResult && overlapOrRadiusFilter )
8235 if ( minInscribedCircleRadius != -1 )
8240 bool testResult {
false };
8241 if ( minOverlap != -1 || requireMeasures )
8261 testResult = testLinestring( feat2.
geometry(), overlapValue );
8266 testResult = testPolygon( feat2.
geometry(), radiusValue, overlapValue );
8272 if ( ! testResult && overlapOrRadiusFilter )
8300 const QVariant expResult = subExpression.
evaluate( &subContext );
8302 if ( requireMeasures )
8304 QVariantMap resultRecord;
8305 resultRecord.insert( QStringLiteral(
"id" ), feat2.
id() );
8306 resultRecord.insert( QStringLiteral(
"result" ), expResult );
8308 resultRecord.insert( QStringLiteral(
"overlap" ), overlapValue );
8310 if ( radiusValue != -1 )
8312 resultRecord.insert( QStringLiteral(
"radius" ), radiusValue );
8314 results.append( resultRecord );
8318 results.append( expResult );
8324 results.append( feat2.
id() );
8338 if ( requireMeasures )
8340 if ( sortByMeasure )
8342 std::sort( results.begin(), results.end(), [ sortAscending ](
const QVariant & recordA,
const QVariant & recordB ) ->
bool
8344 return sortAscending ?
8345 recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble()
8346 : recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble();
8350 if ( limit > 0 && results.size() > limit )
8352 results.erase( results.begin() + limit );
8355 if ( ! returnDetails )
8357 QVariantList expResults;
8358 for (
auto it = results.constBegin(); it != results.constEnd(); ++it )
8360 expResults.append( it->toMap().value( QStringLiteral(
"result" ) ) );
8370 QVariantList disjoint_results;
8379 if ( !results.contains( feat2.
id() ) )
8382 disjoint_results.append( subExpression.
evaluate( &subContext ) );
8385 return disjoint_results;
8428 return executeGeomOverlay( values, context, parent,
nullptr,
false, 0,
true );
8437 QMutexLocker locker( &sFunctionsMutex );
8439 QList<QgsExpressionFunction *> &functions = *sFunctions();
8441 if ( functions.isEmpty() )
8479 functions << randFunc;
8483 functions << randfFunc;
8486 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max" ), -1, fcnMax, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8487 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min" ), -1, fcnMin, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8494 <<
new QgsStaticExpressionFunction( QStringLiteral(
"pi" ), 0, fcnPi, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$pi" ) )
8499 <<
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" ) )
8500 <<
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" ) )
8501 <<
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" ) )
8506 <<
new QgsStaticExpressionFunction( QStringLiteral(
"coalesce" ), -1, fcnCoalesce, QStringLiteral(
"Conditionals" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8520 QStringLiteral(
"Aggregates" ),
8529 if ( !node->
args() )
8532 QSet<QString> referencedVars;
8544 return referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() );
8553 if ( !node->
args() )
8554 return QSet<QString>();
8556 QSet<QString> referencedCols;
8557 QSet<QString> referencedVars;
8572 if ( referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() ) )
8575 return referencedCols;
8588 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count" ), aggParams, fcnAggregateCount, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8589 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_distinct" ), aggParams, fcnAggregateCountDistinct, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8590 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_missing" ), aggParams, fcnAggregateCountMissing, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8591 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minimum" ), aggParams, fcnAggregateMin, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8592 <<
new QgsStaticExpressionFunction( QStringLiteral(
"maximum" ), aggParams, fcnAggregateMax, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8593 <<
new QgsStaticExpressionFunction( QStringLiteral(
"sum" ), aggParams, fcnAggregateSum, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8594 <<
new QgsStaticExpressionFunction( QStringLiteral(
"mean" ), aggParams, fcnAggregateMean, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8595 <<
new QgsStaticExpressionFunction( QStringLiteral(
"median" ), aggParams, fcnAggregateMedian, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8596 <<
new QgsStaticExpressionFunction( QStringLiteral(
"stdev" ), aggParams, fcnAggregateStdev, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8597 <<
new QgsStaticExpressionFunction( QStringLiteral(
"range" ), aggParams, fcnAggregateRange, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8598 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minority" ), aggParams, fcnAggregateMinority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8599 <<
new QgsStaticExpressionFunction( QStringLiteral(
"majority" ), aggParams, fcnAggregateMajority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8600 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q1" ), aggParams, fcnAggregateQ1, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8601 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q3" ), aggParams, fcnAggregateQ3, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8602 <<
new QgsStaticExpressionFunction( QStringLiteral(
"iqr" ), aggParams, fcnAggregateIQR, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8603 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min_length" ), aggParams, fcnAggregateMinLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8604 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max_length" ), aggParams, fcnAggregateMaxLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8605 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect" ), aggParams, fcnAggregateCollectGeometry, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8606 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate" ), aggParamsConcat, fcnAggregateStringConcat, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8607 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate_unique" ), aggParamsConcat, fcnAggregateStringConcatUnique, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8608 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array_agg" ), aggParamsArray, fcnAggregateArray, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8613 <<
new QgsStaticExpressionFunction( QStringLiteral(
"now" ), 0, fcnNow, QStringLiteral(
"Date and Time" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$now" ) )
8616 fcnAge, QStringLiteral(
"Date and Time" ) )
8630 fcnMakeDate, QStringLiteral(
"Date and Time" ) )
8634 fcnMakeTime, QStringLiteral(
"Date and Time" ) )
8641 fcnMakeDateTime, QStringLiteral(
"Date and Time" ) )
8649 fcnMakeInterval, QStringLiteral(
"Date and Time" ) )
8675 false, QSet< QString >(),
false, QStringList(), true )
8676 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concat" ), -1, fcnConcat, QStringLiteral(
"String" ), QString(),
false, QSet<QString>(),
false, QStringList(), true )
8694 fcnColorMixRgb, QStringLiteral(
"Color" ) )
8698 fcnColorMix, QStringLiteral(
"Color" ) )
8702 fcnColorRgb, QStringLiteral(
"Color" ) )
8707 fcnColorRgbF, QStringLiteral(
"Color" ) )
8712 fncColorRgba, QStringLiteral(
"Color" ) )
8721 fcnCreateRamp, QStringLiteral(
"Color" ) )
8725 fcnColorHsl, QStringLiteral(
"Color" ) )
8730 fncColorHsla, QStringLiteral(
"Color" ) )
8735 fcnColorHslF, QStringLiteral(
"Color" ) )
8739 fcnColorHsv, QStringLiteral(
"Color" ) )
8744 fncColorHsva, QStringLiteral(
"Color" ) )
8749 fcnColorHsvF, QStringLiteral(
"Color" ) )
8754 fcnColorCmyk, QStringLiteral(
"Color" ) )
8760 fncColorCmyka, QStringLiteral(
"Color" ) )
8766 fcnColorCmykF, QStringLiteral(
"Color" ) )
8769 fncColorPart, QStringLiteral(
"Color" ) )
8772 fncDarker, QStringLiteral(
"Color" ) )
8775 fncLighter, QStringLiteral(
"Color" ) )
8780 fcnBaseFileName, QStringLiteral(
"Files and Paths" ) )
8782 fcnFileSuffix, QStringLiteral(
"Files and Paths" ) )
8784 fcnFileExists, QStringLiteral(
"Files and Paths" ) )
8786 fcnFileName, QStringLiteral(
"Files and Paths" ) )
8788 fcnPathIsFile, QStringLiteral(
"Files and Paths" ) )
8790 fcnPathIsDir, QStringLiteral(
"Files and Paths" ) )
8792 fcnFilePath, QStringLiteral(
"Files and Paths" ) )
8794 fcnFileSize, QStringLiteral(
"Files and Paths" ) )
8797 fcnExif, QStringLiteral(
"Files and Paths" ) )
8799 fcnExifGeoTag, QStringLiteral(
"GeometryGroup" ) )
8803 fcnGenericHash, QStringLiteral(
"Conversions" ) )
8805 fcnHashMd5, QStringLiteral(
"Conversions" ) )
8807 fcnHashSha256, QStringLiteral(
"Conversions" ) )
8811 fcnToBase64, QStringLiteral(
"Conversions" ) )
8813 fcnFromBase64, QStringLiteral(
"Conversions" ) )
8819 geomFunc->setIsStatic(
false );
8820 functions << geomFunc;
8824 functions << areaFunc;
8830 functions << lengthFunc;
8834 functions << perimeterFunc;
8840 fcnRoundness, QStringLiteral(
"GeometryGroup" ) );
8854 QMap< QString, QgsExpressionFunction::FcnEval > geometry_overlay_definitions
8856 { QStringLiteral(
"overlay_intersects" ), fcnGeomOverlayIntersects },
8857 { QStringLiteral(
"overlay_contains" ), fcnGeomOverlayContains },
8858 { QStringLiteral(
"overlay_crosses" ), fcnGeomOverlayCrosses },
8859 { QStringLiteral(
"overlay_equals" ), fcnGeomOverlayEquals },
8860 { QStringLiteral(
"overlay_touches" ), fcnGeomOverlayTouches },
8861 { QStringLiteral(
"overlay_disjoint" ), fcnGeomOverlayDisjoint },
8862 { QStringLiteral(
"overlay_within" ), fcnGeomOverlayWithin },
8864 QMapIterator< QString, QgsExpressionFunction::FcnEval > i( geometry_overlay_definitions );
8865 while ( i.hasNext() )
8882 functions << fcnGeomOverlayFunc;
8895 functions << fcnGeomOverlayNearestFunc;
8908 fcnNodesToPoints, QStringLiteral(
"GeometryGroup" ) )
8910 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect_geometries" ), -1, fcnCollectGeometries, QStringLiteral(
"GeometryGroup" ) )
8915 fcnMakePointM, QStringLiteral(
"GeometryGroup" ) )
8921 fcnMakeTriangle, QStringLiteral(
"GeometryGroup" ) )
8926 fcnMakeCircle, QStringLiteral(
"GeometryGroup" ) )
8933 fcnMakeEllipse, QStringLiteral(
"GeometryGroup" ) )
8939 fcnMakeRegularPolygon, QStringLiteral(
"GeometryGroup" ) )
8943 fcnMakeSquare, QStringLiteral(
"GeometryGroup" ) )
8949 fcnMakeRectangleFrom3Points, QStringLiteral(
"GeometryGroup" ) )
8953#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
8959 }, fcnGeomMakeValid, QStringLiteral(
"GeometryGroup" ) );
8968 functions << xAtFunc;
8973 functions << yAtFunc;
8989 fcnDisjoint, QStringLiteral(
"GeometryGroup" ) )
8992 fcnIntersects, QStringLiteral(
"GeometryGroup" ) )
8995 fcnTouches, QStringLiteral(
"GeometryGroup" ) )
8998 fcnCrosses, QStringLiteral(
"GeometryGroup" ) )
9001 fcnContains, QStringLiteral(
"GeometryGroup" ) )
9004 fcnOverlaps, QStringLiteral(
"GeometryGroup" ) )
9007 fcnWithin, QStringLiteral(
"GeometryGroup" ) )
9011 fcnTranslate, QStringLiteral(
"GeometryGroup" ) )
9016 fcnRotate, QStringLiteral(
"GeometryGroup" ) )
9021 fcnScale, QStringLiteral(
"GeometryGroup" ) )
9032 fcnAffineTransform, QStringLiteral(
"GeometryGroup" ) )
9039 fcnBuffer, QStringLiteral(
"GeometryGroup" ) )
9041 fcnForceRHR, QStringLiteral(
"GeometryGroup" ) )
9043 fcnForcePolygonCW, QStringLiteral(
"GeometryGroup" ) )
9045 fcnForcePolygonCCW, QStringLiteral(
"GeometryGroup" ) )
9055 , fcnTaperedBuffer, QStringLiteral(
"GeometryGroup" ) )
9058 , fcnBufferByM, QStringLiteral(
"GeometryGroup" ) )
9064 fcnOffsetCurve, QStringLiteral(
"GeometryGroup" ) )
9070 fcnSingleSidedBuffer, QStringLiteral(
"GeometryGroup" ) )
9074 fcnExtend, QStringLiteral(
"GeometryGroup" ) )
9083 fcnInteriorRingN, QStringLiteral(
"GeometryGroup" ) )
9086 fcnGeometryN, QStringLiteral(
"GeometryGroup" ) )
9093 }, fcnSharedPaths, QStringLiteral(
"GeometryGroup" ) )
9107 }, fcnTriangularWave, QStringLiteral(
"GeometryGroup" ) )
9116 }, fcnTriangularWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9123 }, fcnSquareWave, QStringLiteral(
"GeometryGroup" ) )
9132 }, fcnSquareWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9139 }, fcnRoundWave, QStringLiteral(
"GeometryGroup" ) )
9148 }, fcnRoundWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9157 }, fcnApplyDashPattern, QStringLiteral(
"GeometryGroup" ) )
9162 }, fcnDensifyByCount, QStringLiteral(
"GeometryGroup" ) )
9167 }, fcnDensifyByDistance, QStringLiteral(
"GeometryGroup" ) )
9179#
if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
9186 fcnOrientedBBox, QStringLiteral(
"GeometryGroup" ) )
9189 fcnMainAngle, QStringLiteral(
"GeometryGroup" ) )
9193 fcnMinimalCircle, QStringLiteral(
"GeometryGroup" ) )
9196 fcnDifference, QStringLiteral(
"GeometryGroup" ) )
9199 fcnDistance, QStringLiteral(
"GeometryGroup" ) )
9202 fcnHausdorffDistance, QStringLiteral(
"GeometryGroup" ) )
9205 fcnIntersection, QStringLiteral(
"GeometryGroup" ) )
9208 fcnSymDifference, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"symDifference" ) )
9211 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
9214 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
9217 fcnGeomToWKT, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"geomToWKT" ) )
9219 fcnGeomToWKB, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false )
9224 fcnTransformGeometry, QStringLiteral(
"GeometryGroup" ) )
9228 fcnExtrude, QStringLiteral(
"GeometryGroup" ), QString() )
9230 fcnGeomIsMultipart, QStringLiteral(
"GeometryGroup" ) )
9232 fcnZMax, QStringLiteral(
"GeometryGroup" ) )
9234 fcnZMin, QStringLiteral(
"GeometryGroup" ) )
9236 fcnMMax, QStringLiteral(
"GeometryGroup" ) )
9238 fcnMMin, QStringLiteral(
"GeometryGroup" ) )
9240 fcnSinuosity, QStringLiteral(
"GeometryGroup" ) )
9242 fcnStraightDistance2d, QStringLiteral(
"GeometryGroup" ) );
9248 fcnOrderParts, QStringLiteral(
"GeometryGroup" ), QString() );
9253 const QList< QgsExpressionNode *> argList = node->
args()->list();
9256 if ( !argNode->isStatic( parent, context ) )
9264 QString expString = argNode->
eval( parent, context ).toString();
9268 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9280 QString
expression = argNode->
eval( parent, context ).toString();
9282 e.prepare( context );
9288 functions << orderPartsFunc;
9293 fcnClosestPoint, QStringLiteral(
"GeometryGroup" ) )
9296 fcnShortestLine, QStringLiteral(
"GeometryGroup" ) )
9301 fcnLineInterpolatePointByM, QStringLiteral(
"GeometryGroup" ) )
9308 fcnLineLocateM, QStringLiteral(
"GeometryGroup" ) )
9321 functions << idFunc;
9325 functions << currentFeatureFunc;
9327 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" ) );
9329 functions << uuidFunc;
9336 fcnGetFeature, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"QgsExpressionUtils::getFeature" ) )
9339 fcnGetFeatureById, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false );
9344 functions << attributesFunc;
9348 functions << representAttributesFunc;
9356 functions << validateFeature;
9365 functions << validateAttribute;
9368 QStringLiteral(
"maptip" ),
9371 QStringLiteral(
"Record and Attributes" ),
9377 functions << maptipFunc;
9380 QStringLiteral(
"display_expression" ),
9382 fcnFeatureDisplayExpression,
9383 QStringLiteral(
"Record and Attributes" ),
9389 functions << displayFunc;
9392 QStringLiteral(
"is_selected" ),
9395 QStringLiteral(
"Record and Attributes" ),
9401 functions << isSelectedFunc;
9405 QStringLiteral(
"num_selected" ),
9408 QStringLiteral(
"Record and Attributes" ),
9416 QStringLiteral(
"sqlite_fetch_and_increment" ),
9424 fcnSqliteFetchAndIncrement,
9425 QStringLiteral(
"Record and Attributes" )
9449 parent->
setEvalErrorString( tr(
"If represent_value is called with 1 parameter, it must be an attribute." ) );
9459 parent->
setEvalErrorString( tr(
"represent_value must be called with exactly 1 or 2 parameters." ) );
9465 functions << representValueFunc;
9471 fcnGetLayerProperty, QStringLiteral(
"Map Layers" ) )
9476 fcnDecodeUri, QStringLiteral(
"Map Layers" ) )
9480 fcnMimeType, QStringLiteral(
"General" ) )
9497 QgsExpressionNode *argNode = node->args()->at( 0 );
9499 if ( !argNode->isStatic( parent, context ) )
9502 const QString varName = argNode->eval( parent, context ).toString();
9503 if ( varName == QLatin1String(
"feature" ) || varName == QLatin1String(
"id" ) || varName == QLatin1String(
"geometry" ) )
9506 const QgsExpressionContextScope *scope = context->activeScopeForVariable( varName );
9507 return scope ? scope->isStatic( varName ) : false;
9515 if ( node && node->
args()->
count() > 0 )
9520 if ( literal->value() == QLatin1String(
"geometry" ) || literal->value() == QLatin1String(
"feature" ) )
9537 QgsExpressionNode *argNode = node->args()->at( 0 );
9539 if ( argNode->isStatic( parent, context ) )
9541 QString expString = argNode->eval( parent, context ).toString();
9543 QgsExpression e( expString );
9545 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9552 functions << evalTemplateFunction;
9560 QgsExpressionNode *argNode = node->args()->at( 0 );
9562 if ( argNode->isStatic( parent, context ) )
9564 QString expString = argNode->eval( parent, context ).toString();
9566 QgsExpression e( expString );
9568 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9576 functions << evalFunc;
9582 const QList< QgsExpressionNode *> argList = node->
args()->list();
9585 if ( !argNode->
isStatic( parent, context ) )
9597 functions << attributeFunc;
9608 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array" ), -1, fcnArray, QStringLiteral(
"Arrays" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
9657 fcnMapPrefixKeys, QStringLiteral(
"Maps" ) )
9659 fcnMapToHtmlTable, QStringLiteral(
"Maps" ) )
9661 fcnMapToHtmlDefinitionList, QStringLiteral(
"Maps" ) )
9663 fcnToFormUrlEncode, QStringLiteral(
"Maps" ) )
9672 *sOwnedFunctions() << func;
9673 *sBuiltinFunctions() << func->name();
9674 sBuiltinFunctions()->append( func->aliases() );
9688 QMutexLocker locker( &sFunctionsMutex );
9689 sFunctions()->append( function );
9690 if ( transferOwnership )
9691 sOwnedFunctions()->append( function );
9706 QMutexLocker locker( &sFunctionsMutex );
9707 sFunctions()->removeAt( fnIdx );
9708 sFunctionIndexMap.clear();
9716 qDeleteAll( *sOwnedFunctions() );
9717 sOwnedFunctions()->clear();
9722 if ( sBuiltinFunctions()->isEmpty() )
9726 return *sBuiltinFunctions();
9733 QStringLiteral(
"Arrays" ) )
9744 if ( args->
count() < 2 )
9747 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9757 QVariantList result;
9759 if ( args->
count() < 2 )
9763 QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9766 std::unique_ptr< QgsExpressionContext > tempContext;
9769 tempContext = std::make_unique< QgsExpressionContext >();
9770 subContext = tempContext.get();
9777 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it, ++i )
9781 result << args->
at( 1 )->
eval( parent, subContext );
9806 if ( args->
count() < 2 )
9810 args->
at( 0 )->
prepare( parent, context );
9814 subContext = *context;
9821 args->
at( 1 )->
prepare( parent, &subContext );
9831 QStringLiteral(
"Arrays" ) )
9842 if ( args->
count() < 2 )
9845 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9855 QVariantList result;
9857 if ( args->
count() < 2 )
9861 const QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9864 std::unique_ptr< QgsExpressionContext > tempContext;
9867 tempContext = std::make_unique< QgsExpressionContext >();
9868 subContext = tempContext.get();
9875 if ( args->
count() >= 3 )
9877 const QVariant limitVar = args->
at( 2 )->
eval( parent, context );
9879 if ( QgsExpressionUtils::isIntSafe( limitVar ) )
9881 limit = limitVar.toInt();
9889 for (
const QVariant &value : array )
9892 if ( args->
at( 1 )->
eval( parent, subContext ).toBool() )
9896 if ( limit > 0 && limit == result.size() )
9896 if ( limit > 0 && limit == result.size() ) {
…}
9923 if ( args->
count() < 2 )
9927 args->
at( 0 )->
prepare( parent, context );
9931 subContext = *context;
9937 args->
at( 1 )->
prepare( parent, &subContext );
9946 QStringLiteral(
"General" ) )
9957 if ( args->
count() < 3 )
9961 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9963 QVariant
name = args->
at( 0 )->
eval( parent, context );
9964 QVariant value = args->
at( 1 )->
eval( parent, context );
9967 appendTemporaryVariable( context,
name.toString(), value );
9968 if ( args->
at( 2 )->
isStatic( parent, context ) )
9970 popTemporaryVariable( context );
9981 if ( args->
count() < 3 )
9985 QVariant
name = args->
at( 0 )->
eval( parent, context );
9986 QVariant value = args->
at( 1 )->
eval( parent, context );
9989 std::unique_ptr< QgsExpressionContext > tempContext;
9990 if ( !updatedContext )
9992 tempContext = std::make_unique< QgsExpressionContext >();
9993 updatedContext = tempContext.get();
9996 appendTemporaryVariable( updatedContext,
name.toString(), value );
9997 result = args->
at( 2 )->
eval( parent, updatedContext );
10000 popTemporaryVariable( updatedContext );
10009 Q_UNUSED( context )
10021 if ( args->
count() < 3 )
10026 QVariant value = args->
at( 1 )->
prepare( parent, context );
10029 std::unique_ptr< QgsExpressionContext > tempContext;
10030 if ( !updatedContext )
10032 tempContext = std::make_unique< QgsExpressionContext >();
10033 updatedContext = tempContext.get();
10036 appendTemporaryVariable( updatedContext,
name.toString(), value );
10037 args->
at( 2 )->
prepare( parent, updatedContext );
10040 popTemporaryVariable( updatedContext );
10045void QgsWithVariableExpressionFunction::popTemporaryVariable(
const QgsExpressionContext *context )
const
10048 delete updatedContext->
popScope();
10051void 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.
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.
An 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 its 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.
Handles 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.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsFeatureRequest & setRequestMayBeNested(bool requestMayBeNested)
In case this request may be run nested within another already running iteration on the same connectio...
QgsFeatureRequest & setTimeout(int timeout)
Sets the timeout (in milliseconds) for the maximum time we should wait during feature requests before...
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
void setFeedback(QgsFeedback *feedback)
Attach a feedback object that can be queried regularly by the iterator to check if it should be cance...
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Sets the feature ID that should be fetched.
QgsVectorLayer * materialize(const QgsFeatureRequest &request, QgsFeedback *feedback=nullptr)
Materializes a request (query) made against this feature source, by running it over the source and re...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
bool isValid() const
Returns the validity of this feature.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
ConstraintStrength
Strength of constraints.
@ ConstraintStrengthNotSet
Constraint is not set.
@ ConstraintStrengthSoft
User is warned if constraint is violated but feature can still be accepted.
@ ConstraintStrengthHard
Constraint must be honored before feature can be accepted.
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Container of fields for a vector layer.
Q_INVOKABLE int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
int size() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
virtual bool removeGeometry(int nr)
Removes a geometry from the collection.
QgsGeometryCollection * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
int partCount() const override
Returns count of parts contained in the geometry.
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
static QVector< QgsLineString * > extractLineStrings(const QgsAbstractGeometry *geom)
Returns list of linestrings extracted from the passed geometry.
A geometry is the spatial representation of a feature.
double hausdorffDistanceDensify(const QgsGeometry &geom, double densifyFraction) const
Returns the Hausdorff distance between this geometry and geom.
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Returns a copy of the geometry which has been densified by adding the specified number of extra nodes...
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
double lineLocatePoint(const QgsGeometry &point) const
Returns a distance representing the location along this linestring of the closest point on this lines...
QgsGeometry difference(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing the points making up this geometry that do not make up other.
double length() const
Returns the planar, 2-dimensional length of geometry.
QgsGeometry offsetCurve(double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
QgsGeometry poleOfInaccessibility(double precision, double *distanceToBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
QgsGeometry squareWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs square waves along the boundary of the geometry, with the specified wavelength and amplitu...
QgsGeometry triangularWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs triangular waves along the boundary of the geometry, with the specified wavelength and amp...
bool vertexIdFromVertexNr(int number, QgsVertexId &id) const
Calculates the vertex ID from a vertex number.
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
bool touches(const QgsGeometry &geometry) const
Returns true if the geometry touches another geometry.
QgsGeometry applyDashPattern(const QVector< double > &pattern, Qgis::DashPatternLineEndingRule startRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternLineEndingRule endRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternSizeAdjustment adjustment=Qgis::DashPatternSizeAdjustment::ScaleBothDashAndGap, double patternOffset=0) const
Applies a dash pattern to a geometry, returning a MultiLineString geometry which is the input geometr...
QgsGeometry roundWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs rounded (sine-like) waves along the boundary of the geometry, with the specified wavelengt...
QgsGeometry nearestPoint(const QgsGeometry &other) const
Returns the nearest (closest) point on this geometry to another geometry.
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
QgsGeometry mergeLines(const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Merges any connected lines in a LineString/MultiLineString geometry and converts them to single line ...
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.
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.
static QString build(const QVariantMap &map)
Build a hstore-formatted string from a QVariantMap.
static QVariantMap parse(const QString &string)
Returns a QVariantMap object containing the key and values from a hstore-formatted string.
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 a geometry simplifier 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.
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.
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.
Allows creation of a multi-layer database-side transaction.
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 dataset.
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 Q_INVOKABLE bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static Q_INVOKABLE QString geometryDisplayString(Qgis::GeometryType type)
Returns a display string for a geometry type.
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)
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.