68#include <QMimeDatabase>
69#include <QProcessEnvironment>
70#include <QCryptographicHash>
71#include <QRegularExpression>
94 QVariantList argValues;
98 const QList< QgsExpressionNode * > argList = args->
list();
105 v = QVariant::fromValue( n );
109 v = n->eval( parent, context );
111 bool defaultParamIsNull = mParameterList.count() > arg && mParameterList.at( arg ).optional() && !mParameterList.at( arg ).defaultValue().isValid();
112 if ( QgsExpressionUtils::isNull( v ) && !defaultParamIsNull && !
handlesNull() )
115 argValues.append( v );
120 return func( argValues, context, parent, node );
131 return QStringList();
158 return mGroups.isEmpty() ? false : mGroups.contains( QStringLiteral(
"deprecated" ) );
163 return ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 );
175 const QString &group,
176 const QString &helpText,
180 const QStringList &aliases,
184 , mAliases( aliases )
185 , mUsesGeometry( false )
186 , mUsesGeometryFunc( usesGeometry )
187 , mReferencedColumnsFunc( referencedColumns )
199 if ( mUsesGeometryFunc )
200 return mUsesGeometryFunc( node );
202 return mUsesGeometry;
212 if ( mReferencedColumnsFunc )
213 return mReferencedColumnsFunc( node );
215 return mReferencedColumns;
221 return mIsStaticFunc( node, parent, context );
229 return mPrepareFunc( node, parent, context );
241 mIsStaticFunc =
nullptr;
247 mPrepareFunc = prepareFunc;
252 if ( node && node->
args() )
254 const QList< QgsExpressionNode * > argList = node->
args()->
list();
257 if ( !argNode->isStatic( parent, context ) )
267 double start = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
268 double stop = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
269 double step = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
271 if ( step == 0.0 || ( step > 0.0 && start > stop ) || ( step < 0.0 && start < stop ) )
278 double current = start + step;
279 while ( ( ( step > 0.0 && current <= stop ) || ( step < 0.0 && current >= stop ) ) && length <= 1000000 )
294 const QString name = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
296 if ( name == QLatin1String(
"feature" ) )
298 return context->
hasFeature() ? QVariant::fromValue( context->
feature() ) : QVariant();
300 else if ( name == QLatin1String(
"id" ) )
302 return context->
hasFeature() ? QVariant::fromValue( context->
feature().
id() ) : QVariant();
304 else if ( name == QLatin1String(
"geometry" ) )
320 QString templateString = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
329 QString expString = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
331 return expression.evaluate( context );
336 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
337 return QVariant( std::sqrt( x ) );
342 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
343 return QVariant( std::fabs( val ) );
348 double deg = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
349 return ( deg * M_PI ) / 180;
353 double rad = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
354 return ( 180 * rad ) / M_PI;
358 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
359 return QVariant( std::sin( x ) );
363 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
364 return QVariant( std::cos( x ) );
368 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
369 return QVariant( std::tan( x ) );
373 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
374 return QVariant( std::asin( x ) );
378 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
379 return QVariant( std::acos( x ) );
383 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
384 return QVariant( std::atan( x ) );
388 double y = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
389 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
390 return QVariant( std::atan2( y, x ) );
394 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
395 return QVariant( std::exp( x ) );
399 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
402 return QVariant( std::log( x ) );
406 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
409 return QVariant( log10( x ) );
413 double b = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
414 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
415 if ( x <= 0 || b <= 0 )
417 return QVariant( std::log( x ) / std::log( b ) );
421 double min = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
422 double max = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
426 std::random_device rd;
427 std::mt19937_64 generator( rd() );
429 if ( !QgsExpressionUtils::isNull( values.at( 2 ) ) )
432 if ( QgsExpressionUtils::isIntSafe( values.at( 2 ) ) )
435 seed = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
440 QString seedStr = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
441 std::hash<std::string> hasher;
442 seed = hasher( seedStr.toStdString() );
444 generator.seed( seed );
448 double f =
static_cast< double >( generator() ) /
static_cast< double >( std::mt19937_64::max() );
449 return QVariant( min + f * ( max - min ) );
453 qlonglong min = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
454 qlonglong max = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
458 std::random_device rd;
459 std::mt19937_64 generator( rd() );
461 if ( !QgsExpressionUtils::isNull( values.at( 2 ) ) )
464 if ( QgsExpressionUtils::isIntSafe( values.at( 2 ) ) )
467 seed = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
472 QString seedStr = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
473 std::hash<std::string> hasher;
474 seed = hasher( seedStr.toStdString() );
476 generator.seed( seed );
479 qint64 randomInteger = min + ( generator() % ( max - min + 1 ) );
480 if ( randomInteger > std::numeric_limits<int>::max() || randomInteger < -std::numeric_limits<int>::max() )
481 return QVariant( randomInteger );
484 return QVariant(
int( randomInteger ) );
489 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
490 double domainMin = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
491 double domainMax = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
492 double rangeMin = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
493 double rangeMax = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
495 if ( domainMin >= domainMax )
497 parent->
setEvalErrorString( QObject::tr(
"Domain max must be greater than domain min" ) );
502 if ( val >= domainMax )
506 else if ( val <= domainMin )
512 double m = ( rangeMax - rangeMin ) / ( domainMax - domainMin );
513 double c = rangeMin - ( domainMin * m );
516 return QVariant( m * val +
c );
521 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
522 double domainMin = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
523 double domainMax = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
524 double rangeMin = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
525 double rangeMax = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
526 double exponent = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
528 if ( domainMin >= domainMax )
530 parent->
setEvalErrorString( QObject::tr(
"Domain max must be greater than domain min" ) );
540 if ( val >= domainMax )
544 else if ( val <= domainMin )
550 return QVariant( ( ( rangeMax - rangeMin ) / std::pow( domainMax - domainMin, exponent ) ) * std::pow( val - domainMin, exponent ) + rangeMin );
555 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
556 double domainMin = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
557 double domainMax = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
558 double rangeMin = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
559 double rangeMax = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
560 double exponent = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
562 if ( domainMin >= domainMax )
564 parent->
setEvalErrorString( QObject::tr(
"Domain max must be greater than domain min" ) );
574 if ( val >= domainMax )
578 else if ( val <= domainMin )
584 double ratio = ( std::pow( exponent, val - domainMin ) - 1 ) / ( std::pow( exponent, domainMax - domainMin ) - 1 );
585 return QVariant( ( rangeMax - rangeMin ) * ratio + rangeMin );
591 double maxVal = std::numeric_limits<double>::quiet_NaN();
592 for (
const QVariant &val : values )
595 if ( std::isnan( maxVal ) )
599 else if ( !std::isnan( testVal ) )
601 maxVal = std::max( maxVal, testVal );
605 if ( !std::isnan( maxVal ) )
607 result = QVariant( maxVal );
615 double minVal = std::numeric_limits<double>::quiet_NaN();
616 for (
const QVariant &val : values )
619 if ( std::isnan( minVal ) )
623 else if ( !std::isnan( testVal ) )
625 minVal = std::min( minVal, testVal );
629 if ( !std::isnan( minVal ) )
631 result = QVariant( minVal );
643 QVariant value = node->
eval( parent, context );
648 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( value, context, parent );
652 parent->
setEvalErrorString( QObject::tr(
"Cannot find layer with name or ID '%1'" ).arg( value.toString() ) );
657 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
659 value = node->
eval( parent, context );
665 parent->
setEvalErrorString( QObject::tr(
"No such aggregate '%1'" ).arg( value.toString() ) );
670 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
672 QString subExpression = node->
dump();
676 if ( values.count() > 3 )
678 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
681 if ( !nl || nl->value().isValid() )
686 if ( values.count() > 4 )
688 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
690 value = node->
eval( parent, context );
697 if ( values.count() > 5 )
699 node = QgsExpressionUtils::getNode( values.at( 5 ), parent );
702 if ( !nl || nl->value().isValid() )
704 orderBy = node->
dump();
709 QString aggregateError;
717 const QSet< QString > filterVars = filterExp.referencedVariables();
718 const QSet< QString > subExpVars = subExp.referencedVariables();
719 QSet<QString> allVars = filterVars + subExpVars;
721 bool isStatic =
true;
722 if ( filterVars.contains( QStringLiteral(
"parent" ) )
723 || filterVars.contains( QString() )
724 || subExpVars.contains( QStringLiteral(
"parent" ) )
725 || subExpVars.contains( QString() ) )
731 for (
const QString &varName : allVars )
734 if ( scope && !scope->
isStatic( varName ) )
742 if ( isStatic && ! parameters.
orderBy.isEmpty() )
744 for (
const auto &orderByClause : std::as_const( parameters.orderBy ) )
747 if ( orderByExpression.referencedVariables().contains( QStringLiteral(
"parent" ) ) || orderByExpression.referencedVariables().contains( QString() ) )
758 const QString contextHash = context->
uniqueHash( ok, allVars );
761 cacheKey = QStringLiteral(
"aggfcn:%1:%2:%3:%4:%5:%6" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter,
762 orderBy, contextHash );
767 cacheKey = QStringLiteral(
"aggfcn:%1:%2:%3:%4:%5" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter, orderBy );
778 subContext.appendScope( subScope );
779 result = vl->aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &aggregateError );
781 if ( ok && !cacheKey.isEmpty() )
791 result = vl->aggregate( aggregate, subExpression, parameters,
nullptr, &ok,
nullptr,
nullptr, &aggregateError );
795 if ( !aggregateError.isEmpty() )
796 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, aggregateError ) );
798 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
809 parent->
setEvalErrorString( QObject::tr(
"Cannot use relation aggregate function in this context" ) );
817 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
821 parent->
setEvalErrorString( QObject::tr(
"Cannot use relation aggregate function in this context" ) );
830 QVariant value = node->
eval( parent, context );
832 QString relationId = value.toString();
839 if ( relations.isEmpty() || relations.at( 0 ).referencedLayer() != vl )
841 parent->
setEvalErrorString( QObject::tr(
"Cannot find relation with id '%1'" ).arg( relationId ) );
846 relation = relations.at( 0 );
853 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
855 value = node->
eval( parent, context );
861 parent->
setEvalErrorString( QObject::tr(
"No such aggregate '%1'" ).arg( value.toString() ) );
866 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
868 QString subExpression = node->
dump();
872 if ( values.count() > 3 )
874 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
876 value = node->
eval( parent, context );
883 if ( values.count() > 4 )
885 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
888 if ( !nl || nl->value().isValid() )
890 orderBy = node->
dump();
901 const QString cacheKey = QStringLiteral(
"relagg:%1%:%2:%3:%4:%5:%6" ).arg( relationId, vl->id(),
902 QString::number(
static_cast< int >( aggregate ) ),
915 result = childLayer->
aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &error );
919 if ( !error.isEmpty() )
920 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, error ) );
922 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
936 parent->
setEvalErrorString( QObject::tr(
"Cannot use aggregate function in this context" ) );
944 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
948 parent->
setEvalErrorString( QObject::tr(
"Cannot use aggregate function in this context" ) );
957 QString subExpression = node->
dump();
961 if ( values.count() > 1 )
963 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
966 if ( !nl || nl->value().isValid() )
967 groupBy = node->
dump();
971 if ( values.count() > 2 )
973 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
976 if ( !nl || nl->value().isValid() )
982 if ( orderByPos >= 0 && values.count() > orderByPos )
984 node = QgsExpressionUtils::getNode( values.at( orderByPos ), parent );
987 if ( !nl || nl->value().isValid() )
989 orderBy = node->
dump();
997 if ( !groupBy.isEmpty() )
1000 QVariant groupByValue = groupByExp.evaluate( context );
1001 QString groupByClause = QStringLiteral(
"%1 %2 %3" ).arg( groupBy,
1004 if ( !parameters.
filter.isEmpty() )
1005 parameters.
filter = QStringLiteral(
"(%1) AND (%2)" ).arg( parameters.
filter, groupByClause );
1007 parameters.
filter = groupByClause;
1013 bool isStatic =
true;
1014 const QSet<QString> refVars = filterExp.referencedVariables() + subExp.referencedVariables();
1015 for (
const QString &varName : refVars )
1018 if ( scope && !scope->
isStatic( varName ) )
1029 const QString contextHash = context->
uniqueHash( ok, refVars );
1032 cacheKey = QStringLiteral(
"agg:%1:%2:%3:%4:%5:%6" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter,
1033 orderBy, contextHash );
1038 cacheKey = QStringLiteral(
"agg:%1:%2:%3:%4:%5" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter, orderBy );
1050 subContext.appendScope( subScope );
1052 result = vl->aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &error );
1056 if ( !error.isEmpty() )
1057 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, error ) );
1059 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
1164 if ( values.count() > 3 )
1166 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
1168 QVariant value = node->
eval( parent, context );
1170 parameters.
delimiter = value.toString();
1181 if ( values.count() > 3 )
1183 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
1185 QVariant value = node->
eval( parent, context );
1187 parameters.
delimiter = value.toString();
1203 QVariant scale = context->
variable( QStringLiteral(
"map_scale" ) );
1208 const double v = scale.toDouble( &ok );
1216 double minValue = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1217 double testValue = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1218 double maxValue = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1221 if ( testValue <= minValue )
1223 return QVariant( minValue );
1225 else if ( testValue >= maxValue )
1227 return QVariant( maxValue );
1231 return QVariant( testValue );
1237 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1238 return QVariant( std::floor( x ) );
1243 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1244 return QVariant( std::ceil( x ) );
1249 const QVariant value = values.at( 0 );
1250 if ( QgsExpressionUtils::isNull( value.isValid() ) )
1252 return QVariant(
false );
1254 else if ( value.userType() == QMetaType::QString )
1257 return QVariant( !value.toString().isEmpty() );
1259 else if ( QgsExpressionUtils::isList( value ) )
1261 return !value.toList().isEmpty();
1263 return QVariant( value.toBool() );
1267 return QVariant( QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) );
1271 return QVariant( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) );
1275 return QVariant( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ) );
1280 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1281 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1282 if ( format.isEmpty() && !language.isEmpty() )
1284 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to DateTime when the language is specified" ) );
1285 return QVariant( QDateTime() );
1288 if ( format.isEmpty() && language.isEmpty() )
1289 return QVariant( QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent ) );
1291 QString datetimestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1292 QLocale locale = QLocale();
1293 if ( !language.isEmpty() )
1295 locale = QLocale( language );
1298 QDateTime datetime = locale.toDateTime( datetimestring, format );
1299 if ( !datetime.isValid() )
1301 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to DateTime" ).arg( datetimestring ) );
1302 datetime = QDateTime();
1304 return QVariant( datetime );
1309 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1310 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1311 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1313 const QDate date( year, month, day );
1314 if ( !date.isValid() )
1316 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1319 return QVariant( date );
1324 const int hours = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1325 const int minutes = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1326 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1328 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1329 if ( !time.isValid() )
1331 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1334 return QVariant( time );
1339 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1340 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1341 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1342 const int hours = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
1343 const int minutes = QgsExpressionUtils::getIntValue( values.at( 4 ), parent );
1344 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1346 const QDate date( year, month, day );
1347 if ( !date.isValid() )
1349 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1352 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1353 if ( !time.isValid() )
1355 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1358 return QVariant( QDateTime( date, time ) );
1363 const double years = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1364 const double months = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1365 const double weeks = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1366 const double days = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
1367 const double hours = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
1368 const double minutes = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1369 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
1371 return QVariant::fromValue(
QgsInterval( years, months, weeks, days, hours, minutes, seconds ) );
1376 for (
const QVariant &value : values )
1387 const QVariant val1 = values.at( 0 );
1388 const QVariant val2 = values.at( 1 );
1398 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1399 return QVariant( str.toLower() );
1403 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1404 return QVariant( str.toUpper() );
1408 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1409 QStringList elems = str.split(
' ' );
1410 for (
int i = 0; i < elems.size(); i++ )
1412 if ( elems[i].size() > 1 )
1413 elems[i] = elems[i].at( 0 ).toUpper() + elems[i].mid( 1 ).toLower();
1415 return QVariant( elems.join( QLatin1Char(
' ' ) ) );
1420 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1421 return QVariant( str.trimmed() );
1426 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1428 const QString characters = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1430 const QRegularExpression re( QStringLiteral(
"^([%1]*)" ).arg( QRegularExpression::escape( characters ) ) );
1431 str.replace( re, QString() );
1432 return QVariant( str );
1437 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1439 const QString characters = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1441 const QRegularExpression re( QStringLiteral(
"([%1]*)$" ).arg( QRegularExpression::escape( characters ) ) );
1442 str.replace( re, QString() );
1443 return QVariant( str );
1448 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1449 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1455 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1456 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1462 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1463 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1465 return ( dist < 0 ? QVariant() : QVariant(
QgsStringUtils::hammingDistance( string1, string2, true ) ) );
1470 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1476 QChar character = QChar( QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent ) );
1477 return QVariant( QString( character ) );
1482 QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1484 if ( value.isEmpty() )
1489 int res = value.at( 0 ).unicode();
1490 return QVariant( res );
1495 if ( values.length() == 2 || values.length() == 3 )
1497 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1498 qlonglong wrap = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1500 QString customdelimiter = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1513 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent,
true );
1517 return QVariant( geom.
length() );
1523 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1524 return QVariant( str.length() );
1529 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
1534 double totalLength = 0;
1537 if (
const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( *it ) )
1539 totalLength += line->length3D();
1543 std::unique_ptr< QgsLineString > segmentized( qgsgeometry_cast< const QgsCurve * >( *it )->curveToLine() );
1544 totalLength += segmentized->length3D();
1553 if ( values.count() == 2 && values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
1555 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1556 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
1557 QVector< QPair< QString, QString > > mapItems;
1559 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
1561 mapItems.append( qMakePair( it.key(), it.value().toString() ) );
1565 std::sort( mapItems.begin(),
1567 [](
const QPair< QString, QString > &pair1,
1568 const QPair< QString, QString > &pair2 )
1570 return ( pair1.first.length() > pair2.first.length() );
1573 for (
auto it = mapItems.constBegin(); it != mapItems.constEnd(); ++it )
1575 str = str.replace( it->first, it->second );
1578 return QVariant( str );
1580 else if ( values.count() == 3 )
1582 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1583 QVariantList before;
1585 bool isSingleReplacement =
false;
1587 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).userType() != QMetaType::Type::QStringList )
1589 before = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1593 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
1596 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
1598 after = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1599 isSingleReplacement =
true;
1603 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
1606 if ( !isSingleReplacement && before.length() != after.length() )
1608 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
1612 for (
int i = 0; i < before.length(); i++ )
1614 str = str.replace( before.at( i ).toString(), after.at( isSingleReplacement ? 0 : i ).toString() );
1617 return QVariant( str );
1621 parent->
setEvalErrorString( QObject::tr(
"Function replace requires 2 or 3 arguments" ) );
1628 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1629 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1630 QString after = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1632 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1633 if ( !re.isValid() )
1635 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1638 return QVariant( str.replace( re, after ) );
1643 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1644 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1646 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1647 if ( !re.isValid() )
1649 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1652 return QVariant( ( str.indexOf( re ) + 1 ) );
1657 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1658 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1659 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1661 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1662 if ( !re.isValid() )
1664 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1668 QRegularExpressionMatch matches = re.match( str );
1669 if ( matches.hasMatch() )
1672 QStringList list = matches.capturedTexts();
1675 for ( QStringList::const_iterator it = ++list.constBegin(); it != list.constEnd(); ++it )
1677 array += ( !( *it ).isEmpty() ) ? *it : empty;
1680 return QVariant( array );
1690 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1691 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1693 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1694 if ( !re.isValid() )
1696 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1701 QRegularExpressionMatch match = re.match( str );
1702 if ( match.hasMatch() )
1705 if ( match.lastCapturedIndex() > 0 )
1708 return QVariant( match.captured( 1 ) );
1713 return QVariant( match.captured( 0 ) );
1718 return QVariant(
"" );
1724 QString uuid = QUuid::createUuid().toString();
1725 if ( values.at( 0 ).toString().compare( QStringLiteral(
"WithoutBraces" ), Qt::CaseInsensitive ) == 0 )
1726 uuid = QUuid::createUuid().toString( QUuid::StringFormat::WithoutBraces );
1727 else if ( values.at( 0 ).toString().compare( QStringLiteral(
"Id128" ), Qt::CaseInsensitive ) == 0 )
1728 uuid = QUuid::createUuid().toString( QUuid::StringFormat::Id128 );
1734 if ( !values.at( 0 ).isValid() || !values.at( 1 ).isValid() )
1737 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1738 int from = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1741 if ( values.at( 2 ).isValid() )
1742 len = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
1748 from = str.size() + from;
1754 else if ( from > 0 )
1762 len = str.size() + len - from;
1769 return QVariant( str.mid( from, len ) );
1775 return QVariant(
static_cast< int >( f.
id() ) );
1780 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1781 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
1782 bool foundLayer =
false;
1783 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, geom](
QgsMapLayer * mapLayer )
1785 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer * >( mapLayer );
1786 if ( !layer || !layer->dataProvider() )
1788 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1792 if ( bandNb < 1 || bandNb > layer->bandCount() )
1794 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster band number." ) );
1800 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid point geometry." ) );
1808 if ( multiPoint.count() == 1 )
1810 point = multiPoint[0];
1819 double value = layer->dataProvider()->sample( point, bandNb );
1820 return std::isnan( value ) ? QVariant() : value;
1826 parent->
setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1837 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1838 const double value = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1840 bool foundLayer =
false;
1841 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, value](
QgsMapLayer * mapLayer )-> QVariant
1843 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer *>( mapLayer );
1844 if ( !layer || !layer->dataProvider() )
1846 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1850 if ( bandNb < 1 || bandNb > layer->bandCount() )
1852 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster band number." ) );
1856 if ( std::isnan( value ) )
1858 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster value." ) );
1862 if ( ! layer->dataProvider()->attributeTable( bandNb ) )
1867 const QVariantList data = layer->dataProvider()->attributeTable( bandNb )->row( value );
1868 if ( data.isEmpty() )
1874 const QList<QgsRasterAttributeTable::Field> fields { layer->dataProvider()->attributeTable( bandNb )->fields() };
1875 for (
int idx = 0; idx < static_cast<int>( fields.count( ) ) && idx < static_cast<int>( data.count() ); ++idx )
1878 if ( field.isColor() || field.isRamp() )
1882 result.insert( fields.at( idx ).name, data.at( idx ) );
1890 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1911 if ( values.size() == 1 )
1913 attr = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1916 else if ( values.size() == 2 )
1918 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
1919 attr = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1923 parent->
setEvalErrorString( QObject::tr(
"Function `attribute` requires one or two parameters. %n given.",
nullptr, values.length() ) );
1932 QString table { R
"html(
1935 <tr><th>%1</th></tr>
1938 <tr><td>%2</td></tr>
1942 if ( values.size() == 1 )
1944 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1948 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_table` requires one parameter. %n given.",
nullptr, values.length() ) );
1952 if ( dict.isEmpty() )
1957 QStringList headers;
1960 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
1962 headers.push_back( it.key().toHtmlEscaped() );
1963 cells.push_back( it.value().toString( ).toHtmlEscaped() );
1966 return table.arg( headers.join( QLatin1String(
"</th><th>" ) ), cells.join( QLatin1String(
"</td><td>" ) ) );
1971 QString table { R
"html(
1976 if ( values.size() == 1 )
1978 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1982 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_dl` requires one parameter. %n given.",
nullptr, values.length() ) );
1986 if ( dict.isEmpty() )
1993 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
1995 rows.append( QStringLiteral(
"<dt>%1</dt><dd>%2</dd>" ).arg( it.key().toHtmlEscaped(), it.value().toString().toHtmlEscaped() ) );
1998 return table.arg( rows );
2006 layer = context->
variable( QStringLiteral(
"layer" ) );
2011 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
2013 layer = node->
eval( parent, context );
2024 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2028 const QString strength = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).toLower();
2029 if ( strength == QLatin1String(
"hard" ) )
2033 else if ( strength == QLatin1String(
"soft" ) )
2038 bool foundLayer =
false;
2039 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
2041 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2044 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2050 for (
int i = 0; i < fields.
size(); i++ )
2065 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2077 layer = context->
variable( QStringLiteral(
"layer" ) );
2082 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
2084 layer = node->
eval( parent, context );
2095 feature = QgsExpressionUtils::getFeature( values.at( 2 ), parent );
2099 const QString strength = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).toLower();
2100 if ( strength == QLatin1String(
"hard" ) )
2104 else if ( strength == QLatin1String(
"soft" ) )
2109 const QString attributeName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2111 bool foundLayer =
false;
2112 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, attributeName, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
2114 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2121 if ( fieldIndex == -1 )
2123 parent->
setEvalErrorString( QObject::tr(
"The attribute name did not match any field for the given feature" ) );
2134 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2150 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2155 for (
int i = 0; i < fields.
count(); ++i )
2169 if ( values.isEmpty() )
2172 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2174 else if ( values.size() == 1 )
2176 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2177 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2179 else if ( values.size() == 2 )
2181 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2182 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2186 parent->
setEvalErrorString( QObject::tr(
"Function `represent_attributes` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2193 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: layer could not be resolved." ) );
2199 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: feature could not be resolved." ) );
2205 for (
int fieldIndex = 0; fieldIndex < fields.
count(); ++fieldIndex )
2207 const QString fieldName { fields.
at( fieldIndex ).
name() };
2208 const QVariant attributeVal = feature.
attribute( fieldIndex );
2209 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer->
id(), fieldName, attributeVal.toString() );
2212 result.insert( fieldName, context->
cachedValue( cacheValueKey ) );
2221 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer->
id(), fieldName );
2233 QString value( fieldFormatter->
representValue( layer, fieldIndex, setup.
config(), cache, attributeVal ) );
2235 result.insert( fields.
at( fieldIndex ).
name(), value );
2251 bool evaluate =
true;
2255 if ( values.isEmpty() )
2258 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2260 else if ( values.size() == 1 )
2262 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2263 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2265 else if ( values.size() == 2 )
2267 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2268 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2270 else if ( values.size() == 3 )
2272 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2273 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2274 evaluate = values.value( 2 ).toBool();
2280 parent->
setEvalErrorString( QObject::tr(
"Function `maptip` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2284 parent->
setEvalErrorString( QObject::tr(
"Function `display` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2316 subContext.setFeature( feature );
2325 exp.prepare( &subContext );
2326 return exp.evaluate( &subContext ).toString();
2332 return fcnCoreFeatureMaptipDisplay( values, context, parent,
false );
2337 return fcnCoreFeatureMaptipDisplay( values, context, parent,
true );
2344 if ( values.isEmpty() )
2347 layer = context->
variable( QStringLiteral(
"layer" ) );
2349 else if ( values.size() == 1 )
2351 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2352 layer = context->
variable( QStringLiteral(
"layer" ) );
2354 else if ( values.size() == 2 )
2356 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2357 layer = values.at( 0 );
2361 parent->
setEvalErrorString( QObject::tr(
"Function `is_selected` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2365 bool foundLayer =
false;
2366 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [feature](
QgsMapLayer * mapLayer ) -> QVariant
2368 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2369 if ( !layer || !feature.
isValid() )
2386 if ( values.isEmpty() )
2387 layer = context->
variable( QStringLiteral(
"layer" ) );
2388 else if ( values.count() == 1 )
2389 layer = values.at( 0 );
2392 parent->
setEvalErrorString( QObject::tr(
"Function `num_selected` requires no more than one parameter. %n given.",
nullptr, values.length() ) );
2396 bool foundLayer =
false;
2397 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [](
QgsMapLayer * mapLayer ) -> QVariant
2399 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2415 static QMap<QString, qlonglong> counterCache;
2416 QVariant functionResult;
2418 auto fetchAndIncrementFunc = [ values, parent, &functionResult ](
QgsMapLayer * mapLayer,
const QString & databaseArgument )
2422 const QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( mapLayer );
2427 database = decodedUri.value( QStringLiteral(
"path" ) ).toString();
2428 if ( database.isEmpty() )
2430 parent->
setEvalErrorString( QObject::tr(
"Could not extract file path from layer `%1`." ).arg( layer->
name() ) );
2435 database = databaseArgument;
2438 const QString table = values.at( 1 ).toString();
2439 const QString idColumn = values.at( 2 ).toString();
2440 const QString filterAttribute = values.at( 3 ).toString();
2441 const QVariant filterValue = values.at( 4 ).toString();
2442 const QVariantMap defaultValues = values.at( 5 ).toMap();
2448 if ( sqliteDb.
open_v2( database, SQLITE_OPEN_READWRITE,
nullptr ) != SQLITE_OK )
2451 functionResult = QVariant();
2455 QString errorMessage;
2456 QString currentValSql;
2458 qlonglong nextId = 0;
2459 bool cachedMode =
false;
2460 bool valueRetrieved =
false;
2462 QString cacheString = QStringLiteral(
"%1:%2:%3:%4:%5" ).arg( database, table, idColumn, filterAttribute, filterValue.toString() );
2469 auto cachedCounter = counterCache.find( cacheString );
2471 if ( cachedCounter != counterCache.end() )
2473 qlonglong &cachedValue = cachedCounter.value();
2474 nextId = cachedValue;
2476 cachedValue = nextId;
2477 valueRetrieved =
true;
2482 if ( !cachedMode || !valueRetrieved )
2484 int result = SQLITE_ERROR;
2487 if ( !filterAttribute.isNull() )
2492 sqliteStatement = sqliteDb.
prepare( currentValSql, result );
2494 if ( result == SQLITE_OK )
2497 if ( sqliteStatement.
step() == SQLITE_ROW )
2503 if ( cachedMode && result == SQLITE_OK )
2505 counterCache.insert( cacheString, nextId );
2509 counterCache.remove( cacheString );
2512 valueRetrieved =
true;
2516 if ( valueRetrieved )
2525 if ( !filterAttribute.isNull() )
2531 for ( QVariantMap::const_iterator iter = defaultValues.constBegin(); iter != defaultValues.constEnd(); ++iter )
2534 vals << iter.value().toString();
2537 upsertSql += QLatin1String(
" (" ) + cols.join(
',' ) +
')';
2538 upsertSql += QLatin1String(
" VALUES " );
2539 upsertSql +=
'(' + vals.join(
',' ) +
')';
2541 int result = SQLITE_ERROR;
2545 if ( transaction->
executeSql( upsertSql, errorMessage ) )
2552 result = sqliteDb.
exec( upsertSql, errorMessage );
2554 if ( result == SQLITE_OK )
2556 functionResult = QVariant( nextId );
2561 parent->
setEvalErrorString( QStringLiteral(
"Could not increment value: SQLite error: \"%1\" (%2)." ).arg( errorMessage, QString::number( result ) ) );
2562 functionResult = QVariant();
2567 functionResult = QVariant();
2570 bool foundLayer =
false;
2571 QgsExpressionUtils::executeLambdaForMapLayer( values.at( 0 ), context, parent, [&fetchAndIncrementFunc](
QgsMapLayer * layer )
2573 fetchAndIncrementFunc( layer, QString() );
2577 const QString databasePath = values.at( 0 ).toString();
2580 fetchAndIncrementFunc(
nullptr, databasePath );
2584 return functionResult;
2590 for (
const QVariant &value : values )
2593 concat += QgsExpressionUtils::getStringValue( value, parent );
2600 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2601 return string.indexOf( QgsExpressionUtils::getStringValue( values.at( 1 ), parent ) ) + 1;
2606 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2607 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2608 return string.right( pos );
2613 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2614 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2615 return string.left( pos );
2620 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2621 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2622 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2623 return string.leftJustified( length, fill.at( 0 ),
true );
2628 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2629 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2630 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2631 return string.rightJustified( length, fill.at( 0 ),
true );
2636 if ( values.size() < 1 )
2638 parent->
setEvalErrorString( QObject::tr(
"Function format requires at least 1 argument" ) );
2642 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2643 for (
int n = 1; n < values.length(); n++ )
2645 string =
string.arg( QgsExpressionUtils::getStringValue( values.at( n ), parent ) );
2653 return QVariant( QDateTime::currentDateTime() );
2658 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2659 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2660 if ( format.isEmpty() && !language.isEmpty() )
2662 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Date when the language is specified" ) );
2663 return QVariant( QDate() );
2666 if ( format.isEmpty() && language.isEmpty() )
2667 return QVariant( QgsExpressionUtils::getDateValue( values.at( 0 ), parent ) );
2669 QString datestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2670 QLocale locale = QLocale();
2671 if ( !language.isEmpty() )
2673 locale = QLocale( language );
2676 QDate date = locale.toDate( datestring, format );
2677 if ( !date.isValid() )
2679 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Date" ).arg( datestring ) );
2682 return QVariant( date );
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 Time when the language is specified" ) );
2692 return QVariant( QTime() );
2695 if ( format.isEmpty() && language.isEmpty() )
2696 return QVariant( QgsExpressionUtils::getTimeValue( values.at( 0 ), parent ) );
2698 QString timestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2699 QLocale locale = QLocale();
2700 if ( !language.isEmpty() )
2702 locale = QLocale( language );
2705 QTime time = locale.toTime( timestring, format );
2706 if ( !time.isValid() )
2708 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Time" ).arg( timestring ) );
2711 return QVariant( time );
2716 return QVariant::fromValue( QgsExpressionUtils::getInterval( values.at( 0 ), parent ) );
2725 double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
2726 QString axis = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2727 int precision = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
2729 QString formatString;
2730 if ( values.count() > 3 )
2731 formatString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
2734 if ( formatString.compare( QLatin1String(
"suffix" ), Qt::CaseInsensitive ) == 0 )
2738 else if ( formatString.compare( QLatin1String(
"aligned" ), Qt::CaseInsensitive ) == 0 )
2742 else if ( ! formatString.isEmpty() )
2744 parent->
setEvalErrorString( QObject::tr(
"Invalid formatting parameter: '%1'. It must be empty, or 'suffix' or 'aligned'." ).arg( formatString ) );
2748 if ( axis.compare( QLatin1String(
"x" ), Qt::CaseInsensitive ) == 0 )
2752 else if ( axis.compare( QLatin1String(
"y" ), Qt::CaseInsensitive ) == 0 )
2758 parent->
setEvalErrorString( QObject::tr(
"Invalid axis name: '%1'. It must be either 'x' or 'y'." ).arg( axis ) );
2766 return floatToDegreeFormat( format, values, context, parent, node );
2773 value = QgsCoordinateUtils::dmsToDecimal( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), &ok );
2775 return ok ? QVariant( value ) : QVariant();
2781 return floatToDegreeFormat( format, values, context, parent, node );
2786 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2787 QDateTime d2 = QgsExpressionUtils::getDateTimeValue( values.at( 1 ), parent );
2788 qint64 seconds = d2.secsTo( d1 );
2789 return QVariant::fromValue(
QgsInterval( seconds ) );
2794 if ( !values.at( 0 ).canConvert<QDate>() )
2797 QDate date = QgsExpressionUtils::getDateValue( values.at( 0 ), parent );
2798 if ( !date.isValid() )
2803 return date.dayOfWeek() % 7;
2808 QVariant value = values.at( 0 );
2809 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2812 return QVariant( inter.
days() );
2816 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2817 return QVariant( d1.date().day() );
2823 QVariant value = values.at( 0 );
2824 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2827 return QVariant( inter.
years() );
2831 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2832 return QVariant( d1.date().year() );
2838 QVariant value = values.at( 0 );
2839 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2842 return QVariant( inter.
months() );
2846 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2847 return QVariant( d1.date().month() );
2853 QVariant value = values.at( 0 );
2854 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2857 return QVariant( inter.
weeks() );
2861 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2862 return QVariant( d1.date().weekNumber() );
2868 QVariant value = values.at( 0 );
2869 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2872 return QVariant( inter.
hours() );
2876 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2877 return QVariant( t1.hour() );
2883 QVariant value = values.at( 0 );
2884 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2887 return QVariant( inter.
minutes() );
2891 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2892 return QVariant( t1.minute() );
2898 QVariant value = values.at( 0 );
2899 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2902 return QVariant( inter.
seconds() );
2906 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2907 return QVariant( t1.second() );
2913 QDateTime dt = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2916 return QVariant( dt.toMSecsSinceEpoch() );
2926 long long millisecs_since_epoch = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
2928 return QVariant( QDateTime::fromMSecsSinceEpoch( millisecs_since_epoch ) );
2933 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2936 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif" ) ) );
2939 QString tag = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2945 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2948 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif_geotag" ) ) );
2955#define ENSURE_GEOM_TYPE(f, g, geomtype) \
2956 if ( !(f).hasGeometry() ) \
2957 return QVariant(); \
2958 QgsGeometry g = (f).geometry(); \
2959 if ( (g).type() != (geomtype) ) \
2966 if ( g.isMultipart() )
2968 return g.asMultiPoint().at( 0 ).x();
2972 return g.asPoint().x();
2980 if ( g.isMultipart() )
2982 return g.asMultiPoint().at( 0 ).y();
2986 return g.asPoint().y();
3000 if ( g.isEmpty() || !abGeom->
is3D() )
3005 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( g.constGet() );
3011 if (
const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( g.constGet() ) )
3013 if ( collection->numGeometries() > 0 )
3015 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3026 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3032 return QVariant( isValid );
3037 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3041 const QString methodString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).trimmed();
3042#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
3047 if ( methodString.compare( QLatin1String(
"linework" ), Qt::CaseInsensitive ) == 0 )
3049 else if ( methodString.compare( QLatin1String(
"structure" ), Qt::CaseInsensitive ) == 0 )
3052 const bool keepCollapsed = values.value( 2 ).toBool();
3057 valid = geom.
makeValid( method, keepCollapsed );
3061 parent->
setEvalErrorString( QObject::tr(
"The make_valid parameters require a newer GEOS library version" ) );
3065 return QVariant::fromValue( valid );
3070 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3076 for (
int i = 0; i < multiGeom.size(); ++i )
3078 array += QVariant::fromValue( multiGeom.at( i ) );
3086 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3098 QVariant result( centroid.asPoint().
x() );
3104 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3116 QVariant result( centroid.asPoint().
y() );
3122 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3132 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3140 if ( collection->numGeometries() == 1 )
3142 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3153 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3163 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3171 if ( collection->numGeometries() == 1 )
3173 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3184 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3189 int idx = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
3216 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3233 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3250 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3255 bool ignoreClosing =
false;
3256 if ( values.length() > 1 )
3258 ignoreClosing = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3268 bool skipLast =
false;
3269 if ( ignoreClosing && ring.count() > 2 && ring.first() == ring.last() )
3274 for (
int i = 0; i < ( skipLast ? ring.count() - 1 : ring.count() ); ++ i )
3286 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3297 for (
int i = 0; i < line->numPoints() - 1; ++i )
3301 << line->pointN( i )
3302 << line->pointN( i + 1 ) );
3313 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3323 if ( collection->numGeometries() == 1 )
3325 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->geometryN( 0 ) );
3330 if ( !curvePolygon )
3334 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3340 QVariant result = curve ? QVariant::fromValue(
QgsGeometry( curve ) ) : QVariant();
3346 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3356 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3362 QVariant result = part ? QVariant::fromValue(
QgsGeometry( part ) ) : QVariant();
3368 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3377 return QVariant::fromValue(
QgsGeometry( boundary ) );
3382 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3391 return QVariant::fromValue( merged );
3396 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3400 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3405 if ( sharedPaths.
isNull() )
3408 return QVariant::fromValue( sharedPaths );
3414 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3419 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3422 if ( simplified.
isNull() )
3430 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3435 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3440 if ( simplified.
isNull() )
3448 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3453 int iterations = std::min( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), 10 );
3454 double offset = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0.0, 0.5 );
3455 double minLength = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3456 double maxAngle = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ), 0.0, 180.0 );
3458 QgsGeometry smoothed = geom.
smooth(
static_cast<unsigned int>( iterations ), offset, minLength, maxAngle );
3467 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3472 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3473 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3474 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3485 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3490 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3491 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3492 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3493 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3494 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3497 minAmplitude, maxAmplitude, seed );
3506 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3511 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3512 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3513 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3524 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3529 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3530 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3531 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3532 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3533 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3536 minAmplitude, maxAmplitude, seed );
3545 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3550 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3551 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3552 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3563 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3568 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3569 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3570 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3571 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3572 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3575 minAmplitude, maxAmplitude, seed );
3584 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3589 const QVariantList pattern = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
3590 QVector< double > dashPattern;
3591 dashPattern.reserve( pattern.size() );
3592 for (
const QVariant &value : std::as_const( pattern ) )
3595 double v = value.toDouble( &ok );
3602 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must be an array of numbers" ) );
3607 if ( dashPattern.size() % 2 != 0 )
3609 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must contain an even number of elements" ) );
3613 const QString startRuleString = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).trimmed();
3615 if ( startRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3617 else if ( startRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3619 else if ( startRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3621 else if ( startRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3623 else if ( startRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3627 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( startRuleString ) );
3631 const QString endRuleString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
3633 if ( endRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3635 else if ( endRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3637 else if ( endRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3639 else if ( endRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3641 else if ( endRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3645 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( endRuleString ) );
3649 const QString adjustString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
3651 if ( adjustString.compare( QLatin1String(
"both" ), Qt::CaseInsensitive ) == 0 )
3653 else if ( adjustString.compare( QLatin1String(
"dash" ), Qt::CaseInsensitive ) == 0 )
3655 else if ( adjustString.compare( QLatin1String(
"gap" ), Qt::CaseInsensitive ) == 0 )
3659 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern size adjustment" ).arg( adjustString ) );
3663 const double patternOffset = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
3674 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3679 const long long count = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3681 if ( densified.
isNull() )
3689 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3694 const double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3696 if ( densified.
isNull() )
3705 if ( values.size() == 1 && QgsExpressionUtils::isList( values.at( 0 ) ) )
3707 list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
3714 QVector< QgsGeometry > parts;
3715 parts.reserve( list.size() );
3716 for (
const QVariant &value : std::as_const( list ) )
3718 QgsGeometry part = QgsExpressionUtils::getGeometry( value, parent );
3729 if ( values.count() < 2 || values.count() > 4 )
3731 parent->
setEvalErrorString( QObject::tr(
"Function make_point requires 2-4 arguments" ) );
3735 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3736 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3737 double z = values.count() >= 3 ? QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) : 0.0;
3738 double m = values.count() >= 4 ? QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) : 0.0;
3739 switch ( values.count() )
3753 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3754 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3755 double m = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3761 if ( values.empty() )
3766 QVector<QgsPoint> points;
3767 points.reserve( values.count() );
3769 auto addPoint = [&points](
const QgsGeometry & geom )
3777 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3784 for (
const QVariant &value : values )
3786 if ( value.userType() == QMetaType::Type::QVariantList )
3788 const QVariantList list = value.toList();
3789 for (
const QVariant &v : list )
3791 addPoint( QgsExpressionUtils::getGeometry( v, parent ) );
3796 addPoint( QgsExpressionUtils::getGeometry( value, parent ) );
3800 if ( points.count() < 2 )
3808 if ( values.count() < 1 )
3810 parent->
setEvalErrorString( QObject::tr(
"Function make_polygon requires an argument" ) );
3814 QgsGeometry outerRing = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3822 std::unique_ptr< QgsPolygon > polygon = std::make_unique< QgsPolygon >();
3824 const QgsCurve *exteriorRing = qgsgeometry_cast< QgsCurve * >( outerRing.
constGet() );
3831 exteriorRing = qgsgeometry_cast< QgsCurve * >( collection->
geometryN( 0 ) );
3836 if ( !exteriorRing )
3839 polygon->setExteriorRing( exteriorRing->
segmentize() );
3842 for (
int i = 1; i < values.count(); ++i )
3844 QgsGeometry ringGeom = QgsExpressionUtils::getGeometry( values.at( i ), parent );
3851 const QgsCurve *ring = qgsgeometry_cast< QgsCurve * >( ringGeom.
constGet() );
3858 ring = qgsgeometry_cast< QgsCurve * >( collection->
geometryN( 0 ) );
3866 polygon->addInteriorRing( ring->
segmentize() );
3869 return QVariant::fromValue(
QgsGeometry( std::move( polygon ) ) );
3874 std::unique_ptr<QgsTriangle> tr(
new QgsTriangle() );
3875 std::unique_ptr<QgsLineString> lineString(
new QgsLineString() );
3876 lineString->clear();
3878 for (
const QVariant &value : values )
3880 QgsGeometry geom = QgsExpressionUtils::getGeometry( value, parent );
3887 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3894 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3902 lineString->addVertex( *point );
3905 tr->setExteriorRing( lineString.release() );
3907 return QVariant::fromValue(
QgsGeometry( tr.release() ) );
3912 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3919 double radius = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3920 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
3927 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3934 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3942 return QVariant::fromValue(
QgsGeometry( circ.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
3947 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3954 double majorAxis = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3955 double minorAxis = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3956 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3957 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 4 ), parent );
3963 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3970 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3977 QgsEllipse elp( *point, majorAxis, minorAxis, azimuth );
3978 return QVariant::fromValue(
QgsGeometry( elp.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
3984 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3991 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3998 unsigned int nbEdges =
static_cast<unsigned int>( QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) );
4001 parent->
setEvalErrorString( QObject::tr(
"Number of edges/sides must be greater than 2" ) );
4008 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (inscribed) or 1 (circumscribed)" ) );
4012 const QgsPoint *center = qgsgeometry_cast< const QgsPoint * >( pt1.
constGet() );
4019 center = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4026 const QgsPoint *corner = qgsgeometry_cast< const QgsPoint * >( pt2.
constGet() );
4033 corner = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4048 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4054 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4060 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
4061 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
4069 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4075 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4081 QgsGeometry pt3 = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
4090 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (distance) or 1 (projected)" ) );
4093 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
4094 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
4095 const QgsPoint *point3 = qgsgeometry_cast< const QgsPoint *>( pt3.
constGet() );
4114 return QVariant::fromValue( geom.
vertexAt( idx ) );
4122 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4124 const QVariant v = pointAt( geom, idx, parent );
4127 return QVariant( v.value<
QgsPoint>().
x() );
4133 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4135 return fcnOldXat( values, f, parent, node );
4137 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4139 return fcnOldXat( QVariantList() << values[1], f, parent, node );
4142 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4148 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4150 const QVariant v = pointAt( geom, vertexNumber, parent );
4152 return QVariant( v.value<
QgsPoint>().
x() );
4162 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4164 const QVariant v = pointAt( geom, idx, parent );
4167 return QVariant( v.value<
QgsPoint>().
y() );
4173 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4175 return fcnOldYat( values, f, parent, node );
4177 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4179 return fcnOldYat( QVariantList() << values[1], f, parent, node );
4182 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4188 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4190 const QVariant v = pointAt( geom, vertexNumber, parent );
4192 return QVariant( v.value<
QgsPoint>().
y() );
4199 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4205 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4207 const QVariant v = pointAt( geom, vertexNumber, parent );
4209 return QVariant( v.value<
QgsPoint>().
z() );
4216 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4222 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4224 const QVariant v = pointAt( geom, vertexNumber, parent );
4226 return QVariant( v.value<
QgsPoint>().
m() );
4245 return QVariant::fromValue( geom );
4253 QString wkt = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4255 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4261 const QByteArray wkb = QgsExpressionUtils::getBinaryValue( values.at( 0 ), parent );
4267 return !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4272 QString gml = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4279 ogcContext.
layer = mapLayerPtr.data();
4280 ogcContext.
transformContext = context->
variable( QStringLiteral(
"_project_transform_context" ) ).value<QgsCoordinateTransformContext>();
4284 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4299 return QVariant( area );
4303 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating area" ) );
4315 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4320 return QVariant( geom.
area() );
4334 return QVariant( len );
4338 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating length" ) );
4359 return QVariant( len );
4363 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating perimeter" ) );
4369 return f.
geometry().
isNull() ? QVariant( 0 ) : QVariant( f.geometry().constGet()->perimeter() );
4375 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4381 return QVariant( geom.
length() );
4386 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4387 return QVariant( geom.
isNull() ? 0 : geom.constGet()->nCoordinates() );
4392 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4401 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4410 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4425 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon *>( collection->
geometryN( i ) );
4426 if ( !curvePolygon )
4429 return QVariant( curvePolygon->
isEmpty() ? 0 : curvePolygon->numInteriorRings() );
4438 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4445 return QVariant( curvePolygon->
ringCount() );
4447 bool foundPoly =
false;
4455 curvePolygon = qgsgeometry_cast< QgsCurvePolygon *>( collection->
geometryN( i ) );
4456 if ( !curvePolygon )
4467 return QVariant( ringCount );
4472 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4474 QVariant result = !geomBounds.
isNull() ? QVariant::fromValue( geomBounds ) : QVariant();
4480 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4486 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4492 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4501 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4507 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4513 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4519 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4525 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4533 double max = std::numeric_limits< double >::lowest();
4537 double z = ( *it ).z();
4543 if ( max == std::numeric_limits< double >::lowest() )
4546 return QVariant( max );
4551 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4559 double min = std::numeric_limits< double >::max();
4563 double z = ( *it ).z();
4569 if ( min == std::numeric_limits< double >::max() )
4572 return QVariant( min );
4577 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4585 double min = std::numeric_limits< double >::max();
4589 double m = ( *it ).m();
4595 if ( min == std::numeric_limits< double >::max() )
4598 return QVariant( min );
4603 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4611 double max = std::numeric_limits< double >::lowest();
4615 double m = ( *it ).m();
4621 if ( max == std::numeric_limits< double >::lowest() )
4624 return QVariant( max );
4629 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4630 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom.
constGet() );
4633 parent->
setEvalErrorString( QObject::tr(
"Function `sinuosity` requires a line geometry." ) );
4642 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4646 parent->
setEvalErrorString( QObject::tr(
"Function `straight_distance_2d` requires a line geometry or a multi line geometry with a single part." ) );
4655 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4660 parent->
setEvalErrorString( QObject::tr(
"Function `roundness` requires a polygon geometry or a multi polygon geometry with a single part." ) );
4671 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4675 std::unique_ptr< QgsAbstractGeometry > flipped( geom.
constGet()->
clone() );
4677 return QVariant::fromValue(
QgsGeometry( std::move( flipped ) ) );
4682 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4686 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( fGeom.
constGet() );
4693 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
4701 return QVariant::fromValue( curve->
isClosed() );
4706 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4719 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4720 closedLine->close();
4722 result = QVariant::fromValue(
QgsGeometry( std::move( closedLine ) ) );
4732 if (
const QgsLineString *line = qgsgeometry_cast<const QgsLineString * >( collection->
geometryN( i ) ) )
4734 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4735 closedLine->close();
4737 closed->addGeometry( closedLine.release() );
4740 result = QVariant::fromValue(
QgsGeometry( std::move( closed ) ) );
4748 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4752 return QVariant::fromValue( fGeom.
isEmpty() );
4758 return QVariant::fromValue(
true );
4760 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4761 return QVariant::fromValue( fGeom.
isNull() || fGeom.
isEmpty() );
4766 if ( values.length() < 2 || values.length() > 3 )
4769 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4770 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4777 if ( values.length() == 2 )
4780 QString result = engine->relate( sGeom.
constGet() );
4781 return QVariant::fromValue( result );
4786 QString pattern = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
4787 bool result = engine->relatePattern( sGeom.
constGet(), pattern );
4788 return QVariant::fromValue( result );
4794 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4795 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4800 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4801 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4802 return fGeom.
disjoint( sGeom ) ? TVL_True : TVL_False;
4806 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4807 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4808 return fGeom.
intersects( sGeom ) ? TVL_True : TVL_False;
4812 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4813 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4814 return fGeom.
touches( sGeom ) ? TVL_True : TVL_False;
4818 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4819 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4820 return fGeom.
crosses( sGeom ) ? TVL_True : TVL_False;
4824 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4825 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4826 return fGeom.
contains( sGeom ) ? TVL_True : TVL_False;
4830 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4831 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4832 return fGeom.
overlaps( sGeom ) ? TVL_True : TVL_False;
4836 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4837 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4838 return fGeom.
within( sGeom ) ? TVL_True : TVL_False;
4843 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4844 const double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4845 const int seg = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4846 const QString endCapString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
4847 const QString joinString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
4848 const double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
4851 if ( endCapString.compare( QLatin1String(
"flat" ), Qt::CaseInsensitive ) == 0 )
4853 else if ( endCapString.compare( QLatin1String(
"square" ), Qt::CaseInsensitive ) == 0 )
4857 if ( joinString.compare( QLatin1String(
"miter" ), Qt::CaseInsensitive ) == 0 )
4859 else if ( joinString.compare( QLatin1String(
"bevel" ), Qt::CaseInsensitive ) == 0 )
4863 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4869 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4871 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4876 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4878 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4883 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4885 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4890 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4891 const QgsPoint *pt = qgsgeometry_cast<const QgsPoint *>( fGeom.
constGet() );
4898 pt = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4905 parent->
setEvalErrorString( QObject::tr(
"Function `wedge_buffer` requires a point value for the center." ) );
4909 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4910 double width = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4911 double outerRadius = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4912 double innerRadius = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
4915 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4921 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4924 parent->
setEvalErrorString( QObject::tr(
"Function `tapered_buffer` requires a line geometry." ) );
4928 double startWidth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4929 double endWidth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4930 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) );
4933 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4939 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4942 parent->
setEvalErrorString( QObject::tr(
"Function `buffer_by_m` requires a line geometry." ) );
4946 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) );
4949 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4955 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4956 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4957 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4958 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4959 if ( joinInt < 1 || joinInt > 3 )
4963 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4966 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4972 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4973 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4974 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4976 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4977 if ( joinInt < 1 || joinInt > 3 )
4981 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4984 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4990 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4991 double distStart = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4992 double distEnd = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4995 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5001 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5002 double dx = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5003 double dy = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5005 return QVariant::fromValue( fGeom );
5010 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5011 const double rotation = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5012 const QgsGeometry center = values.at( 2 ).
isValid() ? QgsExpressionUtils::getGeometry( values.at( 2 ), parent )
5014 const bool perPart = values.value( 3 ).toBool();
5021 std::unique_ptr< QgsGeometryCollection > collection( qgsgeometry_cast< QgsGeometryCollection * >( fGeom.
constGet()->
clone() ) );
5024 const QgsPointXY partCenter = ( *it )->boundingBox().center();
5025 QTransform t = QTransform::fromTranslate( partCenter.
x(), partCenter.
y() );
5026 t.rotate( -rotation );
5027 t.translate( -partCenter.
x(), -partCenter.
y() );
5028 ( *it )->transform( t );
5030 return QVariant::fromValue(
QgsGeometry( std::move( collection ) ) );
5042 parent->
setEvalErrorString( QObject::tr(
"Function 'rotate' requires a point value for the center" ) );
5050 fGeom.
rotate( rotation, pt );
5051 return QVariant::fromValue( fGeom );
5057 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5058 const double xScale = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5059 const double yScale = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5060 const QgsGeometry center = values.at( 3 ).isValid() ? QgsExpressionUtils::getGeometry( values.at( 3 ), parent )
5071 parent->
setEvalErrorString( QObject::tr(
"Function 'scale' requires a point value for the center" ) );
5079 QTransform t = QTransform::fromTranslate( pt.
x(), pt.
y() );
5080 t.scale( xScale, yScale );
5081 t.translate( -pt.
x(), -pt.
y() );
5083 return QVariant::fromValue( fGeom );
5088 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5094 const double deltaX = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5095 const double deltaY = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5097 const double rotationZ = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5099 const double scaleX = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
5100 const double scaleY = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
5102 const double deltaZ = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
5103 const double deltaM = QgsExpressionUtils::getDoubleValue( values.at( 7 ), parent );
5104 const double scaleZ = QgsExpressionUtils::getDoubleValue( values.at( 8 ), parent );
5105 const double scaleM = QgsExpressionUtils::getDoubleValue( values.at( 9 ), parent );
5116 QTransform transform;
5117 transform.translate( deltaX, deltaY );
5118 transform.rotate( rotationZ );
5119 transform.scale( scaleX, scaleY );
5120 fGeom.
transform( transform, deltaZ, scaleZ, deltaM, scaleM );
5122 return QVariant::fromValue( fGeom );
5128 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5130 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5135 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5137 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5143 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5144 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5146 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5152 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5154 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5158#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
5163 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5164 const double targetPercent = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5165 const bool allowHoles = values.value( 2 ).toBool();
5167 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5180 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5182 if ( values.length() == 2 )
5183 segments = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5191 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5197 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5199 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5205 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5211 double area,
angle, width, height;
5224 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5225 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5227 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5233 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5240 const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( fGeom.
constGet() );
5245 result = reversed ? QVariant::fromValue(
QgsGeometry( reversed ) ) : QVariant();
5253 if (
const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( collection->
geometryN( i ) ) )
5255 reversed->addGeometry( curve->
reversed() );
5262 result = reversed ? QVariant::fromValue(
QgsGeometry( std::move( reversed ) ) ) : QVariant();
5269 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5280 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->
geometryN( 0 ) );
5289 QVariant result = exterior ? QVariant::fromValue(
QgsGeometry( exterior ) ) : QVariant();
5295 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5296 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5297 return QVariant( fGeom.
distance( sGeom ) );
5302 QgsGeometry g1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5303 QgsGeometry g2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5306 if ( values.length() == 3 && values.at( 2 ).isValid() )
5308 double densify = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5309 densify = std::clamp( densify, 0.0, 1.0 );
5317 return res > -1 ? QVariant( res ) : QVariant();
5322 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5323 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5325 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5330 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5331 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5333 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5338 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5339 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5341 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5347 if ( values.length() < 1 || values.length() > 2 )
5350 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5352 if ( values.length() == 2 )
5353 prec = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5354 QString wkt = fGeom.
asWkt( prec );
5355 return QVariant( wkt );
5360 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5361 return fGeom.
isNull() ? QVariant() : QVariant( fGeom.asWkb() );
5366 if ( values.length() != 2 )
5368 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires exactly two parameters. %n given.",
nullptr, values.length() ) );
5372 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5373 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5375 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5382 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5387 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5394 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5401 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires two points as arguments." ) );
5408 if ( pt1->
y() < pt2->
y() )
5410 else if ( pt1->
y() > pt2->
y() )
5418 if ( pt1->
x() < pt2->
x() )
5420 else if ( pt1->
x() > pt2->
x() )
5421 return M_PI + ( M_PI_2 );
5426 if ( pt1->
x() < pt2->
x() )
5428 if ( pt1->
y() < pt2->
y() )
5430 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) );
5434 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5441 if ( pt1->
y() > pt2->
y() )
5443 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) )
5448 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5449 + ( M_PI + ( M_PI_2 ) );
5456 const QgsGeometry geom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5457 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5458 QString sourceCrs = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5459 QString ellipsoid = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
5463 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires two valid point geometries." ) );
5471 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires point geometries or multi point geometries with a single part." ) );
5480 if ( sourceCrs.isEmpty() )
5482 sourceCrs = context->
variable( QStringLiteral(
"layer_crs" ) ).toString();
5485 if ( ellipsoid.isEmpty() )
5487 ellipsoid = context->
variable( QStringLiteral(
"project_ellipsoid" ) ).toString();
5494 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires a valid source CRS." ) );
5502 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires a valid ellipsoid acronym or ellipsoid authority ID." ) );
5508 const double bearing = da.
bearing( point1, point2 );
5509 if ( std::isfinite( bearing ) )
5511 return std::fmod( bearing + 2 * M_PI, 2 * M_PI );
5524 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5528 parent->
setEvalErrorString( QStringLiteral(
"'project' requires a point geometry" ) );
5532 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5533 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5534 double inclination = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5537 QgsPoint newPoint = p->
project( distance, 180.0 * azimuth / M_PI, 180.0 * inclination / M_PI );
5544 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5545 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5547 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5554 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5558 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5565 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5573 parent->
setEvalErrorString( QStringLiteral(
"Function 'inclination' requires two points as arguments." ) );
5583 if ( values.length() != 3 )
5586 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5587 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5588 double y = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5592 QVariant result = geom.
constGet() ? QVariant::fromValue( geom ) : QVariant();
5598 if ( values.length() < 2 )
5601 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5604 return values.at( 0 );
5606 QString expString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5607 QVariant cachedExpression;
5612 if ( cachedExpression.isValid() )
5619 bool asc = values.value( 2 ).toBool();
5637 Q_ASSERT( collection );
5641 QgsExpressionSorter sorter( orderBy );
5643 QList<QgsFeature> partFeatures;
5644 partFeatures.reserve( collection->
partCount() );
5645 for (
int i = 0; i < collection->
partCount(); ++i )
5651 sorter.sortFeatures( partFeatures, unconstedContext );
5655 Q_ASSERT( orderedGeom );
5660 for (
const QgsFeature &feature : std::as_const( partFeatures ) )
5665 QVariant result = QVariant::fromValue(
QgsGeometry( orderedGeom ) );
5668 delete unconstedContext;
5675 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5676 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5680 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5686 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5687 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5691 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5697 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5698 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5702 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5708 const QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5709 const double m = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5710 const bool use3DDistance = values.at( 2 ).toBool();
5712 double x, y, z, distance;
5735 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5738 parent->
setEvalErrorString( QObject::tr(
"line_substring requires a curve geometry input" ) );
5744 curve = qgsgeometry_cast< const QgsCurve * >( lineGeom.
constGet() );
5751 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
5758 double startDistance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5759 double endDistance = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5761 std::unique_ptr< QgsCurve > substring( curve->
curveSubstring( startDistance, endDistance ) );
5763 return !result.isNull() ? QVariant::fromValue( result ) : QVariant();
5768 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5769 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5776 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5777 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5782 vertex = count + vertex;
5790 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5791 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5796 vertex = count + vertex;
5804 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5805 QgsGeometry pointGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5809 return distance >= 0 ? distance : QVariant();
5814 const QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5815 const double m = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5816 const bool use3DDistance = values.at( 2 ).toBool();
5818 double x, y, z, distance;
5827 return found ? distance : QVariant();
5832 if ( values.length() == 2 && values.at( 1 ).toInt() != 0 )
5834 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5835 return qgsRound( number, QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
5838 if ( values.length() >= 1 )
5840 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5841 return QVariant( qlonglong( std::round( number ) ) );
5856 const double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5857 const int places = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5858 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5865 const bool omitGroupSeparator = values.value( 3 ).toBool();
5866 const bool trimTrailingZeros = values.value( 4 ).toBool();
5868 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5869 if ( !omitGroupSeparator )
5870 locale.setNumberOptions( locale.numberOptions() & ~QLocale::NumberOption::OmitGroupSeparator );
5872 locale.setNumberOptions( locale.numberOptions() | QLocale::NumberOption::OmitGroupSeparator );
5874 QString res = locale.toString( value,
'f', places );
5876 if ( trimTrailingZeros )
5878#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
5879 const QChar decimal = locale.decimalPoint();
5880 const QChar zeroDigit = locale.zeroDigit();
5882 const QChar decimal = locale.decimalPoint().at( 0 );
5883 const QChar zeroDigit = locale.zeroDigit().at( 0 );
5886 if ( res.contains( decimal ) )
5888 int trimPoint = res.length() - 1;
5890 while ( res.at( trimPoint ) == zeroDigit )
5893 if ( res.at( trimPoint ) == decimal )
5896 res.truncate( trimPoint + 1 );
5905 QDateTime datetime = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
5906 const QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5907 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5910 if ( format.indexOf(
"Z" ) > 0 )
5911 datetime = datetime.toUTC();
5913 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5914 return locale.toString( datetime, format );
5919 const QVariant variant = values.at( 0 );
5921 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
5922 if ( !color.isValid() )
5925 const float alpha = color.alphaF();
5926 if ( color.spec() == QColor::Spec::Cmyk )
5928 const float avg = ( color.cyanF() + color.magentaF() + color.yellowF() ) / 3;
5929 color = QColor::fromCmykF( avg, avg, avg, color.blackF(), alpha );
5933 const float avg = ( color.redF() + color.greenF() + color.blueF() ) / 3;
5934 color.setRgbF( avg, avg, avg, alpha );
5937 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
5944 double ratio = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5949 else if ( ratio < 0 )
5954 int red =
static_cast<int>( color1.red() * ( 1 - ratio ) + color2.red() * ratio );
5955 int green =
static_cast<int>( color1.green() * ( 1 - ratio ) + color2.green() * ratio );
5956 int blue =
static_cast<int>( color1.blue() * ( 1 - ratio ) + color2.blue() * ratio );
5957 int alpha =
static_cast<int>( color1.alpha() * ( 1 - ratio ) + color2.alpha() * ratio );
5959 QColor newColor( red, green, blue, alpha );
5966 const QVariant variant1 = values.at( 0 );
5967 const QVariant variant2 = values.at( 1 );
5969 if ( variant1.userType() != variant2.userType() )
5971 parent->
setEvalErrorString( QObject::tr(
"Both color arguments must have the same type (string or color object)" ) );
5976 const QColor color1 = QgsExpressionUtils::getColorValue( variant1, parent, isQColor );
5977 if ( !color1.isValid() )
5980 const QColor color2 = QgsExpressionUtils::getColorValue( variant2, parent, isQColor );
5981 if ( !color2.isValid() )
5984 if ( ( color1.spec() == QColor::Cmyk ) != ( color2.spec() == QColor::Cmyk ) )
5986 parent->
setEvalErrorString( QObject::tr(
"Both color arguments must have compatible color type (CMYK or RGB/HSV/HSL)" ) );
5990 const float ratio =
static_cast<float>( std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0., 1. ) );
5996 const float alpha = color1.alphaF() * ( 1 - ratio ) + color2.alphaF() * ratio;
5997 if ( color1.spec() == QColor::Spec::Cmyk )
5999 float cyan = color1.cyanF() * ( 1 - ratio ) + color2.cyanF() * ratio;
6000 float magenta = color1.magentaF() * ( 1 - ratio ) + color2.magentaF() * ratio;
6001 float yellow = color1.yellowF() * ( 1 - ratio ) + color2.yellowF() * ratio;
6002 float black = color1.blackF() * ( 1 - ratio ) + color2.blackF() * ratio;
6003 newColor = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6007 float red = color1.redF() * ( 1 - ratio ) + color2.redF() * ratio;
6008 float green = color1.greenF() * ( 1 - ratio ) + color2.greenF() * ratio;
6009 float blue = color1.blueF() * ( 1 - ratio ) + color2.blueF() * ratio;
6010 newColor = QColor::fromRgbF( red, green, blue, alpha );
6015 return isQColor ? QVariant( newColor ) : QVariant(
QgsSymbolLayerUtils::encodeColor( newColor ) );
6020 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
6021 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6022 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6023 QColor color = QColor( red, green, blue );
6024 if ( ! color.isValid() )
6026 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( red ).arg( green ).arg( blue ) );
6027 color = QColor( 0, 0, 0 );
6030 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6035 const float red = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6036 const float green = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6037 const float blue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6038 const float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6039 QColor color = QColor::fromRgbF( red, green, blue, alpha );
6040 if ( ! color.isValid() )
6042 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
6051 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
6052 QVariant value = node->
eval( parent, context );
6056 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
6058 value = node->
eval( parent, context );
6066 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
6068 QVariant value = node->
eval( parent, context );
6070 if ( value.toBool() )
6072 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
6074 value = node->
eval( parent, context );
6079 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
6081 value = node->
eval( parent, context );
6089 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
6090 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6091 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6092 int alpha = QgsExpressionUtils::getNativeIntValue( values.at( 3 ), parent );
6093 QColor color = QColor( red, green, blue, alpha );
6094 if ( ! color.isValid() )
6096 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
6097 color = QColor( 0, 0, 0 );
6106 if ( values.at( 0 ).userType() == qMetaTypeId< QgsGradientColorRamp>() )
6108 expRamp = QgsExpressionUtils::getRamp( values.at( 0 ), parent );
6113 QString rampName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
6117 parent->
setEvalErrorString( QObject::tr(
"\"%1\" is not a valid color ramp" ).arg( rampName ) );
6122 double value = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
6123 QColor color = ramp->
color( value );
6136 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6138 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6140 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6142 QColor color = QColor::fromHslF( hue, saturation, lightness );
6144 if ( ! color.isValid() )
6146 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( lightness ) );
6147 color = QColor( 0, 0, 0 );
6150 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6156 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6158 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6160 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6162 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
6164 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
6165 if ( ! color.isValid() )
6167 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
6168 color = QColor( 0, 0, 0 );
6175 float hue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6176 float saturation = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6177 float lightness = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6178 float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6180 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
6181 if ( ! color.isValid() )
6183 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
6193 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6195 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6197 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6199 QColor color = QColor::fromHsvF( hue, saturation, value );
6201 if ( ! color.isValid() )
6203 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( value ) );
6204 color = QColor( 0, 0, 0 );
6207 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6213 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6215 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6217 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6219 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
6221 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
6222 if ( ! color.isValid() )
6224 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
6225 color = QColor( 0, 0, 0 );
6232 float hue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6233 float saturation = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6234 float value = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6235 float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6236 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
6238 if ( ! color.isValid() )
6240 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
6249 const float cyan = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6250 const float magenta = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6251 const float yellow = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6252 const float black = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6253 const float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ) ), 0.f, 1.f );
6255 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6256 if ( ! color.isValid() )
6258 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
6268 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
6270 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6272 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6274 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
6276 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black );
6278 if ( ! color.isValid() )
6280 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ) );
6281 color = QColor( 0, 0, 0 );
6284 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6290 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
6292 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6294 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6296 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
6298 double alpha = QgsExpressionUtils::getIntValue( values.at( 4 ), parent ) / 255.0;
6300 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6301 if ( ! color.isValid() )
6303 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
6304 color = QColor( 0, 0, 0 );
6311 const QVariant variant = values.at( 0 );
6313 const QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6314 if ( !color.isValid() )
6317 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6318 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6320 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6321 return color.green();
6322 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6323 return color.blue();
6324 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6325 return color.alpha();
6326 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6327 return static_cast< double >( color.hsvHueF() * 360 );
6328 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6329 return static_cast< double >( color.hsvSaturationF() * 100 );
6330 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6331 return static_cast< double >( color.valueF() * 100 );
6332 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6333 return static_cast< double >( color.hslHueF() * 360 );
6334 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6335 return static_cast< double >( color.hslSaturationF() * 100 );
6336 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6337 return static_cast< double >( color.lightnessF() * 100 );
6338 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6339 return static_cast< double >( color.cyanF() * 100 );
6340 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6341 return static_cast< double >( color.magentaF() * 100 );
6342 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6343 return static_cast< double >( color.yellowF() * 100 );
6344 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6345 return static_cast< double >( color.blackF() * 100 );
6347 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6353 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
6356 parent->
setEvalErrorString( QObject::tr(
"A minimum of two colors is required to create a ramp" ) );
6360 QList< QColor > colors;
6362 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
6365 if ( !colors.last().isValid() )
6367 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( it.value().toString() ) );
6371 double step = it.key().toDouble();
6372 if ( it == map.constBegin() )
6377 else if ( it == map.constEnd() )
6387 bool discrete = values.at( 1 ).toBool();
6389 if ( colors.empty() )
6392 return QVariant::fromValue(
QgsGradientColorRamp( colors.first(), colors.last(), discrete, stops ) );
6397 const QVariant variant = values.at( 0 );
6399 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6400 if ( !color.isValid() )
6403 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6404 int value = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6405 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6406 color.setRed( std::clamp( value, 0, 255 ) );
6407 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6408 color.setGreen( std::clamp( value, 0, 255 ) );
6409 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6410 color.setBlue( std::clamp( value, 0, 255 ) );
6411 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6412 color.setAlpha( std::clamp( value, 0, 255 ) );
6413 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6414 color.setHsv( std::clamp( value, 0, 359 ), color.hsvSaturation(), color.value(), color.alpha() );
6415 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6416 color.setHsvF( color.hsvHueF(), std::clamp( value, 0, 100 ) / 100.0, color.valueF(), color.alphaF() );
6417 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6418 color.setHsvF( color.hsvHueF(), color.hsvSaturationF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6419 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6420 color.setHsl( std::clamp( value, 0, 359 ), color.hslSaturation(), color.lightness(), color.alpha() );
6421 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6422 color.setHslF( color.hslHueF(), std::clamp( value, 0, 100 ) / 100.0, color.lightnessF(), color.alphaF() );
6423 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6424 color.setHslF( color.hslHueF(), color.hslSaturationF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6425 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6426 color.setCmykF( std::clamp( value, 0, 100 ) / 100.0, color.magentaF(), color.yellowF(), color.blackF(), color.alphaF() );
6427 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6428 color.setCmykF( color.cyanF(), std::clamp( value, 0, 100 ) / 100.0, color.yellowF(), color.blackF(), color.alphaF() );
6429 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6430 color.setCmykF( color.cyanF(), color.magentaF(), std::clamp( value, 0, 100 ) / 100.0, color.blackF(), color.alphaF() );
6431 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6432 color.setCmykF( color.cyanF(), color.magentaF(), color.yellowF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6435 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6438 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6443 const QVariant variant = values.at( 0 );
6445 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6446 if ( !color.isValid() )
6449 color = color.darker( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6451 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6456 const QVariant variant = values.at( 0 );
6458 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6459 if ( !color.isValid() )
6462 color = color.lighter( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6464 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6469 QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6472 return QVariant::fromValue( geom );
6478 const QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6486 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
6487 QString sAuthId = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6488 QString dAuthId = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6492 return QVariant::fromValue( fGeom );
6495 return QVariant::fromValue( fGeom );
6504 return QVariant::fromValue( fGeom );
6517 bool foundLayer =
false;
6518 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6521 if ( !featureSource || !foundLayer )
6526 const QgsFeatureId fid = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
6539 result = QVariant::fromValue( fet );
6547 bool foundLayer =
false;
6548 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6551 if ( !featureSource || !foundLayer )
6556 QString cacheValueKey;
6557 if ( values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
6559 QVariantMap attributeMap = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
6561 QMap <QString, QVariant>::const_iterator i = attributeMap.constBegin();
6562 QString filterString;
6563 for ( ; i != attributeMap.constEnd(); ++i )
6565 if ( !filterString.isEmpty() )
6567 filterString.append(
" AND " );
6571 cacheValueKey = QStringLiteral(
"getfeature:%1:%2" ).arg( featureSource->id(), filterString );
6580 QString attribute = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6581 int attributeId = featureSource->fields().lookupField( attribute );
6582 if ( attributeId == -1 )
6587 const QVariant &attVal = values.at( 2 );
6589 cacheValueKey = QStringLiteral(
"getfeature:%1:%2:%3" ).arg( featureSource->id(), QString::number( attributeId ), attVal.toString() );
6612 res = QVariant::fromValue( fet );
6627 if ( !values.isEmpty() )
6630 if ( col && ( values.size() == 1 || !values.at( 1 ).isValid() ) )
6631 fieldName = col->
name();
6632 else if ( values.size() == 2 )
6633 fieldName = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6636 QVariant value = values.at( 0 );
6641 if ( fieldIndex == -1 )
6643 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: Field not found %2" ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6649 QgsVectorLayer *layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
6652 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName, value.toString() );
6661 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName );
6679 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: function cannot be evaluated without a context." ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6687 const QVariant data = values.at( 0 );
6688 const QMimeDatabase db;
6689 return db.mimeTypeForData( data.toByteArray() ).name();
6694 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6696 bool foundLayer =
false;
6697 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [layerProperty](
QgsMapLayer * layer )-> QVariant
6703 if ( QString::compare( layerProperty, QStringLiteral(
"name" ), Qt::CaseInsensitive ) == 0 )
6704 return layer->name();
6705 else if ( QString::compare( layerProperty, QStringLiteral(
"id" ), Qt::CaseInsensitive ) == 0 )
6707 else if ( QString::compare( layerProperty, QStringLiteral(
"title" ), Qt::CaseInsensitive ) == 0 )
6708 return !layer->metadata().title().isEmpty() ? layer->metadata().title() : layer->serverProperties()->title();
6709 else if ( QString::compare( layerProperty, QStringLiteral(
"abstract" ), Qt::CaseInsensitive ) == 0 )
6710 return !layer->metadata().abstract().isEmpty() ? layer->metadata().abstract() : layer->serverProperties()->abstract();
6711 else if ( QString::compare( layerProperty, QStringLiteral(
"keywords" ), Qt::CaseInsensitive ) == 0 )
6713 QStringList keywords;
6714 const QgsAbstractMetadataBase::KeywordMap keywordMap = layer->metadata().keywords();
6715 for ( auto it = keywordMap.constBegin(); it != keywordMap.constEnd(); ++it )
6717 keywords.append( it.value() );
6719 if ( !keywords.isEmpty() )
6721 return layer->serverProperties()->keywordList();
6723 else if ( QString::compare( layerProperty, QStringLiteral(
"data_url" ), Qt::CaseInsensitive ) == 0 )
6725 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution" ), Qt::CaseInsensitive ) == 0 )
6727 return !layer->
metadata().
rights().isEmpty() ? QVariant( layer->
metadata().
rights() ) : QVariant( layer->serverProperties()->attribution() );
6729 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution_url" ), Qt::CaseInsensitive ) == 0 )
6731 else if ( QString::compare( layerProperty, QStringLiteral(
"source" ), Qt::CaseInsensitive ) == 0 )
6733 else if ( QString::compare( layerProperty, QStringLiteral(
"min_scale" ), Qt::CaseInsensitive ) == 0 )
6735 else if ( QString::compare( layerProperty, QStringLiteral(
"max_scale" ), Qt::CaseInsensitive ) == 0 )
6737 else if ( QString::compare( layerProperty, QStringLiteral(
"is_editable" ), Qt::CaseInsensitive ) == 0 )
6739 else if ( QString::compare( layerProperty, QStringLiteral(
"crs" ), Qt::CaseInsensitive ) == 0 )
6741 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_definition" ), Qt::CaseInsensitive ) == 0 )
6743 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_description" ), Qt::CaseInsensitive ) == 0 )
6745 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_ellipsoid" ), Qt::CaseInsensitive ) == 0 )
6747 else if ( QString::compare( layerProperty, QStringLiteral(
"extent" ), Qt::CaseInsensitive ) == 0 )
6750 QVariant result = QVariant::fromValue( extentGeom );
6753 else if ( QString::compare( layerProperty, QStringLiteral(
"distance_units" ), Qt::CaseInsensitive ) == 0 )
6755 else if ( QString::compare( layerProperty, QStringLiteral(
"path" ), Qt::CaseInsensitive ) == 0 )
6758 return decodedUri.value( QStringLiteral(
"path" ) );
6760 else if ( QString::compare( layerProperty, QStringLiteral(
"type" ), Qt::CaseInsensitive ) == 0 )
6762 switch ( layer->
type() )
6765 return QCoreApplication::translate(
"expressions",
"Vector" );
6767 return QCoreApplication::translate(
"expressions",
"Raster" );
6769 return QCoreApplication::translate(
"expressions",
"Mesh" );
6771 return QCoreApplication::translate(
"expressions",
"Vector Tile" );
6773 return QCoreApplication::translate(
"expressions",
"Plugin" );
6775 return QCoreApplication::translate(
"expressions",
"Annotation" );
6777 return QCoreApplication::translate(
"expressions",
"Point Cloud" );
6779 return QCoreApplication::translate(
"expressions",
"Group" );
6781 return QCoreApplication::translate(
"expressions",
"Tiled Scene" );
6787 QgsVectorLayer *vLayer = qobject_cast< QgsVectorLayer * >( layer );
6790 if ( QString::compare( layerProperty, QStringLiteral(
"storage_type" ), Qt::CaseInsensitive ) == 0 )
6792 else if ( QString::compare( layerProperty, QStringLiteral(
"geometry_type" ), Qt::CaseInsensitive ) == 0 )
6794 else if ( QString::compare( layerProperty, QStringLiteral(
"feature_count" ), Qt::CaseInsensitive ) == 0 )
6810 const QString uriPart = values.at( 1 ).toString();
6812 bool foundLayer =
false;
6814 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, uriPart](
QgsMapLayer * layer )-> QVariant
6816 if ( !layer->dataProvider() )
6818 parent->setEvalErrorString( QObject::tr(
"Layer %1 has invalid data provider" ).arg( layer->name() ) );
6824 if ( !uriPart.isNull() )
6826 return decodedUri.value( uriPart );
6836 parent->
setEvalErrorString( QObject::tr(
"Function `decode_uri` requires a valid layer." ) );
6847 const int band = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6848 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6850 bool foundLayer =
false;
6851 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, band, layerProperty](
QgsMapLayer * layer )-> QVariant
6853 QgsRasterLayer *rl = qobject_cast< QgsRasterLayer * >( layer );
6857 if ( band < 1 || band > rl->bandCount() )
6859 parent->setEvalErrorString( QObject::tr(
"Invalid band number %1 for layer" ).arg( band ) );
6865 if ( QString::compare( layerProperty, QStringLiteral(
"avg" ), Qt::CaseInsensitive ) == 0 )
6867 else if ( QString::compare( layerProperty, QStringLiteral(
"stdev" ), Qt::CaseInsensitive ) == 0 )
6869 else if ( QString::compare( layerProperty, QStringLiteral(
"min" ), Qt::CaseInsensitive ) == 0 )
6871 else if ( QString::compare( layerProperty, QStringLiteral(
"max" ), Qt::CaseInsensitive ) == 0 )
6873 else if ( QString::compare( layerProperty, QStringLiteral(
"range" ), Qt::CaseInsensitive ) == 0 )
6875 else if ( QString::compare( layerProperty, QStringLiteral(
"sum" ), Qt::CaseInsensitive ) == 0 )
6879 parent->
setEvalErrorString( QObject::tr(
"Invalid raster statistic: '%1'" ).arg( layerProperty ) );
6907 parent->
setEvalErrorString( QObject::tr(
"Function `raster_statistic` requires a valid raster layer." ) );
6924 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6925 bool ascending = values.value( 1 ).toBool();
6926 std::sort( list.begin(), list.end(), [ascending]( QVariant a, QVariant b ) ->
bool { return ( !ascending ? qgsVariantLessThan( b, a ) : qgsVariantLessThan( a, b ) ); } );
6932 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).length();
6937 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).contains( values.at( 1 ) ) );
6942 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).count( values.at( 1 ) ) );
6947 QVariantList listA = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6948 QVariantList listB = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
6950 for (
const auto &item : listB )
6952 if ( listA.contains( item ) )
6956 return QVariant( match == listB.count() );
6961 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).indexOf( values.at( 1 ) );
6966 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6967 const int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6968 if ( pos < list.length() && pos >= 0 )
return list.at( pos );
6969 else if ( pos < 0 && ( list.length() + pos ) >= 0 )
6970 return list.at( list.length() + pos );
6976 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6977 return list.value( 0 );
6982 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6983 return list.value( list.size() - 1 );
6988 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6989 return list.isEmpty() ? QVariant() : *std::min_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
6994 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6995 return list.isEmpty() ? QVariant() : *std::max_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
7000 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7003 for (
const QVariant &item : list )
7005 switch ( item.userType() )
7007 case QMetaType::Int:
7008 case QMetaType::UInt:
7009 case QMetaType::LongLong:
7010 case QMetaType::ULongLong:
7011 case QMetaType::Float:
7012 case QMetaType::Double:
7013 total += item.toDouble();
7018 return i == 0 ? QVariant() : total / i;
7023 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7024 QVariantList numbers;
7025 for (
const auto &item : list )
7027 switch ( item.userType() )
7029 case QMetaType::Int:
7030 case QMetaType::UInt:
7031 case QMetaType::LongLong:
7032 case QMetaType::ULongLong:
7033 case QMetaType::Float:
7034 case QMetaType::Double:
7035 numbers.append( item );
7039 std::sort( numbers.begin(), numbers.end(), []( QVariant a, QVariant b ) ->
bool { return ( qgsVariantLessThan( a, b ) ); } );
7040 const int count = numbers.count();
7045 else if ( count % 2 )
7047 return numbers.at( count / 2 );
7051 return ( numbers.at( count / 2 - 1 ).toDouble() + numbers.at( count / 2 ).toDouble() ) / 2;
7057 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7060 for (
const QVariant &item : list )
7062 switch ( item.userType() )
7064 case QMetaType::Int:
7065 case QMetaType::UInt:
7066 case QMetaType::LongLong:
7067 case QMetaType::ULongLong:
7068 case QMetaType::Float:
7069 case QMetaType::Double:
7070 total += item.toDouble();
7075 return i == 0 ? QVariant() : total;
7078static QVariant convertToSameType(
const QVariant &value, QMetaType::Type type )
7080 QVariant result = value;
7081 result.convert(
static_cast<int>( type ) );
7087 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7088 QHash< QVariant, int > hash;
7089 for (
const auto &item : list )
7093 const QList< int > occurrences = hash.values();
7094 if ( occurrences.empty() )
7095 return QVariantList();
7097 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
7099 const QString option = values.at( 1 ).toString();
7100 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
7102 return convertToSameType( hash.keys( maxValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7104 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
7106 if ( hash.isEmpty() )
7109 return QVariant( hash.key( maxValue ) );
7111 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
7113 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( maxValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) ), context, parent, node );
7115 else if ( option.compare( QLatin1String(
"real_majority" ), Qt::CaseInsensitive ) == 0 )
7117 if ( maxValue * 2 <= list.size() )
7120 return QVariant( hash.key( maxValue ) );
7131 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7132 QHash< QVariant, int > hash;
7133 for (
const auto &item : list )
7137 const QList< int > occurrences = hash.values();
7138 if ( occurrences.empty() )
7139 return QVariantList();
7141 const int minValue = *std::min_element( occurrences.constBegin(), occurrences.constEnd() );
7143 const QString option = values.at( 1 ).toString();
7144 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
7146 return convertToSameType( hash.keys( minValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7148 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
7150 if ( hash.isEmpty() )
7153 return QVariant( hash.key( minValue ) );
7155 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
7157 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( minValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) ), context, parent, node );
7159 else if ( option.compare( QLatin1String(
"real_minority" ), Qt::CaseInsensitive ) == 0 )
7161 if ( hash.isEmpty() )
7165 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
7166 if ( maxValue * 2 > list.size() )
7167 hash.remove( hash.key( maxValue ) );
7169 return convertToSameType( hash.keys(),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7180 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7181 list.append( values.at( 1 ) );
7182 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7187 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7188 list.prepend( values.at( 1 ) );
7189 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7194 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7195 list.insert( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), values.at( 2 ) );
7196 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7201 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7202 int position = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7204 position = position + list.length();
7205 if ( position >= 0 && position < list.length() )
7206 list.removeAt( position );
7207 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7215 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7217 const QVariant toRemove = values.at( 1 );
7220 list.erase( std::remove_if( list.begin(), list.end(), [](
const QVariant & element )
7222 return QgsVariantUtils::isNull( element );
7227 list.removeAll( toRemove );
7229 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7234 if ( values.count() == 2 && values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
7236 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
7238 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7239 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
7241 int index = list.indexOf( it.key() );
7242 while ( index >= 0 )
7244 list.replace( index, it.value() );
7245 index = list.indexOf( it.key() );
7249 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7251 else if ( values.count() == 3 )
7253 QVariantList before;
7255 bool isSingleReplacement =
false;
7257 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).userType() != QMetaType::Type::QStringList )
7259 before = QVariantList() << values.at( 1 );
7263 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
7266 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
7268 after = QVariantList() << values.at( 2 );
7269 isSingleReplacement =
true;
7273 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
7276 if ( !isSingleReplacement && before.length() != after.length() )
7278 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
7282 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7283 for (
int i = 0; i < before.length(); i++ )
7285 int index = list.indexOf( before.at( i ) );
7286 while ( index >= 0 )
7288 list.replace( index, after.at( isSingleReplacement ? 0 : i ) );
7289 index = list.indexOf( before.at( i ) );
7293 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7297 parent->
setEvalErrorString( QObject::tr(
"Function array_replace requires 2 or 3 arguments" ) );
7304 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7305 QVariantList list_new;
7307 for (
const QVariant &cur :
QgsExpressionUtils::getListValue( values.at( 1 ), parent ) )
7309 while ( list.removeOne( cur ) )
7311 list_new.append( cur );
7315 list_new.append( list );
7317 return convertToSameType( list_new,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7323 for (
const QVariant &cur : values )
7325 list += QgsExpressionUtils::getListValue( cur, parent );
7327 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7332 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7333 int start_pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7334 const int end_pos = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
7335 int slice_length = 0;
7337 if ( start_pos < 0 )
7339 start_pos = list.length() + start_pos;
7343 slice_length = end_pos - start_pos + 1;
7347 slice_length = list.length() + end_pos - start_pos + 1;
7350 if ( slice_length < 0 )
7354 list = list.mid( start_pos, slice_length );
7360 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7361 std::reverse( list.begin(), list.end() );
7367 const QVariantList array1 = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7368 const QVariantList array2 = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
7369 for (
const QVariant &cur : array2 )
7371 if ( array1.contains( cur ) )
7372 return QVariant(
true );
7374 return QVariant(
false );
7379 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7381 QVariantList distinct;
7383 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7385 if ( !distinct.contains( *it ) )
7387 distinct += ( *it );
7396 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7397 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7398 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7402 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7404 str += ( !( *it ).toString().isEmpty() ) ? ( *it ).toString() : empty;
7405 if ( it != ( array.constEnd() - 1 ) )
7411 return QVariant( str );
7416 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7417 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7418 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7420 QStringList list = str.split( delimiter );
7423 for ( QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
7425 array += ( !( *it ).isEmpty() ) ? *it : empty;
7433 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7434 QJsonDocument document = QJsonDocument::fromJson( str.toUtf8() );
7435 if ( document.isNull() )
7438 return document.toVariant();
7444 QJsonDocument document = QJsonDocument::fromVariant( values.at( 0 ) );
7445 return QString( document.toJson( QJsonDocument::Compact ) );
7450 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7451 if ( str.isEmpty() )
7452 return QVariantMap();
7453 str = str.trimmed();
7460 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7467 for (
int i = 0; i + 1 < values.length(); i += 2 )
7469 result.insert( QgsExpressionUtils::getStringValue( values.at( i ), parent ), values.at( i + 1 ) );
7476 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7477 const QString prefix = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7478 QVariantMap resultMap;
7480 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7482 resultMap.insert( QString( it.key() ).prepend( prefix ), it.value() );
7490 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).value( values.at( 1 ).toString() );
7495 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).contains( values.at( 1 ).toString() );
7500 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7501 map.remove( values.at( 1 ).toString() );
7507 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7508 map.insert( values.at( 1 ).toString(), values.at( 2 ) );
7515 for (
const QVariant &cur : values )
7517 const QVariantMap curMap = QgsExpressionUtils::getMapValue( cur, parent );
7518 for ( QVariantMap::const_iterator it = curMap.constBegin(); it != curMap.constEnd(); ++it )
7519 result.insert( it.key(), it.value() );
7526 return QStringList( QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).keys() );
7531 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).values();
7536 const QString envVarName = values.at( 0 ).toString();
7537 if ( !QProcessEnvironment::systemEnvironment().contains( envVarName ) )
7540 return QProcessEnvironment::systemEnvironment().value( envVarName );
7545 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7548 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"base_file_name" ) ) );
7551 return QFileInfo( file ).completeBaseName();
7556 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7559 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_suffix" ) ) );
7562 return QFileInfo( file ).completeSuffix();
7567 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7570 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_exists" ) ) );
7573 return QFileInfo::exists( file );
7578 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7581 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_name" ) ) );
7584 return QFileInfo( file ).fileName();
7589 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7592 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_file" ) ) );
7595 return QFileInfo( file ).isFile();
7600 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7603 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_directory" ) ) );
7606 return QFileInfo( file ).isDir();
7611 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7614 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_path" ) ) );
7617 return QDir::toNativeSeparators( QFileInfo( file ).path() );
7622 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7625 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_size" ) ) );
7628 return QFileInfo( file ).size();
7631static QVariant fcnHash(
const QString &str,
const QCryptographicHash::Algorithm
algorithm )
7633 return QString( QCryptographicHash::hash( str.toUtf8(),
algorithm ).toHex() );
7639 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7640 QString method = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).toLower();
7642 if ( method == QLatin1String(
"md4" ) )
7644 hash = fcnHash( str, QCryptographicHash::Md4 );
7646 else if ( method == QLatin1String(
"md5" ) )
7648 hash = fcnHash( str, QCryptographicHash::Md5 );
7650 else if ( method == QLatin1String(
"sha1" ) )
7652 hash = fcnHash( str, QCryptographicHash::Sha1 );
7654 else if ( method == QLatin1String(
"sha224" ) )
7656 hash = fcnHash( str, QCryptographicHash::Sha224 );
7658 else if ( method == QLatin1String(
"sha256" ) )
7660 hash = fcnHash( str, QCryptographicHash::Sha256 );
7662 else if ( method == QLatin1String(
"sha384" ) )
7664 hash = fcnHash( str, QCryptographicHash::Sha384 );
7666 else if ( method == QLatin1String(
"sha512" ) )
7668 hash = fcnHash( str, QCryptographicHash::Sha512 );
7670 else if ( method == QLatin1String(
"sha3_224" ) )
7672 hash = fcnHash( str, QCryptographicHash::Sha3_224 );
7674 else if ( method == QLatin1String(
"sha3_256" ) )
7676 hash = fcnHash( str, QCryptographicHash::Sha3_256 );
7678 else if ( method == QLatin1String(
"sha3_384" ) )
7680 hash = fcnHash( str, QCryptographicHash::Sha3_384 );
7682 else if ( method == QLatin1String(
"sha3_512" ) )
7684 hash = fcnHash( str, QCryptographicHash::Sha3_512 );
7686 else if ( method == QLatin1String(
"keccak_224" ) )
7688 hash = fcnHash( str, QCryptographicHash::Keccak_224 );
7690 else if ( method == QLatin1String(
"keccak_256" ) )
7692 hash = fcnHash( str, QCryptographicHash::Keccak_256 );
7694 else if ( method == QLatin1String(
"keccak_384" ) )
7696 hash = fcnHash( str, QCryptographicHash::Keccak_384 );
7698 else if ( method == QLatin1String(
"keccak_512" ) )
7700 hash = fcnHash( str, QCryptographicHash::Keccak_512 );
7704 parent->
setEvalErrorString( QObject::tr(
"Hash method %1 is not available on this system." ).arg( str ) );
7711 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Md5 );
7716 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Sha256 );
7721 const QByteArray input = values.at( 0 ).toByteArray();
7722 return QVariant( QString( input.toBase64() ) );
7727 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7729 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7731 query.addQueryItem( it.key(), it.value().toString() );
7733 return query.toString( QUrl::ComponentFormattingOption::FullyEncoded );
7738 const QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7739 const QByteArray base64 = value.toLocal8Bit();
7740 const QByteArray decoded = QByteArray::fromBase64( base64 );
7741 return QVariant( decoded );
7746static 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 )
7751 parent->
setEvalErrorString( QStringLiteral(
"This function was called without an expression context." ) );
7755 const QVariant sourceLayerRef = context->
variable( QStringLiteral(
"layer" ) );
7758 QgsVectorLayer *sourceLayer = QgsExpressionUtils::getVectorLayer( sourceLayerRef, context, parent );
7767 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
7770 const bool layerCanBeCached = node->
isStatic( parent, context );
7771 QVariant targetLayerValue = node->
eval( parent, context );
7775 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
7777 QString subExpString = node->dump();
7779 bool testOnly = ( subExpString ==
"NULL" );
7782 QgsVectorLayer *targetLayer = QgsExpressionUtils::getVectorLayer( targetLayerValue, context, parent );
7786 parent->
setEvalErrorString( QObject::tr(
"Layer '%1' could not be loaded." ).arg( targetLayerValue.toString() ) );
7791 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
7793 QString filterString = node->dump();
7794 if ( filterString !=
"NULL" )
7796 request.setFilterExpression( filterString );
7800 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
7802 QVariant limitValue = node->eval( parent, context );
7804 qlonglong limit = QgsExpressionUtils::getIntValue( limitValue, parent );
7807 double max_distance = 0;
7808 if ( isNearestFunc )
7810 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
7812 QVariant distanceValue = node->eval( parent, context );
7814 max_distance = QgsExpressionUtils::getDoubleValue( distanceValue, parent );
7818 node = QgsExpressionUtils::getNode( values.at( isNearestFunc ? 5 : 4 ), parent );
7820 QVariant cacheValue = node->eval( parent, context );
7822 bool cacheEnabled = cacheValue.toBool();
7828 double minOverlap { -1 };
7829 double minInscribedCircleRadius { -1 };
7830 bool returnDetails =
false;
7831 bool sortByMeasure =
false;
7832 bool sortAscending =
false;
7833 bool requireMeasures =
false;
7834 bool overlapOrRadiusFilter =
false;
7835 if ( isIntersectsFunc )
7838 node = QgsExpressionUtils::getNode( values.at( 5 ), parent );
7840 const QVariant minOverlapValue = node->eval( parent, context );
7842 minOverlap = QgsExpressionUtils::getDoubleValue( minOverlapValue, parent );
7843 node = QgsExpressionUtils::getNode( values.at( 6 ), parent );
7845 const QVariant minInscribedCircleRadiusValue = node->eval( parent, context );
7847 minInscribedCircleRadius = QgsExpressionUtils::getDoubleValue( minInscribedCircleRadiusValue, parent );
7848 node = QgsExpressionUtils::getNode( values.at( 7 ), parent );
7850 returnDetails = !testOnly && node->eval( parent, context ).toBool();
7851 node = QgsExpressionUtils::getNode( values.at( 8 ), parent );
7853 const QString sorting { node->eval( parent, context ).toString().toLower() };
7854 sortByMeasure = !testOnly && ( sorting.startsWith(
"asc" ) || sorting.startsWith(
"des" ) );
7855 sortAscending = sorting.startsWith(
"asc" );
7856 requireMeasures = sortByMeasure || returnDetails;
7857 overlapOrRadiusFilter = minInscribedCircleRadius != -1 || minOverlap != -1;
7864 if ( sourceLayer && targetLayer->crs() != sourceLayer->crs() )
7867 request.setDestinationCrs( sourceLayer->crs(), TransformContext );
7870 bool sameLayers = ( sourceLayer && sourceLayer->id() == targetLayer->id() );
7873 if ( bboxGrow != 0 )
7875 intDomain.
grow( bboxGrow );
7878 const QString cacheBase { QStringLiteral(
"%1:%2:%3" ).arg( targetLayer->id(), subExpString, filterString ) };
7884 QList<QgsFeature> features;
7885 if ( isNearestFunc || ( layerCanBeCached && cacheEnabled ) )
7889 const QString cacheLayer { QStringLiteral(
"ovrlaylyr:%1" ).arg( cacheBase ) };
7890 const QString cacheIndex { QStringLiteral(
"ovrlayidx:%1" ).arg( cacheBase ) };
7894 cachedTarget = targetLayer->
materialize( request );
7895 if ( layerCanBeCached )
7896 context->
setCachedValue( cacheLayer, QVariant::fromValue( cachedTarget ) );
7906 if ( layerCanBeCached )
7907 context->
setCachedValue( cacheIndex, QVariant::fromValue( spatialIndex ) );
7914 QList<QgsFeatureId> fidsList;
7915 if ( isNearestFunc )
7917 fidsList = spatialIndex.
nearestNeighbor( geometry, sameLayers ? limit + 1 : limit, max_distance );
7921 fidsList = spatialIndex.
intersects( intDomain );
7924 QListIterator<QgsFeatureId> i( fidsList );
7925 while ( i.hasNext() )
7928 if ( sameLayers && feat.
id() == fId2 )
7930 features.append( cachedTarget->
getFeature( fId2 ) );
7938 request.setFilterRect( intDomain );
7943 if ( sameLayers && feat.
id() == feat2.
id() )
7945 features.append( feat2 );
7953 const QString expCacheKey { QStringLiteral(
"exp:%1" ).arg( cacheBase ) };
7954 const QString ctxCacheKey { QStringLiteral(
"ctx:%1" ).arg( cacheBase ) };
7960 subExpression.
prepare( &subContext );
7973 auto testLinestring = [ = ](
const QgsGeometry intersection,
double & overlapValue ) ->
bool
7975 bool testResult {
false };
7977 QVector<double> overlapValues;
7981 const QgsCurve *geom = qgsgeometry_cast< const QgsCurve * >( *it );
7983 if ( minOverlap != -1 || requireMeasures )
7985 overlapValue = geom->
length();
7986 overlapValues.append( overlapValue );
7987 if ( minOverlap != -1 )
7989 if ( overlapValue >= minOverlap )
8001 if ( ! overlapValues.isEmpty() )
8003 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
8010 auto testPolygon = [ = ](
const QgsGeometry intersection,
double & radiusValue,
double & overlapValue ) ->
bool
8013 bool testResult {
false };
8015 QVector<double> overlapValues;
8016 QVector<double> radiusValues;
8019 const QgsCurvePolygon *geom = qgsgeometry_cast< const QgsCurvePolygon * >( *it );
8021 if ( minOverlap != -1 || requireMeasures )
8023 overlapValue = geom->
area();
8024 overlapValues.append( geom->
area() );
8025 if ( minOverlap != - 1 )
8027 if ( overlapValue >= minOverlap )
8039 if ( minInscribedCircleRadius != -1 || requireMeasures )
8042 const double width = bbox.
width();
8043 const double height = bbox.
height();
8044 const double size = width > height ? width : height;
8045 const double tolerance = size / 100.0;
8047 testResult = radiusValue >= minInscribedCircleRadius;
8048 radiusValues.append( radiusValues );
8053 if ( !radiusValues.isEmpty() )
8055 radiusValue = *std::max_element( radiusValues.cbegin(), radiusValues.cend() );
8058 if ( ! overlapValues.isEmpty() )
8060 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
8070 QVariantList results;
8072 QListIterator<QgsFeature> i( features );
8073 while ( i.hasNext() && ( sortByMeasure || limit == -1 || foundCount < limit ) )
8079 if ( ! relationFunction || ( geometry.*relationFunction )( feat2.
geometry() ) )
8082 double overlapValue = -1;
8083 double radiusValue = -1;
8085 if ( isIntersectsFunc && ( requireMeasures || overlapOrRadiusFilter ) )
8098 for (
const auto &geom : std::as_const( geometries ) )
8100 switch ( geom.type() )
8104 poly.append( geom.asPolygon() );
8109 line.append( geom.asPolyline() );
8114 point.append( geom.asPoint() );
8125 switch ( geometry.
type() )
8153 switch ( intersection.
type() )
8160 bool testResult { testPolygon( intersection, radiusValue, overlapValue ) };
8162 if ( ! testResult && overlapOrRadiusFilter )
8175 if ( minInscribedCircleRadius != -1 )
8181 const bool testResult { testLinestring( intersection, overlapValue ) };
8183 if ( ! testResult && overlapOrRadiusFilter )
8196 if ( minInscribedCircleRadius != -1 )
8201 bool testResult {
false };
8202 if ( minOverlap != -1 || requireMeasures )
8222 testResult = testLinestring( feat2.
geometry(), overlapValue );
8227 testResult = testPolygon( feat2.
geometry(), radiusValue, overlapValue );
8233 if ( ! testResult && overlapOrRadiusFilter )
8261 const QVariant expResult = subExpression.
evaluate( &subContext );
8263 if ( requireMeasures )
8265 QVariantMap resultRecord;
8266 resultRecord.insert( QStringLiteral(
"id" ), feat2.
id() );
8267 resultRecord.insert( QStringLiteral(
"result" ), expResult );
8269 resultRecord.insert( QStringLiteral(
"overlap" ), overlapValue );
8271 if ( radiusValue != -1 )
8273 resultRecord.insert( QStringLiteral(
"radius" ), radiusValue );
8275 results.append( resultRecord );
8279 results.append( expResult );
8285 results.append( feat2.
id() );
8299 if ( requireMeasures )
8301 if ( sortByMeasure )
8303 std::sort( results.begin(), results.end(), [ sortAscending ](
const QVariant & recordA,
const QVariant & recordB ) ->
bool
8305 return sortAscending ?
8306 recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble()
8307 : recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble();
8311 if ( limit > 0 && results.size() > limit )
8313 results.erase( results.begin() + limit );
8316 if ( ! returnDetails )
8318 QVariantList expResults;
8319 for (
auto it = results.constBegin(); it != results.constEnd(); ++it )
8321 expResults.append( it->toMap().value( QStringLiteral(
"result" ) ) );
8331 QVariantList disjoint_results;
8340 if ( !results.contains( feat2.
id() ) )
8343 disjoint_results.append( subExpression.
evaluate( &subContext ) );
8346 return disjoint_results;
8389 return executeGeomOverlay( values, context, parent,
nullptr,
false, 0,
true );
8398 QMutexLocker locker( &sFunctionsMutex );
8400 QList<QgsExpressionFunction *> &functions = *sFunctions();
8402 if ( functions.isEmpty() )
8440 functions << randFunc;
8444 functions << randfFunc;
8447 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max" ), -1, fcnMax, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8448 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min" ), -1, fcnMin, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8455 <<
new QgsStaticExpressionFunction( QStringLiteral(
"pi" ), 0, fcnPi, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$pi" ) )
8460 <<
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" ) )
8461 <<
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" ) )
8462 <<
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" ) )
8467 <<
new QgsStaticExpressionFunction( QStringLiteral(
"coalesce" ), -1, fcnCoalesce, QStringLiteral(
"Conditionals" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8481 QStringLiteral(
"Aggregates" ),
8490 if ( !node->
args() )
8493 QSet<QString> referencedVars;
8505 return referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() );
8514 if ( !node->
args() )
8515 return QSet<QString>();
8517 QSet<QString> referencedCols;
8518 QSet<QString> referencedVars;
8533 if ( referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() ) )
8536 return referencedCols;
8549 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count" ), aggParams, fcnAggregateCount, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8550 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_distinct" ), aggParams, fcnAggregateCountDistinct, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8551 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_missing" ), aggParams, fcnAggregateCountMissing, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8552 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minimum" ), aggParams, fcnAggregateMin, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8553 <<
new QgsStaticExpressionFunction( QStringLiteral(
"maximum" ), aggParams, fcnAggregateMax, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8554 <<
new QgsStaticExpressionFunction( QStringLiteral(
"sum" ), aggParams, fcnAggregateSum, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8555 <<
new QgsStaticExpressionFunction( QStringLiteral(
"mean" ), aggParams, fcnAggregateMean, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8556 <<
new QgsStaticExpressionFunction( QStringLiteral(
"median" ), aggParams, fcnAggregateMedian, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8557 <<
new QgsStaticExpressionFunction( QStringLiteral(
"stdev" ), aggParams, fcnAggregateStdev, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8558 <<
new QgsStaticExpressionFunction( QStringLiteral(
"range" ), aggParams, fcnAggregateRange, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8559 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minority" ), aggParams, fcnAggregateMinority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8560 <<
new QgsStaticExpressionFunction( QStringLiteral(
"majority" ), aggParams, fcnAggregateMajority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8561 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q1" ), aggParams, fcnAggregateQ1, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8562 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q3" ), aggParams, fcnAggregateQ3, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8563 <<
new QgsStaticExpressionFunction( QStringLiteral(
"iqr" ), aggParams, fcnAggregateIQR, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8564 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min_length" ), aggParams, fcnAggregateMinLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8565 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max_length" ), aggParams, fcnAggregateMaxLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8566 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect" ), aggParams, fcnAggregateCollectGeometry, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8567 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate" ), aggParamsConcat, fcnAggregateStringConcat, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8568 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate_unique" ), aggParamsConcat, fcnAggregateStringConcatUnique, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8569 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array_agg" ), aggParamsArray, fcnAggregateArray, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8574 <<
new QgsStaticExpressionFunction( QStringLiteral(
"now" ), 0, fcnNow, QStringLiteral(
"Date and Time" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$now" ) )
8577 fcnAge, QStringLiteral(
"Date and Time" ) )
8591 fcnMakeDate, QStringLiteral(
"Date and Time" ) )
8595 fcnMakeTime, QStringLiteral(
"Date and Time" ) )
8602 fcnMakeDateTime, QStringLiteral(
"Date and Time" ) )
8610 fcnMakeInterval, QStringLiteral(
"Date and Time" ) )
8635 false, QSet< QString >(),
false, QStringList(), true )
8636 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concat" ), -1, fcnConcat, QStringLiteral(
"String" ), QString(),
false, QSet<QString>(),
false, QStringList(), true )
8654 fcnColorMixRgb, QStringLiteral(
"Color" ) )
8658 fcnColorMix, QStringLiteral(
"Color" ) )
8662 fcnColorRgb, QStringLiteral(
"Color" ) )
8667 fcnColorRgbF, QStringLiteral(
"Color" ) )
8672 fncColorRgba, QStringLiteral(
"Color" ) )
8681 fcnCreateRamp, QStringLiteral(
"Color" ) )
8685 fcnColorHsl, QStringLiteral(
"Color" ) )
8690 fncColorHsla, QStringLiteral(
"Color" ) )
8695 fcnColorHslF, QStringLiteral(
"Color" ) )
8699 fcnColorHsv, QStringLiteral(
"Color" ) )
8704 fncColorHsva, QStringLiteral(
"Color" ) )
8709 fcnColorHsvF, QStringLiteral(
"Color" ) )
8714 fcnColorCmyk, QStringLiteral(
"Color" ) )
8720 fncColorCmyka, QStringLiteral(
"Color" ) )
8726 fcnColorCmykF, QStringLiteral(
"Color" ) )
8729 fncColorPart, QStringLiteral(
"Color" ) )
8732 fncDarker, QStringLiteral(
"Color" ) )
8735 fncLighter, QStringLiteral(
"Color" ) )
8740 fcnBaseFileName, QStringLiteral(
"Files and Paths" ) )
8742 fcnFileSuffix, QStringLiteral(
"Files and Paths" ) )
8744 fcnFileExists, QStringLiteral(
"Files and Paths" ) )
8746 fcnFileName, QStringLiteral(
"Files and Paths" ) )
8748 fcnPathIsFile, QStringLiteral(
"Files and Paths" ) )
8750 fcnPathIsDir, QStringLiteral(
"Files and Paths" ) )
8752 fcnFilePath, QStringLiteral(
"Files and Paths" ) )
8754 fcnFileSize, QStringLiteral(
"Files and Paths" ) )
8757 fcnExif, QStringLiteral(
"Files and Paths" ) )
8759 fcnExifGeoTag, QStringLiteral(
"GeometryGroup" ) )
8763 fcnGenericHash, QStringLiteral(
"Conversions" ) )
8765 fcnHashMd5, QStringLiteral(
"Conversions" ) )
8767 fcnHashSha256, QStringLiteral(
"Conversions" ) )
8771 fcnToBase64, QStringLiteral(
"Conversions" ) )
8773 fcnFromBase64, QStringLiteral(
"Conversions" ) )
8779 geomFunc->setIsStatic(
false );
8780 functions << geomFunc;
8784 functions << areaFunc;
8790 functions << lengthFunc;
8794 functions << perimeterFunc;
8800 fcnRoundness, QStringLiteral(
"GeometryGroup" ) );
8814 QMap< QString, QgsExpressionFunction::FcnEval > geometry_overlay_definitions
8816 { QStringLiteral(
"overlay_intersects" ), fcnGeomOverlayIntersects },
8817 { QStringLiteral(
"overlay_contains" ), fcnGeomOverlayContains },
8818 { QStringLiteral(
"overlay_crosses" ), fcnGeomOverlayCrosses },
8819 { QStringLiteral(
"overlay_equals" ), fcnGeomOverlayEquals },
8820 { QStringLiteral(
"overlay_touches" ), fcnGeomOverlayTouches },
8821 { QStringLiteral(
"overlay_disjoint" ), fcnGeomOverlayDisjoint },
8822 { QStringLiteral(
"overlay_within" ), fcnGeomOverlayWithin },
8824 QMapIterator< QString, QgsExpressionFunction::FcnEval > i( geometry_overlay_definitions );
8825 while ( i.hasNext() )
8842 functions << fcnGeomOverlayFunc;
8855 functions << fcnGeomOverlayNearestFunc;
8868 fcnNodesToPoints, QStringLiteral(
"GeometryGroup" ) )
8870 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect_geometries" ), -1, fcnCollectGeometries, QStringLiteral(
"GeometryGroup" ) )
8875 fcnMakePointM, QStringLiteral(
"GeometryGroup" ) )
8881 fcnMakeTriangle, QStringLiteral(
"GeometryGroup" ) )
8886 fcnMakeCircle, QStringLiteral(
"GeometryGroup" ) )
8893 fcnMakeEllipse, QStringLiteral(
"GeometryGroup" ) )
8899 fcnMakeRegularPolygon, QStringLiteral(
"GeometryGroup" ) )
8903 fcnMakeSquare, QStringLiteral(
"GeometryGroup" ) )
8909 fcnMakeRectangleFrom3Points, QStringLiteral(
"GeometryGroup" ) )
8913#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
8919 }, fcnGeomMakeValid, QStringLiteral(
"GeometryGroup" ) );
8928 functions << xAtFunc;
8933 functions << yAtFunc;
8949 fcnDisjoint, QStringLiteral(
"GeometryGroup" ) )
8952 fcnIntersects, QStringLiteral(
"GeometryGroup" ) )
8955 fcnTouches, QStringLiteral(
"GeometryGroup" ) )
8958 fcnCrosses, QStringLiteral(
"GeometryGroup" ) )
8961 fcnContains, QStringLiteral(
"GeometryGroup" ) )
8964 fcnOverlaps, QStringLiteral(
"GeometryGroup" ) )
8967 fcnWithin, QStringLiteral(
"GeometryGroup" ) )
8971 fcnTranslate, QStringLiteral(
"GeometryGroup" ) )
8976 fcnRotate, QStringLiteral(
"GeometryGroup" ) )
8981 fcnScale, QStringLiteral(
"GeometryGroup" ) )
8992 fcnAffineTransform, QStringLiteral(
"GeometryGroup" ) )
8999 fcnBuffer, QStringLiteral(
"GeometryGroup" ) )
9001 fcnForceRHR, QStringLiteral(
"GeometryGroup" ) )
9003 fcnForcePolygonCW, QStringLiteral(
"GeometryGroup" ) )
9005 fcnForcePolygonCCW, QStringLiteral(
"GeometryGroup" ) )
9015 , fcnTaperedBuffer, QStringLiteral(
"GeometryGroup" ) )
9018 , fcnBufferByM, QStringLiteral(
"GeometryGroup" ) )
9024 fcnOffsetCurve, QStringLiteral(
"GeometryGroup" ) )
9030 fcnSingleSidedBuffer, QStringLiteral(
"GeometryGroup" ) )
9034 fcnExtend, QStringLiteral(
"GeometryGroup" ) )
9043 fcnInteriorRingN, QStringLiteral(
"GeometryGroup" ) )
9046 fcnGeometryN, QStringLiteral(
"GeometryGroup" ) )
9053 }, fcnSharedPaths, QStringLiteral(
"GeometryGroup" ) )
9067 }, fcnTriangularWave, QStringLiteral(
"GeometryGroup" ) )
9076 }, fcnTriangularWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9083 }, fcnSquareWave, QStringLiteral(
"GeometryGroup" ) )
9092 }, fcnSquareWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9099 }, fcnRoundWave, QStringLiteral(
"GeometryGroup" ) )
9108 }, fcnRoundWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9117 }, fcnApplyDashPattern, QStringLiteral(
"GeometryGroup" ) )
9122 }, fcnDensifyByCount, QStringLiteral(
"GeometryGroup" ) )
9127 }, fcnDensifyByDistance, QStringLiteral(
"GeometryGroup" ) )
9139#
if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
9146 fcnOrientedBBox, QStringLiteral(
"GeometryGroup" ) )
9149 fcnMainAngle, QStringLiteral(
"GeometryGroup" ) )
9153 fcnMinimalCircle, QStringLiteral(
"GeometryGroup" ) )
9156 fcnDifference, QStringLiteral(
"GeometryGroup" ) )
9159 fcnDistance, QStringLiteral(
"GeometryGroup" ) )
9162 fcnHausdorffDistance, QStringLiteral(
"GeometryGroup" ) )
9165 fcnIntersection, QStringLiteral(
"GeometryGroup" ) )
9168 fcnSymDifference, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"symDifference" ) )
9171 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
9174 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
9177 fcnGeomToWKT, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"geomToWKT" ) )
9179 fcnGeomToWKB, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false )
9184 fcnTransformGeometry, QStringLiteral(
"GeometryGroup" ) )
9188 fcnExtrude, QStringLiteral(
"GeometryGroup" ), QString() )
9190 fcnGeomIsMultipart, QStringLiteral(
"GeometryGroup" ) )
9192 fcnZMax, QStringLiteral(
"GeometryGroup" ) )
9194 fcnZMin, QStringLiteral(
"GeometryGroup" ) )
9196 fcnMMax, QStringLiteral(
"GeometryGroup" ) )
9198 fcnMMin, QStringLiteral(
"GeometryGroup" ) )
9200 fcnSinuosity, QStringLiteral(
"GeometryGroup" ) )
9202 fcnStraightDistance2d, QStringLiteral(
"GeometryGroup" ) );
9208 fcnOrderParts, QStringLiteral(
"GeometryGroup" ), QString() );
9213 const QList< QgsExpressionNode *> argList = node->
args()->list();
9216 if ( !argNode->isStatic( parent, context ) )
9224 QString expString = argNode->
eval( parent, context ).toString();
9228 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9240 QString
expression = argNode->
eval( parent, context ).toString();
9242 e.prepare( context );
9248 functions << orderPartsFunc;
9253 fcnClosestPoint, QStringLiteral(
"GeometryGroup" ) )
9256 fcnShortestLine, QStringLiteral(
"GeometryGroup" ) )
9261 fcnLineInterpolatePointByM, QStringLiteral(
"GeometryGroup" ) )
9268 fcnLineLocateM, QStringLiteral(
"GeometryGroup" ) )
9281 functions << idFunc;
9285 functions << currentFeatureFunc;
9287 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" ) );
9289 functions << uuidFunc;
9296 fcnGetFeature, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"QgsExpressionUtils::getFeature" ) )
9299 fcnGetFeatureById, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false );
9304 functions << attributesFunc;
9308 functions << representAttributesFunc;
9316 functions << validateFeature;
9325 functions << validateAttribute;
9328 QStringLiteral(
"maptip" ),
9331 QStringLiteral(
"Record and Attributes" ),
9337 functions << maptipFunc;
9340 QStringLiteral(
"display_expression" ),
9342 fcnFeatureDisplayExpression,
9343 QStringLiteral(
"Record and Attributes" ),
9349 functions << displayFunc;
9352 QStringLiteral(
"is_selected" ),
9355 QStringLiteral(
"Record and Attributes" ),
9361 functions << isSelectedFunc;
9365 QStringLiteral(
"num_selected" ),
9368 QStringLiteral(
"Record and Attributes" ),
9376 QStringLiteral(
"sqlite_fetch_and_increment" ),
9384 fcnSqliteFetchAndIncrement,
9385 QStringLiteral(
"Record and Attributes" )
9403 parent->
setEvalErrorString( tr(
"If represent_value is called with 1 parameter, it must be an attribute." ) );
9413 parent->
setEvalErrorString( tr(
"represent_value must be called with exactly 1 or 2 parameters." ) );
9419 functions << representValueFunc;
9425 fcnGetLayerProperty, QStringLiteral(
"Map Layers" ) )
9430 fcnDecodeUri, QStringLiteral(
"Map Layers" ) )
9434 fcnMimeType, QStringLiteral(
"General" ) )
9451 QgsExpressionNode *argNode = node->args()->at( 0 );
9453 if ( !argNode->isStatic( parent, context ) )
9456 const QString varName = argNode->eval( parent, context ).toString();
9457 if ( varName == QLatin1String(
"feature" ) || varName == QLatin1String(
"id" ) || varName == QLatin1String(
"geometry" ) )
9460 const QgsExpressionContextScope *scope = context->activeScopeForVariable( varName );
9461 return scope ? scope->isStatic( varName ) : false;
9469 if ( node && node->
args()->
count() > 0 )
9474 if ( literal->value() == QLatin1String(
"geometry" ) || literal->value() == QLatin1String(
"feature" ) )
9491 QgsExpressionNode *argNode = node->args()->at( 0 );
9493 if ( argNode->isStatic( parent, context ) )
9495 QString expString = argNode->eval( parent, context ).toString();
9497 QgsExpression e( expString );
9499 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9506 functions << evalTemplateFunction;
9514 QgsExpressionNode *argNode = node->args()->at( 0 );
9516 if ( argNode->isStatic( parent, context ) )
9518 QString expString = argNode->eval( parent, context ).toString();
9520 QgsExpression e( expString );
9522 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9530 functions << evalFunc;
9536 const QList< QgsExpressionNode *> argList = node->
args()->list();
9539 if ( !argNode->
isStatic( parent, context ) )
9551 functions << attributeFunc;
9562 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array" ), -1, fcnArray, QStringLiteral(
"Arrays" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
9611 fcnMapPrefixKeys, QStringLiteral(
"Maps" ) )
9613 fcnMapToHtmlTable, QStringLiteral(
"Maps" ) )
9615 fcnMapToHtmlDefinitionList, QStringLiteral(
"Maps" ) )
9617 fcnToFormUrlEncode, QStringLiteral(
"Maps" ) )
9626 *sOwnedFunctions() << func;
9627 *sBuiltinFunctions() << func->name();
9628 sBuiltinFunctions()->append( func->aliases() );
9642 QMutexLocker locker( &sFunctionsMutex );
9643 sFunctions()->append( function );
9644 if ( transferOwnership )
9645 sOwnedFunctions()->append( function );
9660 QMutexLocker locker( &sFunctionsMutex );
9661 sFunctions()->removeAt( fnIdx );
9662 sFunctionIndexMap.clear();
9670 qDeleteAll( *sOwnedFunctions() );
9671 sOwnedFunctions()->clear();
9676 if ( sBuiltinFunctions()->isEmpty() )
9680 return *sBuiltinFunctions();
9687 QStringLiteral(
"Arrays" ) )
9698 if ( args->
count() < 2 )
9701 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9711 QVariantList result;
9713 if ( args->
count() < 2 )
9717 QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9720 std::unique_ptr< QgsExpressionContext > tempContext;
9723 tempContext = std::make_unique< QgsExpressionContext >();
9724 subContext = tempContext.get();
9731 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it, ++i )
9735 result << args->
at( 1 )->
eval( parent, subContext );
9760 if ( args->
count() < 2 )
9764 args->
at( 0 )->
prepare( parent, context );
9768 subContext = *context;
9775 args->
at( 1 )->
prepare( parent, &subContext );
9785 QStringLiteral(
"Arrays" ) )
9796 if ( args->
count() < 2 )
9799 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9809 QVariantList result;
9811 if ( args->
count() < 2 )
9815 const QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9818 std::unique_ptr< QgsExpressionContext > tempContext;
9821 tempContext = std::make_unique< QgsExpressionContext >();
9822 subContext = tempContext.get();
9829 if ( args->
count() >= 3 )
9831 const QVariant limitVar = args->
at( 2 )->
eval( parent, context );
9833 if ( QgsExpressionUtils::isIntSafe( limitVar ) )
9835 limit = limitVar.toInt();
9843 for (
const QVariant &value : array )
9846 if ( args->
at( 1 )->
eval( parent, subContext ).toBool() )
9850 if ( limit > 0 && limit == result.size() )
9877 if ( args->
count() < 2 )
9881 args->
at( 0 )->
prepare( parent, context );
9885 subContext = *context;
9891 args->
at( 1 )->
prepare( parent, &subContext );
9900 QStringLiteral(
"General" ) )
9911 if ( args->
count() < 3 )
9915 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9917 QVariant
name = args->
at( 0 )->
eval( parent, context );
9918 QVariant value = args->
at( 1 )->
eval( parent, context );
9921 appendTemporaryVariable( context,
name.toString(), value );
9922 if ( args->
at( 2 )->
isStatic( parent, context ) )
9924 popTemporaryVariable( context );
9935 if ( args->
count() < 3 )
9939 QVariant
name = args->
at( 0 )->
eval( parent, context );
9940 QVariant value = args->
at( 1 )->
eval( parent, context );
9943 std::unique_ptr< QgsExpressionContext > tempContext;
9944 if ( !updatedContext )
9946 tempContext = std::make_unique< QgsExpressionContext >();
9947 updatedContext = tempContext.get();
9950 appendTemporaryVariable( updatedContext,
name.toString(), value );
9951 result = args->
at( 2 )->
eval( parent, updatedContext );
9954 popTemporaryVariable( updatedContext );
9975 if ( args->
count() < 3 )
9980 QVariant value = args->
at( 1 )->
prepare( parent, context );
9983 std::unique_ptr< QgsExpressionContext > tempContext;
9984 if ( !updatedContext )
9986 tempContext = std::make_unique< QgsExpressionContext >();
9987 updatedContext = tempContext.get();
9990 appendTemporaryVariable( updatedContext,
name.toString(), value );
9991 args->
at( 2 )->
prepare( parent, updatedContext );
9994 popTemporaryVariable( updatedContext );
9999void QgsWithVariableExpressionFunction::popTemporaryVariable(
const QgsExpressionContext *context )
const
10002 delete updatedContext->
popScope();
10005void QgsWithVariableExpressionFunction::appendTemporaryVariable(
const QgsExpressionContext *context,
const QString &name,
const QVariant &value )
const
@ Left
Buffer to left of line.
DashPatternSizeAdjustment
Dash pattern size adjustment options.
@ ScaleDashOnly
Only dash lengths are adjusted.
@ ScaleBothDashAndGap
Both the dash and gap lengths are adjusted equally.
@ ScaleGapOnly
Only gap lengths are adjusted.
@ Success
Operation succeeded.
@ Visvalingam
The simplification gives each point in a line an importance weighting, so that least important points...
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
JoinStyle
Join styles for buffers.
@ Bevel
Use beveled joins.
@ Round
Use rounded joins.
@ Miter
Use mitered joins.
RasterBandStatistic
Available raster band statistics.
@ StdDev
Standard deviation.
@ NoStatistic
No statistic.
@ Group
Composite group layer. Added in QGIS 3.24.
@ Plugin
Plugin based layer.
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
EndCapStyle
End cap styles for buffers.
@ Flat
Flat cap (in line with start/end of line)
@ Square
Square cap (extends past start/end of line by buffer distance)
Aggregate
Available aggregates to calculate.
@ StringMinimumLength
Minimum length of string (string fields only)
@ FirstQuartile
First quartile (numeric fields only)
@ Mean
Mean of values (numeric fields only)
@ Median
Median of values (numeric fields only)
@ StringMaximumLength
Maximum length of string (string fields only)
@ Range
Range of values (max - min) (numeric and datetime fields only)
@ StringConcatenateUnique
Concatenate unique values with a joining string (string fields only). Specify the delimiter using set...
@ Minority
Minority of values.
@ CountMissing
Number of missing (null) values.
@ ArrayAggregate
Create an array of values.
@ Majority
Majority of values.
@ StDevSample
Sample standard deviation of values (numeric fields only)
@ ThirdQuartile
Third quartile (numeric fields only)
@ CountDistinct
Number of distinct values.
@ StringConcatenate
Concatenate values with a joining string (string fields only). Specify the delimiter using setDelimit...
@ GeometryCollect
Create a multipart geometry from aggregated geometries.
@ InterQuartileRange
Inter quartile range (IQR) (numeric fields only)
DashPatternLineEndingRule
Dash pattern line ending rules.
@ HalfDash
Start or finish the pattern with a half length dash.
@ HalfGap
Start or finish the pattern with a half length gap.
@ FullGap
Start or finish the pattern with a full gap.
@ FullDash
Start or finish the pattern with a full dash.
MakeValidMethod
Algorithms to use when repairing invalid geometries.
@ Linework
Combines all rings into a set of noded lines and then extracts valid polygons from that linework.
@ Structure
Structured method, first makes all rings valid and then merges shells and subtracts holes from shells...
@ GeometryCollection
GeometryCollection.
Abstract base class for all geometries.
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
virtual QgsAbstractGeometry * boundary() const =0
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
virtual const QgsAbstractGeometry * simplifiedTypeRef() const
Returns a reference to the simplest lossless representation of this geometry, e.g.
bool isMeasure() const
Returns true if the geometry contains m values.
virtual QgsRectangle boundingBox() const
Returns the minimal bounding box for the geometry.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
part_iterator parts_end()
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
virtual double length() const
Returns the planar, 2-dimensional length of the geometry.
virtual QgsCoordinateSequence coordinateSequence() const =0
Retrieves the sequence of geometries, rings and nodes.
virtual int partCount() const =0
Returns count of parts contained in the geometry.
part_iterator parts_begin()
Returns STL-style iterator pointing to the first part of the geometry.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
static Qgis::Aggregate stringToAggregate(const QString &string, bool *ok=nullptr)
Converts a string to a aggregate type.
static QgsFieldFormatterRegistry * fieldFormatterRegistry()
Gets the registry of available field formatters.
Handles the array_filter(array, expression) expression function.
QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Returns result of evaluating the function.
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Evaluates the function, first evaluating all required arguments before passing them to the function's...
QgsArrayFilterExpressionFunction()
Handles the array loopingarray_Foreach(array, expression) expression function.
QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Returns result of evaluating the function.
QgsArrayForeachExpressionFunction()
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Evaluates the function, first evaluating all required arguments before passing them to the function's...
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
Abstract base class for color ramps.
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QString toProj() const
Returns a Proj string representation of this CRS.
QString ellipsoidAcronym() const
Returns the ellipsoid acronym for the ellipsoid used by the CRS.
Qgis::DistanceUnit mapUnits
Contains information about the context in which a coordinate transform is executed.
Custom exception class for Coordinate Reference System related exceptions.
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
bool isEmpty() const override
Returns true if the geometry is empty.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
double area() const override
Returns the planar, 2-dimensional area of the geometry.
double roundness() const
Returns the roundness of the curve polygon.
int ringCount(int part=0) const override
Returns the number of rings of which this geometry is built.
Abstract base class for curved geometry type.
double sinuosity() const
Returns the curve sinuosity, which is the ratio of the curve length() to curve straightDistance2d().
QgsCurve * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
virtual QgsCurve * curveSubstring(double startDistance, double endDistance) const =0
Returns a new curve representing a substring of this curve.
virtual bool isClosed() const
Returns true if the curve is closed.
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
double straightDistance2d() const
Returns the straight distance of the curve, i.e.
virtual QgsCurve * reversed() const =0
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
double measureArea(const QgsGeometry &geometry) const
Measures the area of a geometry.
double convertLengthMeasurement(double length, Qgis::DistanceUnit toUnits) const
Takes a length measurement calculated by this QgsDistanceArea object and converts it to a different d...
double measurePerimeter(const QgsGeometry &geometry) const
Measures the perimeter of a polygon geometry.
double measureLength(const QgsGeometry &geometry) const
Measures the length of a geometry.
double bearing(const QgsPointXY &p1, const QgsPointXY &p2) const
Computes the bearing (in radians) between two points.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
double convertAreaMeasurement(double area, Qgis::AreaUnit toUnits) const
Takes an area measurement calculated by this QgsDistanceArea object and converts it to a different ar...
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
bool isStatic(const QString &name) const
Tests whether the variable with the specified name is static and can be cached.
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
static void registerContextFunctions()
Registers all known core functions provided by QgsExpressionContextScope objects.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
void setCachedValue(const QString &key, const QVariant &value) const
Sets a value to cache within the expression context.
QString uniqueHash(bool &ok, const QSet< QString > &variables=QSet< QString >()) const
Returns a unique hash representing the current state of the context.
QgsGeometry geometry() const
Convenience function for retrieving the geometry for the context, if set.
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
QgsExpressionContextScope * activeScopeForVariable(const QString &name)
Returns the currently active scope from the context for a specified variable name.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly by the expression to check if evaluation sh...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
bool hasGeometry() const
Returns true if the context has a geometry associated with it.
bool hasCachedValue(const QString &key) const
Returns true if the expression context contains a cached value with a matching key.
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
QVariant cachedValue(const QString &key) const
Returns the matching cached value, if set.
bool hasFeature() const
Returns true if the context has a feature associated with it.
QgsFields fields() const
Convenience function for retrieving the fields for the context, if set.
Represents a single parameter passed to a function.
A abstract base class for defining QgsExpression functions.
QList< QgsExpressionFunction::Parameter > ParameterList
List of parameters, used for function definition.
bool operator==(const QgsExpressionFunction &other) const
virtual bool isDeprecated() const
Returns true if the function is deprecated and should not be presented as a valid option to users in ...
virtual bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
Will be called during prepare to determine if the function is static.
virtual QStringList aliases() const
Returns a list of possible aliases for the function.
bool lazyEval() const
true if this function should use lazy evaluation.
static bool allParamsStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context)
This will return true if all the params for the provided function node are static within the constrai...
QString name() const
The name of the function.
virtual QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
Evaluates the function, first evaluating all required arguments before passing them to the function's...
virtual QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)=0
Returns result of evaluating the function.
virtual QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const
Returns a set of field names which are required for this function.
virtual bool handlesNull() const
Returns true if the function handles NULL values in arguments by itself, and the default NULL value h...
virtual bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
This will be called during the prepare step() of an expression if it is not static.
virtual bool usesGeometry(const QgsExpressionNodeFunction *node) const
Does this function use a geometry object.
An expression node which takes it value from a feature's field.
QString name() const
The name of the column.
An expression node for expression functions.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
An expression node for literal values.
A list of expression nodes.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
QgsExpressionNode * at(int i)
Gets the node at position i in the list.
int count() const
Returns the number of nodes in the list.
Abstract base class for all nodes that can appear in an expression.
virtual QString dump() const =0
Dump this node into a serialized (part) of an expression.
QVariant eval(QgsExpression *parent, const QgsExpressionContext *context)
Evaluate this node with the given context and parent.
virtual bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const =0
Returns true if this node can be evaluated for a static value.
bool prepare(QgsExpression *parent, const QgsExpressionContext *context)
Prepare this node for evaluation.
virtual QSet< QString > referencedColumns() const =0
Abstract virtual method which returns a list of columns required to evaluate this node.
virtual QSet< QString > referencedVariables() const =0
Returns a set of all variables which are used in this expression.
A set of expression-related functions.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
static const QList< QgsExpressionFunction * > & Functions()
QString expression() const
Returns the original, unmodified expression string.
static void cleanRegisteredFunctions()
Deletes all registered functions whose ownership have been transferred to the expression engine.
Qgis::DistanceUnit distanceUnits() const
Returns the desired distance units for calculations involving geomCalculator(), e....
static bool registerFunction(QgsExpressionFunction *function, bool transferOwnership=false)
Registers a function to the expression engine.
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
static const QStringList & BuiltinFunctions()
static QString replaceExpressionText(const QString &action, const QgsExpressionContext *context, const QgsDistanceArea *distanceArea=nullptr)
This function replaces each expression between [% and %] in the string with the result of its evaluat...
static PRIVATE QString helpText(QString name)
Returns the help text for a specified function.
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value, QMetaType::Type fieldType=QMetaType::Type::UnknownType)
Create an expression allowing to evaluate if a field is equal to a value.
static bool unregisterFunction(const QString &name)
Unregisters a function from the expression engine.
Qgis::AreaUnit areaUnits() const
Returns the desired areal units for calculations involving geomCalculator(), e.g.,...
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions)
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QVariant evaluate()
Evaluate the feature and return the result.
QgsDistanceArea * geomCalculator()
Returns calculator used for distance and area calculations (used by $length, $area and $perimeter fun...
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
Represents a list of OrderByClauses, with the most important first and the least important last.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsFeatureRequest & setRequestMayBeNested(bool requestMayBeNested)
In case this request may be run nested within another already running iteration on the same connectio...
QgsFeatureRequest & setTimeout(int timeout)
Sets the timeout (in milliseconds) for the maximum time we should wait during feature requests before...
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
void setFeedback(QgsFeedback *feedback)
Attach a feedback object that can be queried regularly by the iterator to check if it should be cance...
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Sets the feature ID that should be fetched.
QgsVectorLayer * materialize(const QgsFeatureRequest &request, QgsFeedback *feedback=nullptr)
Materializes a request (query) made against this feature source, by running it over the source and re...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
bool isValid() const
Returns the validity of this feature.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
ConstraintStrength
Strength of constraints.
@ ConstraintStrengthNotSet
Constraint is not set.
@ ConstraintStrengthSoft
User is warned if constraint is violated but feature can still be accepted.
@ ConstraintStrengthHard
Constraint must be honored before feature can be accepted.
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Container of fields for a vector layer.
Q_INVOKABLE int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
int size() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
virtual bool removeGeometry(int nr)
Removes a geometry from the collection.
QgsGeometryCollection * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
int partCount() const override
Returns count of parts contained in the geometry.
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
static QVector< QgsLineString * > extractLineStrings(const QgsAbstractGeometry *geom)
Returns list of linestrings extracted from the passed geometry.
A geometry is the spatial representation of a feature.
double hausdorffDistanceDensify(const QgsGeometry &geom, double densifyFraction) const
Returns the Hausdorff distance between this geometry and geom.
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Returns a copy of the geometry which has been densified by adding the specified number of extra nodes...
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
double lineLocatePoint(const QgsGeometry &point) const
Returns a distance representing the location along this linestring of the closest point on this lines...
QgsGeometry difference(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing the points making up this geometry that do not make up other.
double length() const
Returns the planar, 2-dimensional length of geometry.
QgsGeometry offsetCurve(double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
QgsGeometry poleOfInaccessibility(double precision, double *distanceToBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
QgsGeometry squareWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs square waves along the boundary of the geometry, with the specified wavelength and amplitu...
QgsGeometry triangularWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs triangular waves along the boundary of the geometry, with the specified wavelength and amp...
bool vertexIdFromVertexNr(int number, QgsVertexId &id) const
Calculates the vertex ID from a vertex number.
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
bool touches(const QgsGeometry &geometry) const
Returns true if the geometry touches another geometry.
QgsGeometry applyDashPattern(const QVector< double > &pattern, Qgis::DashPatternLineEndingRule startRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternLineEndingRule endRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternSizeAdjustment adjustment=Qgis::DashPatternSizeAdjustment::ScaleBothDashAndGap, double patternOffset=0) const
Applies a dash pattern to a geometry, returning a MultiLineString geometry which is the input geometr...
QgsGeometry roundWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs rounded (sine-like) waves along the boundary of the geometry, with the specified wavelengt...
QgsGeometry nearestPoint(const QgsGeometry &other) const
Returns the nearest (closest) point on this geometry to another geometry.
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
static QgsGeometry fromMultiPolylineXY(const QgsMultiPolylineXY &multiline)
Creates a new geometry from a QgsMultiPolylineXY object.
QgsGeometry makeValid(Qgis::MakeValidMethod method=Qgis::MakeValidMethod::Linework, bool keepCollapsed=false) const
Attempts to make an invalid geometry valid without losing vertices.
QString lastError() const
Returns an error string referring to the last error encountered either when this geometry was created...
QgsGeometry combine(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing all the points in this geometry and other (a union geometry operation...
QgsGeometry variableWidthBufferByM(int segments) const
Calculates a variable width buffer for a (multi)linestring geometry, where the width at each node is ...
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
QgsMultiPointXY asMultiPoint() const
Returns the contents of the geometry as a multi-point.
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
bool disjoint(const QgsGeometry &geometry) const
Returns true if the geometry is disjoint of another geometry.
QVector< QgsGeometry > asGeometryCollection() const
Returns contents of the geometry as a list of geometries.
QgsGeometry roundWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized rounded (sine-like) waves along the boundary of the geometry,...
double distance(const QgsGeometry &geom) const
Returns the minimum distance between this geometry and another geometry.
QgsGeometry interpolate(double distance) const
Returns an interpolated point on the geometry at the specified distance.
QgsGeometry extrude(double x, double y)
Returns an extruded version of this geometry.
static QgsGeometry fromMultiPointXY(const QgsMultiPointXY &multipoint)
Creates a new geometry from a QgsMultiPointXY object.
QgsGeometry singleSidedBuffer(double distance, int segments, Qgis::BufferSide side, Qgis::JoinStyle joinStyle=Qgis::JoinStyle::Round, double miterLimit=2.0) const
Returns a single sided buffer for a (multi)line geometry.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
static Q_INVOKABLE QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
bool contains(const QgsPointXY *p) const
Returns true if the geometry contains the point p.
QgsGeometry forceRHR() const
Forces geometries to respect the Right-Hand-Rule, in which the area that is bounded by a polygon is t...
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
bool equals(const QgsGeometry &geometry) const
Test if this geometry is exactly equal to another geometry.
bool isGeosValid(Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const
Checks validity of the geometry using GEOS.
QgsGeometry taperedBuffer(double startWidth, double endWidth, int segments) const
Calculates a variable width buffer ("tapered buffer") for a (multi)curve geometry.
bool within(const QgsGeometry &geometry) const
Returns true if the geometry is completely within another geometry.
QgsGeometry orientedMinimumBoundingBox(double &area, double &angle, double &width, double &height) const
Returns the oriented minimum bounding box for the geometry, which is the smallest (by area) rotated r...
double area() const
Returns the planar, 2-dimensional area of the geometry.
bool isMultipart() const
Returns true if WKB of the geometry is of WKBMulti* type.
QgsGeometry centroid() const
Returns the center of mass of a geometry.
bool crosses(const QgsGeometry &geometry) const
Returns true if the geometry crosses another geometry.
double hausdorffDistance(const QgsGeometry &geom) const
Returns the Hausdorff distance between this geometry and geom.
QgsGeometry concaveHull(double targetPercent, bool allowHoles=false) const
Returns a possibly concave polygon that contains all the points in the geometry.
QgsGeometry convexHull() const
Returns the smallest convex polygon that contains all the points in the geometry.
QgsGeometry sharedPaths(const QgsGeometry &other) const
Find paths shared between the two given lineal geometries (this and other).
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
QgsGeometry intersection(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing the points shared by this geometry and other.
QgsGeometry symDifference(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing the points making up this geometry that do not make up other.
QgsGeometry minimalEnclosingCircle(QgsPointXY ¢er, double &radius, unsigned int segments=36) const
Returns the minimal enclosing circle for the geometry.
QgsGeometry mergeLines() const
Merges any connected lines in a LineString/MultiLineString geometry and converts them to single line ...
static QgsGeometry fromMultiPolygonXY(const QgsMultiPolygonXY &multipoly)
Creates a new geometry from a QgsMultiPolygonXY.
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
double distanceToVertex(int vertex) const
Returns the distance along this geometry from its first vertex to the specified vertex.
QgsAbstractGeometry::const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
QgsGeometry forcePolygonClockwise() const
Forces geometries to respect the exterior ring is clockwise, interior rings are counter-clockwise con...
static QgsGeometry createWedgeBuffer(const QgsPoint ¢er, double azimuth, double angularWidth, double outerRadius, double innerRadius=0)
Creates a wedge shaped buffer from a center point.
QgsGeometry extendLine(double startDistance, double endDistance) const
Extends a (multi)line geometry by extrapolating out the start or end of the line by a specified dista...
QgsGeometry triangularWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized triangular waves along the boundary of the geometry, with the specified wavelen...
QgsGeometry squareWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized square waves along the boundary of the geometry, with the specified wavelength ...
QgsGeometry simplify(double tolerance) const
Returns a simplified version of this geometry using a specified tolerance value.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Qgis::GeometryOperationResult rotate(double rotation, const QgsPointXY ¢er)
Rotate this geometry around the Z axis.
Qgis::GeometryOperationResult translate(double dx, double dy, double dz=0.0, double dm=0.0)
Translates this geometry by dx, dy, dz and dm.
double interpolateAngle(double distance) const
Returns the angle parallel to the linestring or polygon boundary at the specified distance along the ...
double angleAtVertex(int vertex) const
Returns the bisector angle for this geometry at the specified vertex.
QgsGeometry smooth(unsigned int iterations=1, double offset=0.25, double minimumDistance=-1.0, double maxAngle=180.0) const
Smooths a geometry by rounding off corners using the Chaikin algorithm.
QgsGeometry forcePolygonCounterClockwise() const
Forces geometries to respect the exterior ring is counter-clockwise, interior rings are clockwise con...
Q_INVOKABLE QString asWkt(int precision=17) const
Exports the geometry to WKT.
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
bool intersects(const QgsRectangle &rectangle) const
Returns true if this geometry exactly intersects with a rectangle.
QgsAbstractGeometry::vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
bool overlaps(const QgsGeometry &geometry) const
Returns true if the geometry overlaps another geometry.
QgsGeometry shortestLine(const QgsGeometry &other) const
Returns the shortest line joining this geometry to another geometry.
Does vector analysis using the GEOS library and handles import, export, and exception handling.
std::unique_ptr< QgsAbstractGeometry > maximumInscribedCircle(double tolerance, QString *errorMsg=nullptr) const
Returns the maximum inscribed circle.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
Represents a color stop within a QgsGradientColorRamp color ramp.
A representation of the interval between two datetime values.
bool isValid() const
Returns true if the interval is valid.
double days() const
Returns the interval duration in days.
double weeks() const
Returns the interval duration in weeks.
double months() const
Returns the interval duration in months (based on a 30 day month).
double seconds() const
Returns the interval duration in seconds.
double years() const
Returns the interval duration in years (based on an average year length)
double hours() const
Returns the interval duration in hours.
double minutes() const
Returns the interval duration in minutes.
Line string geometry type, with support for z-dimension and m-values.
bool lineLocatePointByM(double m, double &x, double &y, double &z, double &distanceFromStart, bool use3DDistance=true) const
Attempts to locate a point on the linestring by m value.
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
QString dataUrl() const
Returns the DataUrl of the layer used by QGIS Server in GetCapabilities request.
QString attributionUrl() const
Returns the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Base class for all map layer types.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QString source() const
Returns the source for the layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
QgsCoordinateReferenceSystem crs
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
QgsLayerMetadata metadata
QString publicSource(bool hidePassword=false) const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
virtual bool isEditable() const
Returns true if the layer can be edited.
double minimumScale() const
Returns the minimum map scale (i.e.
virtual Q_INVOKABLE QgsDataProvider * dataProvider()
Returns the layer's data provider, it may be nullptr.
double maximumScale() const
Returns the maximum map scale (i.e.
Implementation of GeometrySimplifier using the "MapToPixel" algorithm.
@ SimplifyGeometry
The geometries can be simplified using the current map2pixel context state.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Multi line string geometry collection.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
Multi point geometry collection.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
Custom exception class which is raised when an operation is not supported.
static QgsGeometry geometryFromGML(const QString &xmlString, const QgsOgcUtils::Context &context=QgsOgcUtils::Context())
Static method that creates geometry from GML.
A class to represent a 2D point.
bool isEmpty() const
Returns true if the geometry is empty.
Point geometry type, with support for z-dimension and m-values.
double inclination(const QgsPoint &other) const
Calculates Cartesian inclination between this point and other one (starting from zenith = 0 to nadir ...
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override
Checks validity of the geometry, and returns true if the geometry is valid.
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which corresponds to this point projected by a specified distance with specified ...
QgsRelationManager * relationManager
static QgsProject * instance()
Returns the QgsProject singleton instance.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
Quadrilateral geometry type.
static QgsQuadrilateral squareFromDiagonal(const QgsPoint &p1, const QgsPoint &p2)
Construct a QgsQuadrilateral as a square from a diagonal.
QgsPolygon * toPolygon(bool force2D=false) const
Returns the quadrilateral as a new polygon.
static QgsQuadrilateral rectangleFrom3Points(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &p3, ConstructionOption mode)
Construct a QgsQuadrilateral as a Rectangle from 3 points.
ConstructionOption
A quadrilateral can be constructed from 3 points where the second distance can be determined by the t...
@ Distance
Second distance is equal to the distance between 2nd and 3rd point.
@ Projected
Second distance is equal to the distance of the perpendicular projection of the 3rd point on the segm...
The Field class represents a Raster Attribute Table field, including its name, usage and type.
The RasterBandStats struct is a container for statistics about a single raster band.
double mean
The mean cell value for the band. NO_DATA values are excluded.
double stdDev
The standard deviation of the cell values.
double minimumValue
The minimum cell value in the raster band.
double sum
The sum of all cells in the band. NO_DATA values are excluded.
double maximumValue
The maximum cell value in the raster band.
double range
The range is the distance between min & max.
A rectangle specified with double values.
void grow(double delta)
Grows the rectangle in place by the specified amount.
Regular Polygon geometry type.
ConstructionOption
A regular polygon can be constructed inscribed in a circle or circumscribed about a circle.
@ CircumscribedCircle
Circumscribed about a circle (the radius is the distance from the center to the midpoints of the side...
@ InscribedCircle
Inscribed in a circle (the radius is the distance between the center and vertices)
QgsPolygon * toPolygon() const
Returns as a polygon.
QList< QgsRelation > relationsByName(const QString &name) const
Returns a list of relations with matching names.
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id.
Represents a relationship between two vector layers.
QgsVectorLayer * referencedLayer
QgsVectorLayer * referencingLayer
QString getRelatedFeaturesFilter(const QgsFeature &feature) const
Returns a filter expression which returns all the features on the referencing (child) layer which hav...
A spatial index for QgsFeature objects.
@ FlagStoreFeatureGeometries
Indicates that the spatial index should also store feature geometries. This requires more memory,...
QList< QgsFeatureId > nearestNeighbor(const QgsPointXY &point, int neighbors=1, double maxDistance=0) const
Returns nearest neighbors to a point.
QList< QgsFeatureId > intersects(const QgsRectangle &rectangle) const
Returns a list of features with a bounding box which intersects the specified rectangle.
static QString quotedIdentifier(const QString &identifier)
Returns a properly quoted version of identifier.
static QString quotedValue(const QVariant &value)
Returns a properly quoted and escaped version of value for use in SQL strings.
c++ helper class for defining QgsExpression functions.
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
void setIsStaticFunction(const std::function< bool(const QgsExpressionNodeFunction *, QgsExpression *, const QgsExpressionContext *) > &isStatic)
Set a function that will be called in the prepare step to determine if the function is static or not.
QStringList aliases() const override
Returns a list of possible aliases for the function.
void setPrepareFunction(const std::function< bool(const QgsExpressionNodeFunction *, QgsExpression *, const QgsExpressionContext *)> &prepareFunc)
Set a function that will be called in the prepare step to determine if the function is static or not.
void setUsesGeometryFunction(const std::function< bool(const QgsExpressionNodeFunction *node)> &usesGeometry)
Set a function that will be called when determining if the function requires feature geometry or not.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
void setIsStatic(bool isStatic)
Tag this function as either static or not static.
QgsStaticExpressionFunction(const QString &fnname, int params, FcnEval fcn, const QString &group, const QString &helpText=QString(), bool usesGeometry=false, const QSet< QString > &referencedColumns=QSet< QString >(), bool lazyEval=false, const QStringList &aliases=QStringList(), bool handlesNull=false)
Static function for evaluation against a QgsExpressionContext, using an unnamed list of parameter val...
QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const override
Returns a set of field names which are required for this function.
bool usesGeometry(const QgsExpressionNodeFunction *node) const override
Does this function use a geometry object.
Utility functions for working with strings.
static int hammingDistance(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the Hamming distance between two strings.
static QString soundex(const QString &string)
Returns the Soundex representation of a string.
static int levenshteinDistance(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the Levenshtein edit distance between two strings.
static QString longestCommonSubstring(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the longest common substring between two strings.
static QString wordWrap(const QString &string, int length, bool useMaxLineLength=true, const QString &customDelimiter=QString())
Automatically wraps a string by inserting new line characters at appropriate locations in the string.
const QgsColorRamp * colorRampRef(const QString &name) const
Returns a const pointer to a symbol (doesn't create new instance)
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Contains utility functions for working with symbols and symbol layers.
static QColor decodeColor(const QString &str)
static QString encodeColor(const QColor &color)
static bool runOnMainThread(const Func &func, QgsFeedback *feedback=nullptr)
Guarantees that func is executed on the main thread.
This class allows including a set of layers in a database-side transaction, provided the layer data p...
virtual bool executeSql(const QString &sql, QString &error, bool isDirty=false, const QString &name=QString())=0
Execute the sql string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
virtual QgsTransaction * transaction() const
Returns the transaction this data provider is included in, if any.
static bool validateAttribute(const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors, QgsFieldConstraints::ConstraintStrength strength=QgsFieldConstraints::ConstraintStrengthNotSet, QgsFieldConstraints::ConstraintOrigin origin=QgsFieldConstraints::ConstraintOriginNotSet)
Tests a feature attribute value to check whether it passes all constraints which are present on the c...
Represents a vector layer which manages a vector based data sets.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QVariant aggregate(Qgis::Aggregate aggregate, const QString &fieldOrExpression, const QgsAggregateCalculator::AggregateParameters ¶meters=QgsAggregateCalculator::AggregateParameters(), QgsExpressionContext *context=nullptr, bool *ok=nullptr, QgsFeatureIds *fids=nullptr, QgsFeedback *feedback=nullptr, QString *error=nullptr) const
Calculates an aggregated value from the layer's features.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QString displayExpression
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
QgsEditorWidgetSetup editorWidgetSetup(int index) const
Returns the editor widget setup for the field at the specified index.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
Q_INVOKABLE QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.
Handles the with_variable(name, value, node) expression function.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
QgsWithVariableExpressionFunction()
QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Evaluates the function, first evaluating all required arguments before passing them to the function's...
QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Returns result of evaluating the function.
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
static QString geometryDisplayString(Qgis::GeometryType type)
Returns a display string for a geometry type.
static bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
Unique pointer for sqlite3 databases, which automatically closes the database when the pointer goes o...
sqlite3_statement_unique_ptr prepare(const QString &sql, int &resultCode) const
Prepares a sql statement, returning the result.
QString errorMessage() const
Returns the most recent error message encountered by the database.
int open_v2(const QString &path, int flags, const char *zVfs)
Opens the database at the specified file path.
int exec(const QString &sql, QString &errorMessage) const
Executes the sql command in the database.
Unique pointer for sqlite3 prepared statements, which automatically finalizes the statement when the ...
int step()
Steps to the next record in the statement, returning the sqlite3 result code.
qlonglong columnAsInt64(int column) const
Gets column value from the current statement row as a long long integer (64 bits).
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
CORE_EXPORT QString build(const QVariantMap &map)
Build a hstore-formatted string from a QVariantMap.
CORE_EXPORT QVariantMap parse(const QString &string)
Returns a QVariantMap object containing the key and values from a hstore-formatted string.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QVector< QgsRingSequence > QgsCoordinateSequence
QVector< QgsPointSequence > QgsRingSequence
QVector< QgsPoint > QgsPointSequence
QList< QgsGradientStop > QgsGradientStopsList
List of gradient stops.
Q_DECLARE_METATYPE(QgsDatabaseQueryLogEntry)
Q_GLOBAL_STATIC(QReadWriteLock, sDefinitionCacheLock)
QList< QgsExpressionFunction * > ExpressionFunctionList
QVariant fcnRampColor(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
#define ENSURE_GEOM_TYPE(f, g, geomtype)
QVariant fcnRampColorObject(const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction *)
bool(QgsGeometry::* RelationFunction)(const QgsGeometry &geometry) const
#define ENSURE_NO_EVAL_ERROR
#define FEAT_FROM_CONTEXT(c, f)
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
QVector< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
QLineF segment(int index, QRectF rect, double radius)
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.