68#include <QMimeDatabase>
69#include <QProcessEnvironment>
70#include <QCryptographicHash>
71#include <QRegularExpression>
94 QVariantList argValues;
98 const QList< QgsExpressionNode * > argList = args->
list();
105 v = QVariant::fromValue( n );
109 v = n->eval( parent, context );
111 bool defaultParamIsNull = mParameterList.count() > arg && mParameterList.at( arg ).optional() && !mParameterList.at( arg ).defaultValue().isValid();
112 if ( QgsExpressionUtils::isNull( v ) && !defaultParamIsNull && !
handlesNull() )
115 argValues.append( v );
120 return func( argValues, context, parent, node );
131 return QStringList();
158 return mGroups.isEmpty() ? false : mGroups.contains( QStringLiteral(
"deprecated" ) );
163 return ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 );
175 const QString &group,
176 const QString &helpText,
180 const QStringList &aliases,
184 , mAliases( aliases )
185 , mUsesGeometry( false )
186 , mUsesGeometryFunc( usesGeometry )
187 , mReferencedColumnsFunc( referencedColumns )
199 if ( mUsesGeometryFunc )
200 return mUsesGeometryFunc( node );
202 return mUsesGeometry;
212 if ( mReferencedColumnsFunc )
213 return mReferencedColumnsFunc( node );
215 return mReferencedColumns;
221 return mIsStaticFunc( node, parent, context );
229 return mPrepareFunc( node, parent, context );
241 mIsStaticFunc =
nullptr;
247 mPrepareFunc = prepareFunc;
252 if ( node && node->
args() )
254 const QList< QgsExpressionNode * > argList = node->
args()->
list();
257 if ( !argNode->isStatic( parent, context ) )
267 double start = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
268 double stop = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
269 double step = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
271 if ( step == 0.0 || ( step > 0.0 && start > stop ) || ( step < 0.0 && start < stop ) )
278 double current = start + step;
279 while ( ( ( step > 0.0 && current <= stop ) || ( step < 0.0 && current >= stop ) ) && length <= 1000000 )
294 const QString name = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
296 if ( name == QLatin1String(
"feature" ) )
298 return context->
hasFeature() ? QVariant::fromValue( context->
feature() ) : QVariant();
300 else if ( name == QLatin1String(
"id" ) )
302 return context->
hasFeature() ? QVariant::fromValue( context->
feature().
id() ) : QVariant();
304 else if ( name == QLatin1String(
"geometry" ) )
320 QString templateString = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
329 QString expString = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
331 return expression.evaluate( context );
336 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
337 return QVariant( std::sqrt( x ) );
342 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
343 return QVariant( std::fabs( val ) );
348 double deg = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
349 return ( deg * M_PI ) / 180;
353 double rad = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
354 return ( 180 * rad ) / M_PI;
358 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
359 return QVariant( std::sin( x ) );
363 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
364 return QVariant( std::cos( x ) );
368 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
369 return QVariant( std::tan( x ) );
373 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
374 return QVariant( std::asin( x ) );
378 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
379 return QVariant( std::acos( x ) );
383 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
384 return QVariant( std::atan( x ) );
388 double y = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
389 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
390 return QVariant( std::atan2( y, x ) );
394 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
395 return QVariant( std::exp( x ) );
399 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
402 return QVariant( std::log( x ) );
406 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
409 return QVariant( log10( x ) );
413 double b = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
414 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
415 if ( x <= 0 || b <= 0 )
417 return QVariant( std::log( x ) / std::log( b ) );
421 double min = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
422 double max = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
426 std::random_device rd;
427 std::mt19937_64 generator( rd() );
429 if ( !QgsExpressionUtils::isNull( values.at( 2 ) ) )
432 if ( QgsExpressionUtils::isIntSafe( values.at( 2 ) ) )
435 seed = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
440 QString seedStr = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
441 std::hash<std::string> hasher;
442 seed = hasher( seedStr.toStdString() );
444 generator.seed( seed );
448 double f =
static_cast< double >( generator() ) /
static_cast< double >( std::mt19937_64::max() );
449 return QVariant( min + f * ( max - min ) );
453 qlonglong min = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
454 qlonglong max = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
458 std::random_device rd;
459 std::mt19937_64 generator( rd() );
461 if ( !QgsExpressionUtils::isNull( values.at( 2 ) ) )
464 if ( QgsExpressionUtils::isIntSafe( values.at( 2 ) ) )
467 seed = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
472 QString seedStr = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
473 std::hash<std::string> hasher;
474 seed = hasher( seedStr.toStdString() );
476 generator.seed( seed );
479 qint64 randomInteger = min + ( generator() % ( max - min + 1 ) );
480 if ( randomInteger > std::numeric_limits<int>::max() || randomInteger < -std::numeric_limits<int>::max() )
481 return QVariant( randomInteger );
484 return QVariant(
int( randomInteger ) );
489 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
490 double domainMin = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
491 double domainMax = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
492 double rangeMin = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
493 double rangeMax = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
495 if ( domainMin >= domainMax )
497 parent->
setEvalErrorString( QObject::tr(
"Domain max must be greater than domain min" ) );
502 if ( val >= domainMax )
506 else if ( val <= domainMin )
512 double m = ( rangeMax - rangeMin ) / ( domainMax - domainMin );
513 double c = rangeMin - ( domainMin * m );
516 return QVariant( m * val +
c );
521 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
522 double domainMin = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
523 double domainMax = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
524 double rangeMin = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
525 double rangeMax = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
526 double exponent = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
528 if ( domainMin >= domainMax )
530 parent->
setEvalErrorString( QObject::tr(
"Domain max must be greater than domain min" ) );
540 if ( val >= domainMax )
544 else if ( val <= domainMin )
550 return QVariant( ( ( rangeMax - rangeMin ) / std::pow( domainMax - domainMin, exponent ) ) * std::pow( val - domainMin, exponent ) + rangeMin );
555 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
556 double domainMin = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
557 double domainMax = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
558 double rangeMin = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
559 double rangeMax = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
560 double exponent = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
562 if ( domainMin >= domainMax )
564 parent->
setEvalErrorString( QObject::tr(
"Domain max must be greater than domain min" ) );
574 if ( val >= domainMax )
578 else if ( val <= domainMin )
584 double ratio = ( std::pow( exponent, val - domainMin ) - 1 ) / ( std::pow( exponent, domainMax - domainMin ) - 1 );
585 return QVariant( ( rangeMax - rangeMin ) * ratio + rangeMin );
591 double maxVal = std::numeric_limits<double>::quiet_NaN();
592 for (
const QVariant &val : values )
595 if ( std::isnan( maxVal ) )
599 else if ( !std::isnan( testVal ) )
601 maxVal = std::max( maxVal, testVal );
605 if ( !std::isnan( maxVal ) )
607 result = QVariant( maxVal );
615 double minVal = std::numeric_limits<double>::quiet_NaN();
616 for (
const QVariant &val : values )
619 if ( std::isnan( minVal ) )
623 else if ( !std::isnan( testVal ) )
625 minVal = std::min( minVal, testVal );
629 if ( !std::isnan( minVal ) )
631 result = QVariant( minVal );
643 QVariant value = node->
eval( parent, context );
648 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( value, context, parent );
652 parent->
setEvalErrorString( QObject::tr(
"Cannot find layer with name or ID '%1'" ).arg( value.toString() ) );
657 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
659 value = node->
eval( parent, context );
665 parent->
setEvalErrorString( QObject::tr(
"No such aggregate '%1'" ).arg( value.toString() ) );
670 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
672 QString subExpression = node->
dump();
676 if ( values.count() > 3 )
678 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
681 if ( !nl || nl->value().isValid() )
686 if ( values.count() > 4 )
688 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
690 value = node->
eval( parent, context );
697 if ( values.count() > 5 )
699 node = QgsExpressionUtils::getNode( values.at( 5 ), parent );
702 if ( !nl || nl->value().isValid() )
704 orderBy = node->
dump();
709 QString aggregateError;
717 const QSet< QString > filterVars = filterExp.referencedVariables();
718 const QSet< QString > subExpVars = subExp.referencedVariables();
719 QSet<QString> allVars = filterVars + subExpVars;
721 bool isStatic =
true;
722 if ( filterVars.contains( QStringLiteral(
"parent" ) )
723 || filterVars.contains( QString() )
724 || subExpVars.contains( QStringLiteral(
"parent" ) )
725 || subExpVars.contains( QString() ) )
731 for (
const QString &varName : allVars )
734 if ( scope && !scope->
isStatic( varName ) )
742 if ( isStatic && ! parameters.
orderBy.isEmpty() )
744 for (
const auto &orderByClause : std::as_const( parameters.orderBy ) )
747 if ( orderByExpression.referencedVariables().contains( QStringLiteral(
"parent" ) ) || orderByExpression.referencedVariables().contains( QString() ) )
758 const QString contextHash = context->
uniqueHash( ok, allVars );
761 cacheKey = QStringLiteral(
"aggfcn:%1:%2:%3:%4:%5:%6" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter,
762 orderBy, contextHash );
767 cacheKey = QStringLiteral(
"aggfcn:%1:%2:%3:%4:%5" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter, orderBy );
778 subContext.appendScope( subScope );
779 result = vl->aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &aggregateError );
781 if ( ok && !cacheKey.isEmpty() )
791 result = vl->aggregate( aggregate, subExpression, parameters,
nullptr, &ok,
nullptr,
nullptr, &aggregateError );
795 if ( !aggregateError.isEmpty() )
796 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, aggregateError ) );
798 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
809 parent->
setEvalErrorString( QObject::tr(
"Cannot use relation aggregate function in this context" ) );
817 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
821 parent->
setEvalErrorString( QObject::tr(
"Cannot use relation aggregate function in this context" ) );
830 QVariant value = node->
eval( parent, context );
832 QString relationId = value.toString();
839 if ( relations.isEmpty() || relations.at( 0 ).referencedLayer() != vl )
841 parent->
setEvalErrorString( QObject::tr(
"Cannot find relation with id '%1'" ).arg( relationId ) );
846 relation = relations.at( 0 );
853 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
855 value = node->
eval( parent, context );
861 parent->
setEvalErrorString( QObject::tr(
"No such aggregate '%1'" ).arg( value.toString() ) );
866 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
868 QString subExpression = node->
dump();
872 if ( values.count() > 3 )
874 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
876 value = node->
eval( parent, context );
883 if ( values.count() > 4 )
885 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
888 if ( !nl || nl->value().isValid() )
890 orderBy = node->
dump();
901 const QString cacheKey = QStringLiteral(
"relagg:%1%:%2:%3:%4:%5:%6" ).arg( relationId, vl->id(),
902 QString::number(
static_cast< int >( aggregate ) ),
915 result = childLayer->
aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &error );
919 if ( !error.isEmpty() )
920 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, error ) );
922 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
936 parent->
setEvalErrorString( QObject::tr(
"Cannot use aggregate function in this context" ) );
944 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
948 parent->
setEvalErrorString( QObject::tr(
"Cannot use aggregate function in this context" ) );
957 QString subExpression = node->
dump();
961 if ( values.count() > 1 )
963 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
966 if ( !nl || nl->value().isValid() )
967 groupBy = node->
dump();
971 if ( values.count() > 2 )
973 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
976 if ( !nl || nl->value().isValid() )
982 if ( orderByPos >= 0 && values.count() > orderByPos )
984 node = QgsExpressionUtils::getNode( values.at( orderByPos ), parent );
987 if ( !nl || nl->value().isValid() )
989 orderBy = node->
dump();
997 if ( !groupBy.isEmpty() )
1000 QVariant groupByValue = groupByExp.evaluate( context );
1001 QString groupByClause = QStringLiteral(
"%1 %2 %3" ).arg( groupBy,
1004 if ( !parameters.
filter.isEmpty() )
1005 parameters.
filter = QStringLiteral(
"(%1) AND (%2)" ).arg( parameters.
filter, groupByClause );
1007 parameters.
filter = groupByClause;
1013 bool isStatic =
true;
1014 const QSet<QString> refVars = filterExp.referencedVariables() + subExp.referencedVariables();
1015 for (
const QString &varName : refVars )
1018 if ( scope && !scope->
isStatic( varName ) )
1029 const QString contextHash = context->
uniqueHash( ok, refVars );
1032 cacheKey = QStringLiteral(
"agg:%1:%2:%3:%4:%5:%6" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter,
1033 orderBy, contextHash );
1038 cacheKey = QStringLiteral(
"agg:%1:%2:%3:%4:%5" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter, orderBy );
1050 subContext.appendScope( subScope );
1052 result = vl->aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &error );
1056 if ( !error.isEmpty() )
1057 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, error ) );
1059 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
1164 if ( values.count() > 3 )
1166 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
1168 QVariant value = node->
eval( parent, context );
1170 parameters.
delimiter = value.toString();
1181 if ( values.count() > 3 )
1183 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
1185 QVariant value = node->
eval( parent, context );
1187 parameters.
delimiter = value.toString();
1203 QVariant scale = context->
variable( QStringLiteral(
"map_scale" ) );
1208 const double v = scale.toDouble( &ok );
1216 double minValue = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1217 double testValue = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1218 double maxValue = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1221 if ( testValue <= minValue )
1223 return QVariant( minValue );
1225 else if ( testValue >= maxValue )
1227 return QVariant( maxValue );
1231 return QVariant( testValue );
1237 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1238 return QVariant( std::floor( x ) );
1243 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1244 return QVariant( std::ceil( x ) );
1249 const QVariant value = values.at( 0 );
1250 if ( QgsExpressionUtils::isNull( value.isValid() ) )
1252 return QVariant(
false );
1254 else if ( value.userType() == QMetaType::QString )
1257 return QVariant( !value.toString().isEmpty() );
1259 else if ( QgsExpressionUtils::isList( value ) )
1261 return !value.toList().isEmpty();
1263 return QVariant( value.toBool() );
1267 return QVariant( QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) );
1271 return QVariant( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) );
1275 return QVariant( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ) );
1280 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1281 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1282 if ( format.isEmpty() && !language.isEmpty() )
1284 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to DateTime when the language is specified" ) );
1285 return QVariant( QDateTime() );
1288 if ( format.isEmpty() && language.isEmpty() )
1289 return QVariant( QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent ) );
1291 QString datetimestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1292 QLocale locale = QLocale();
1293 if ( !language.isEmpty() )
1295 locale = QLocale( language );
1298 QDateTime datetime = locale.toDateTime( datetimestring, format );
1299 if ( !datetime.isValid() )
1301 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to DateTime" ).arg( datetimestring ) );
1302 datetime = QDateTime();
1304 return QVariant( datetime );
1309 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1310 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1311 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1313 const QDate date( year, month, day );
1314 if ( !date.isValid() )
1316 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1319 return QVariant( date );
1324 const int hours = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1325 const int minutes = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1326 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1328 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1329 if ( !time.isValid() )
1331 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1334 return QVariant( time );
1339 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1340 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1341 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1342 const int hours = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
1343 const int minutes = QgsExpressionUtils::getIntValue( values.at( 4 ), parent );
1344 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1346 const QDate date( year, month, day );
1347 if ( !date.isValid() )
1349 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1352 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1353 if ( !time.isValid() )
1355 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1358 return QVariant( QDateTime( date, time ) );
1363 const double years = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1364 const double months = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1365 const double weeks = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1366 const double days = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
1367 const double hours = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
1368 const double minutes = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1369 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
1371 return QVariant::fromValue(
QgsInterval( years, months, weeks, days, hours, minutes, seconds ) );
1376 for (
const QVariant &value : values )
1387 const QVariant val1 = values.at( 0 );
1388 const QVariant val2 = values.at( 1 );
1398 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1399 return QVariant( str.toLower() );
1403 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1404 return QVariant( str.toUpper() );
1408 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1409 QStringList elems = str.split(
' ' );
1410 for (
int i = 0; i < elems.size(); i++ )
1412 if ( elems[i].size() > 1 )
1413 elems[i] = elems[i].at( 0 ).toUpper() + elems[i].mid( 1 ).toLower();
1415 return QVariant( elems.join( QLatin1Char(
' ' ) ) );
1420 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1421 return QVariant( str.trimmed() );
1426 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1428 const QString characters = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1430 const QRegularExpression re( QStringLiteral(
"^([%1]*)" ).arg( QRegularExpression::escape( characters ) ) );
1431 str.replace( re, QString() );
1432 return QVariant( str );
1437 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1439 const QString characters = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1441 const QRegularExpression re( QStringLiteral(
"([%1]*)$" ).arg( QRegularExpression::escape( characters ) ) );
1442 str.replace( re, QString() );
1443 return QVariant( str );
1448 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1449 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1455 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1456 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1462 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1463 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1465 return ( dist < 0 ? QVariant() : QVariant(
QgsStringUtils::hammingDistance( string1, string2, true ) ) );
1470 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1476 QChar character = QChar( QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent ) );
1477 return QVariant( QString( character ) );
1482 QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1484 if ( value.isEmpty() )
1489 int res = value.at( 0 ).unicode();
1490 return QVariant( res );
1495 if ( values.length() == 2 || values.length() == 3 )
1497 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1498 qlonglong wrap = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1500 QString customdelimiter = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1513 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent,
true );
1517 return QVariant( geom.
length() );
1523 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1524 return QVariant( str.length() );
1529 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
1534 double totalLength = 0;
1537 if (
const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( *it ) )
1539 totalLength += line->length3D();
1543 std::unique_ptr< QgsLineString > segmentized( qgsgeometry_cast< const QgsCurve * >( *it )->curveToLine() );
1544 totalLength += segmentized->length3D();
1553 if ( values.count() == 2 && values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
1555 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1556 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
1557 QVector< QPair< QString, QString > > mapItems;
1559 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
1561 mapItems.append( qMakePair( it.key(), it.value().toString() ) );
1565 std::sort( mapItems.begin(),
1567 [](
const QPair< QString, QString > &pair1,
1568 const QPair< QString, QString > &pair2 )
1570 return ( pair1.first.length() > pair2.first.length() );
1573 for (
auto it = mapItems.constBegin(); it != mapItems.constEnd(); ++it )
1575 str = str.replace( it->first, it->second );
1578 return QVariant( str );
1580 else if ( values.count() == 3 )
1582 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1583 QVariantList before;
1585 bool isSingleReplacement =
false;
1587 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).userType() != QMetaType::Type::QStringList )
1589 before = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1593 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
1596 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
1598 after = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1599 isSingleReplacement =
true;
1603 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
1606 if ( !isSingleReplacement && before.length() != after.length() )
1608 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
1612 for (
int i = 0; i < before.length(); i++ )
1614 str = str.replace( before.at( i ).toString(), after.at( isSingleReplacement ? 0 : i ).toString() );
1617 return QVariant( str );
1621 parent->
setEvalErrorString( QObject::tr(
"Function replace requires 2 or 3 arguments" ) );
1628 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1629 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1630 QString after = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1632 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1633 if ( !re.isValid() )
1635 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1638 return QVariant( str.replace( re, after ) );
1643 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1644 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1646 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1647 if ( !re.isValid() )
1649 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1652 return QVariant( ( str.indexOf( re ) + 1 ) );
1657 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1658 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1659 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1661 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1662 if ( !re.isValid() )
1664 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1668 QRegularExpressionMatch matches = re.match( str );
1669 if ( matches.hasMatch() )
1672 QStringList list = matches.capturedTexts();
1675 for ( QStringList::const_iterator it = ++list.constBegin(); it != list.constEnd(); ++it )
1677 array += ( !( *it ).isEmpty() ) ? *it : empty;
1680 return QVariant( array );
1690 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1691 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1693 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1694 if ( !re.isValid() )
1696 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1701 QRegularExpressionMatch match = re.match( str );
1702 if ( match.hasMatch() )
1705 if ( match.lastCapturedIndex() > 0 )
1708 return QVariant( match.captured( 1 ) );
1713 return QVariant( match.captured( 0 ) );
1718 return QVariant(
"" );
1724 QString uuid = QUuid::createUuid().toString();
1725 if ( values.at( 0 ).toString().compare( QStringLiteral(
"WithoutBraces" ), Qt::CaseInsensitive ) == 0 )
1726 uuid = QUuid::createUuid().toString( QUuid::StringFormat::WithoutBraces );
1727 else if ( values.at( 0 ).toString().compare( QStringLiteral(
"Id128" ), Qt::CaseInsensitive ) == 0 )
1728 uuid = QUuid::createUuid().toString( QUuid::StringFormat::Id128 );
1734 if ( !values.at( 0 ).isValid() || !values.at( 1 ).isValid() )
1737 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1738 int from = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1741 if ( values.at( 2 ).isValid() )
1742 len = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
1748 from = str.size() + from;
1754 else if ( from > 0 )
1762 len = str.size() + len - from;
1769 return QVariant( str.mid( from, len ) );
1774 return QVariant( f.
id() );
1779 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1780 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
1781 bool foundLayer =
false;
1782 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, geom](
QgsMapLayer * mapLayer )
1784 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer * >( mapLayer );
1785 if ( !layer || !layer->dataProvider() )
1787 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1791 if ( bandNb < 1 || bandNb > layer->bandCount() )
1793 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster band number." ) );
1799 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid point geometry." ) );
1807 if ( multiPoint.count() == 1 )
1809 point = multiPoint[0];
1818 double value = layer->dataProvider()->sample( point, bandNb );
1819 return std::isnan( value ) ? QVariant() : value;
1825 parent->
setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1836 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1837 const double value = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1839 bool foundLayer =
false;
1840 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, value](
QgsMapLayer * mapLayer )-> QVariant
1842 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer *>( mapLayer );
1843 if ( !layer || !layer->dataProvider() )
1845 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1849 if ( bandNb < 1 || bandNb > layer->bandCount() )
1851 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster band number." ) );
1855 if ( std::isnan( value ) )
1857 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster value." ) );
1861 if ( ! layer->dataProvider()->attributeTable( bandNb ) )
1866 const QVariantList data = layer->dataProvider()->attributeTable( bandNb )->row( value );
1867 if ( data.isEmpty() )
1873 const QList<QgsRasterAttributeTable::Field> fields { layer->dataProvider()->attributeTable( bandNb )->fields() };
1874 for (
int idx = 0; idx < static_cast<int>( fields.count( ) ) && idx < static_cast<int>( data.count() ); ++idx )
1877 if ( field.isColor() || field.isRamp() )
1881 result.insert( fields.at( idx ).name, data.at( idx ) );
1889 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1910 if ( values.size() == 1 )
1912 attr = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1915 else if ( values.size() == 2 )
1917 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
1918 attr = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1922 parent->
setEvalErrorString( QObject::tr(
"Function `attribute` requires one or two parameters. %n given.",
nullptr, values.length() ) );
1931 QString table { R
"html(
1934 <tr><th>%1</th></tr>
1937 <tr><td>%2</td></tr>
1941 if ( values.size() == 1 )
1943 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1947 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_table` requires one parameter. %n given.",
nullptr, values.length() ) );
1951 if ( dict.isEmpty() )
1956 QStringList headers;
1959 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
1961 headers.push_back( it.key().toHtmlEscaped() );
1962 cells.push_back( it.value().toString( ).toHtmlEscaped() );
1965 return table.arg( headers.join( QLatin1String(
"</th><th>" ) ), cells.join( QLatin1String(
"</td><td>" ) ) );
1970 QString table { R
"html(
1975 if ( values.size() == 1 )
1977 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1981 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_dl` requires one parameter. %n given.",
nullptr, values.length() ) );
1985 if ( dict.isEmpty() )
1992 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
1994 rows.append( QStringLiteral(
"<dt>%1</dt><dd>%2</dd>" ).arg( it.key().toHtmlEscaped(), it.value().toString().toHtmlEscaped() ) );
1997 return table.arg( rows );
2005 layer = context->
variable( QStringLiteral(
"layer" ) );
2010 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
2012 layer = node->
eval( parent, context );
2023 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2027 const QString strength = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).toLower();
2028 if ( strength == QLatin1String(
"hard" ) )
2032 else if ( strength == QLatin1String(
"soft" ) )
2037 bool foundLayer =
false;
2038 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
2040 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2043 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2049 for (
int i = 0; i < fields.
size(); i++ )
2064 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2076 layer = context->
variable( QStringLiteral(
"layer" ) );
2081 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
2083 layer = node->
eval( parent, context );
2094 feature = QgsExpressionUtils::getFeature( values.at( 2 ), parent );
2098 const QString strength = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).toLower();
2099 if ( strength == QLatin1String(
"hard" ) )
2103 else if ( strength == QLatin1String(
"soft" ) )
2108 const QString attributeName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2110 bool foundLayer =
false;
2111 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, attributeName, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
2113 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2120 if ( fieldIndex == -1 )
2122 parent->
setEvalErrorString( QObject::tr(
"The attribute name did not match any field for the given feature" ) );
2133 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2149 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2154 for (
int i = 0; i < fields.
count(); ++i )
2168 if ( values.isEmpty() )
2171 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2173 else if ( values.size() == 1 )
2175 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2176 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2178 else if ( values.size() == 2 )
2180 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2181 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2185 parent->
setEvalErrorString( QObject::tr(
"Function `represent_attributes` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2192 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: layer could not be resolved." ) );
2198 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: feature could not be resolved." ) );
2204 for (
int fieldIndex = 0; fieldIndex < fields.
count(); ++fieldIndex )
2206 const QString fieldName { fields.
at( fieldIndex ).
name() };
2207 const QVariant attributeVal = feature.
attribute( fieldIndex );
2208 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer->
id(), fieldName, attributeVal.toString() );
2211 result.insert( fieldName, context->
cachedValue( cacheValueKey ) );
2220 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer->
id(), fieldName );
2232 QString value( fieldFormatter->
representValue( layer, fieldIndex, setup.
config(), cache, attributeVal ) );
2234 result.insert( fields.
at( fieldIndex ).
name(), value );
2250 bool evaluate =
true;
2254 if ( values.isEmpty() )
2257 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2259 else if ( values.size() == 1 )
2261 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2262 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2264 else if ( values.size() == 2 )
2266 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2267 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2269 else if ( values.size() == 3 )
2271 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2272 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2273 evaluate = values.value( 2 ).toBool();
2279 parent->
setEvalErrorString( QObject::tr(
"Function `maptip` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2283 parent->
setEvalErrorString( QObject::tr(
"Function `display` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2315 subContext.setFeature( feature );
2324 exp.prepare( &subContext );
2325 return exp.evaluate( &subContext ).toString();
2331 return fcnCoreFeatureMaptipDisplay( values, context, parent,
false );
2336 return fcnCoreFeatureMaptipDisplay( values, context, parent,
true );
2343 if ( values.isEmpty() )
2346 layer = context->
variable( QStringLiteral(
"layer" ) );
2348 else if ( values.size() == 1 )
2350 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2351 layer = context->
variable( QStringLiteral(
"layer" ) );
2353 else if ( values.size() == 2 )
2355 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2356 layer = values.at( 0 );
2360 parent->
setEvalErrorString( QObject::tr(
"Function `is_selected` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2364 bool foundLayer =
false;
2365 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [feature](
QgsMapLayer * mapLayer ) -> QVariant
2367 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2368 if ( !layer || !feature.
isValid() )
2385 if ( values.isEmpty() )
2386 layer = context->
variable( QStringLiteral(
"layer" ) );
2387 else if ( values.count() == 1 )
2388 layer = values.at( 0 );
2391 parent->
setEvalErrorString( QObject::tr(
"Function `num_selected` requires no more than one parameter. %n given.",
nullptr, values.length() ) );
2395 bool foundLayer =
false;
2396 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [](
QgsMapLayer * mapLayer ) -> QVariant
2398 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2414 static QMap<QString, qlonglong> counterCache;
2415 QVariant functionResult;
2417 auto fetchAndIncrementFunc = [ values, parent, &functionResult ](
QgsMapLayer * mapLayer,
const QString & databaseArgument )
2421 const QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( mapLayer );
2426 database = decodedUri.value( QStringLiteral(
"path" ) ).toString();
2427 if ( database.isEmpty() )
2429 parent->
setEvalErrorString( QObject::tr(
"Could not extract file path from layer `%1`." ).arg( layer->
name() ) );
2434 database = databaseArgument;
2437 const QString table = values.at( 1 ).toString();
2438 const QString idColumn = values.at( 2 ).toString();
2439 const QString filterAttribute = values.at( 3 ).toString();
2440 const QVariant filterValue = values.at( 4 ).toString();
2441 const QVariantMap defaultValues = values.at( 5 ).toMap();
2447 if ( sqliteDb.
open_v2( database, SQLITE_OPEN_READWRITE,
nullptr ) != SQLITE_OK )
2450 functionResult = QVariant();
2454 QString errorMessage;
2455 QString currentValSql;
2457 qlonglong nextId = 0;
2458 bool cachedMode =
false;
2459 bool valueRetrieved =
false;
2461 QString cacheString = QStringLiteral(
"%1:%2:%3:%4:%5" ).arg( database, table, idColumn, filterAttribute, filterValue.toString() );
2468 auto cachedCounter = counterCache.find( cacheString );
2470 if ( cachedCounter != counterCache.end() )
2472 qlonglong &cachedValue = cachedCounter.value();
2473 nextId = cachedValue;
2475 cachedValue = nextId;
2476 valueRetrieved =
true;
2481 if ( !cachedMode || !valueRetrieved )
2483 int result = SQLITE_ERROR;
2486 if ( !filterAttribute.isNull() )
2491 sqliteStatement = sqliteDb.
prepare( currentValSql, result );
2493 if ( result == SQLITE_OK )
2496 if ( sqliteStatement.
step() == SQLITE_ROW )
2502 if ( cachedMode && result == SQLITE_OK )
2504 counterCache.insert( cacheString, nextId );
2508 counterCache.remove( cacheString );
2511 valueRetrieved =
true;
2515 if ( valueRetrieved )
2524 if ( !filterAttribute.isNull() )
2530 for ( QVariantMap::const_iterator iter = defaultValues.constBegin(); iter != defaultValues.constEnd(); ++iter )
2533 vals << iter.value().toString();
2536 upsertSql += QLatin1String(
" (" ) + cols.join(
',' ) +
')';
2537 upsertSql += QLatin1String(
" VALUES " );
2538 upsertSql +=
'(' + vals.join(
',' ) +
')';
2540 int result = SQLITE_ERROR;
2544 if ( transaction->
executeSql( upsertSql, errorMessage ) )
2551 result = sqliteDb.
exec( upsertSql, errorMessage );
2553 if ( result == SQLITE_OK )
2555 functionResult = QVariant( nextId );
2560 parent->
setEvalErrorString( QStringLiteral(
"Could not increment value: SQLite error: \"%1\" (%2)." ).arg( errorMessage, QString::number( result ) ) );
2561 functionResult = QVariant();
2566 functionResult = QVariant();
2569 bool foundLayer =
false;
2570 QgsExpressionUtils::executeLambdaForMapLayer( values.at( 0 ), context, parent, [&fetchAndIncrementFunc](
QgsMapLayer * layer )
2572 fetchAndIncrementFunc( layer, QString() );
2576 const QString databasePath = values.at( 0 ).toString();
2579 fetchAndIncrementFunc(
nullptr, databasePath );
2583 return functionResult;
2596 QString definition = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2601 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to cordinate reference system" ).arg( definition ) );
2604 return QVariant::fromValue(
crs );
2610 for (
const QVariant &value : values )
2613 concat += QgsExpressionUtils::getStringValue( value, parent );
2620 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2621 return string.indexOf( QgsExpressionUtils::getStringValue( values.at( 1 ), parent ) ) + 1;
2626 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2627 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2628 return string.right( pos );
2633 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2634 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2635 return string.left( pos );
2640 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2641 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2642 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2643 return string.leftJustified( length, fill.at( 0 ),
true );
2648 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2649 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2650 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2651 return string.rightJustified( length, fill.at( 0 ),
true );
2656 if ( values.size() < 1 )
2658 parent->
setEvalErrorString( QObject::tr(
"Function format requires at least 1 argument" ) );
2662 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2663 for (
int n = 1; n < values.length(); n++ )
2665 string =
string.arg( QgsExpressionUtils::getStringValue( values.at( n ), parent ) );
2673 return QVariant( QDateTime::currentDateTime() );
2678 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2679 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2680 if ( format.isEmpty() && !language.isEmpty() )
2682 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Date when the language is specified" ) );
2683 return QVariant( QDate() );
2686 if ( format.isEmpty() && language.isEmpty() )
2687 return QVariant( QgsExpressionUtils::getDateValue( values.at( 0 ), parent ) );
2689 QString datestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2690 QLocale locale = QLocale();
2691 if ( !language.isEmpty() )
2693 locale = QLocale( language );
2696 QDate date = locale.toDate( datestring, format );
2697 if ( !date.isValid() )
2699 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Date" ).arg( datestring ) );
2702 return QVariant( date );
2707 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2708 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2709 if ( format.isEmpty() && !language.isEmpty() )
2711 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Time when the language is specified" ) );
2712 return QVariant( QTime() );
2715 if ( format.isEmpty() && language.isEmpty() )
2716 return QVariant( QgsExpressionUtils::getTimeValue( values.at( 0 ), parent ) );
2718 QString timestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2719 QLocale locale = QLocale();
2720 if ( !language.isEmpty() )
2722 locale = QLocale( language );
2725 QTime time = locale.toTime( timestring, format );
2726 if ( !time.isValid() )
2728 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Time" ).arg( timestring ) );
2731 return QVariant( time );
2736 return QVariant::fromValue( QgsExpressionUtils::getInterval( values.at( 0 ), parent ) );
2745 double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
2746 QString axis = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2747 int precision = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
2749 QString formatString;
2750 if ( values.count() > 3 )
2751 formatString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
2754 if ( formatString.compare( QLatin1String(
"suffix" ), Qt::CaseInsensitive ) == 0 )
2758 else if ( formatString.compare( QLatin1String(
"aligned" ), Qt::CaseInsensitive ) == 0 )
2762 else if ( ! formatString.isEmpty() )
2764 parent->
setEvalErrorString( QObject::tr(
"Invalid formatting parameter: '%1'. It must be empty, or 'suffix' or 'aligned'." ).arg( formatString ) );
2768 if ( axis.compare( QLatin1String(
"x" ), Qt::CaseInsensitive ) == 0 )
2772 else if ( axis.compare( QLatin1String(
"y" ), Qt::CaseInsensitive ) == 0 )
2778 parent->
setEvalErrorString( QObject::tr(
"Invalid axis name: '%1'. It must be either 'x' or 'y'." ).arg( axis ) );
2786 return floatToDegreeFormat( format, values, context, parent, node );
2793 value = QgsCoordinateUtils::dmsToDecimal( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), &ok );
2795 return ok ? QVariant( value ) : QVariant();
2801 return floatToDegreeFormat( format, values, context, parent, node );
2806 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2807 QDateTime d2 = QgsExpressionUtils::getDateTimeValue( values.at( 1 ), parent );
2808 qint64 seconds = d2.secsTo( d1 );
2809 return QVariant::fromValue(
QgsInterval( seconds ) );
2814 if ( !values.at( 0 ).canConvert<QDate>() )
2817 QDate date = QgsExpressionUtils::getDateValue( values.at( 0 ), parent );
2818 if ( !date.isValid() )
2823 return date.dayOfWeek() % 7;
2828 QVariant value = values.at( 0 );
2829 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2832 return QVariant( inter.
days() );
2836 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2837 return QVariant( d1.date().day() );
2843 QVariant value = values.at( 0 );
2844 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2847 return QVariant( inter.
years() );
2851 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2852 return QVariant( d1.date().year() );
2858 QVariant value = values.at( 0 );
2859 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2862 return QVariant( inter.
months() );
2866 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2867 return QVariant( d1.date().month() );
2873 QVariant value = values.at( 0 );
2874 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2877 return QVariant( inter.
weeks() );
2881 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2882 return QVariant( d1.date().weekNumber() );
2888 QVariant value = values.at( 0 );
2889 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2892 return QVariant( inter.
hours() );
2896 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2897 return QVariant( t1.hour() );
2903 QVariant value = values.at( 0 );
2904 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2907 return QVariant( inter.
minutes() );
2911 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2912 return QVariant( t1.minute() );
2918 QVariant value = values.at( 0 );
2919 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2922 return QVariant( inter.
seconds() );
2926 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2927 return QVariant( t1.second() );
2933 QDateTime dt = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2936 return QVariant( dt.toMSecsSinceEpoch() );
2946 long long millisecs_since_epoch = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
2948 return QVariant( QDateTime::fromMSecsSinceEpoch( millisecs_since_epoch ) );
2953 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2956 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif" ) ) );
2959 QString tag = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2965 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2968 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif_geotag" ) ) );
2975#define ENSURE_GEOM_TYPE(f, g, geomtype) \
2976 if ( !(f).hasGeometry() ) \
2977 return QVariant(); \
2978 QgsGeometry g = (f).geometry(); \
2979 if ( (g).type() != (geomtype) ) \
2986 if ( g.isMultipart() )
2988 return g.asMultiPoint().at( 0 ).x();
2992 return g.asPoint().x();
3000 if ( g.isMultipart() )
3002 return g.asMultiPoint().at( 0 ).y();
3006 return g.asPoint().y();
3020 if ( g.isEmpty() || !abGeom->
is3D() )
3025 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( g.constGet() );
3031 if (
const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( g.constGet() ) )
3033 if ( collection->numGeometries() > 0 )
3035 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3046 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3052 return QVariant( isValid );
3057 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3061 const QString methodString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).trimmed();
3062#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
3067 if ( methodString.compare( QLatin1String(
"linework" ), Qt::CaseInsensitive ) == 0 )
3069 else if ( methodString.compare( QLatin1String(
"structure" ), Qt::CaseInsensitive ) == 0 )
3072 const bool keepCollapsed = values.value( 2 ).toBool();
3077 valid = geom.
makeValid( method, keepCollapsed );
3081 parent->
setEvalErrorString( QObject::tr(
"The make_valid parameters require a newer GEOS library version" ) );
3085 return QVariant::fromValue( valid );
3090 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3096 for (
int i = 0; i < multiGeom.size(); ++i )
3098 array += QVariant::fromValue( multiGeom.at( i ) );
3106 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3118 QVariant result( centroid.asPoint().
x() );
3124 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3136 QVariant result( centroid.asPoint().
y() );
3142 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3152 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3160 if ( collection->numGeometries() == 1 )
3162 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3173 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3183 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3191 if ( collection->numGeometries() == 1 )
3193 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3204 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3209 int idx = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
3236 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3253 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3270 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3275 bool ignoreClosing =
false;
3276 if ( values.length() > 1 )
3278 ignoreClosing = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3288 bool skipLast =
false;
3289 if ( ignoreClosing && ring.count() > 2 && ring.first() == ring.last() )
3294 for (
int i = 0; i < ( skipLast ? ring.count() - 1 : ring.count() ); ++ i )
3306 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3317 for (
int i = 0; i < line->numPoints() - 1; ++i )
3321 << line->pointN( i )
3322 << line->pointN( i + 1 ) );
3333 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3343 if ( collection->numGeometries() == 1 )
3345 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->geometryN( 0 ) );
3350 if ( !curvePolygon )
3354 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3360 QVariant result = curve ? QVariant::fromValue(
QgsGeometry( curve ) ) : QVariant();
3366 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3376 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3382 QVariant result = part ? QVariant::fromValue(
QgsGeometry( part ) ) : QVariant();
3388 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3397 return QVariant::fromValue(
QgsGeometry( boundary ) );
3402 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3411 return QVariant::fromValue( merged );
3416 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3420 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3425 if ( sharedPaths.
isNull() )
3428 return QVariant::fromValue( sharedPaths );
3434 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3439 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3442 if ( simplified.
isNull() )
3450 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3455 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3460 if ( simplified.
isNull() )
3468 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3473 int iterations = std::min( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), 10 );
3474 double offset = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0.0, 0.5 );
3475 double minLength = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3476 double maxAngle = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ), 0.0, 180.0 );
3478 QgsGeometry smoothed = geom.
smooth(
static_cast<unsigned int>( iterations ), offset, minLength, maxAngle );
3487 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3492 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3493 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3494 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3505 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3510 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3511 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3512 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3513 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3514 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3517 minAmplitude, maxAmplitude, seed );
3526 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3531 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3532 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3533 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3544 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3549 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3550 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3551 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3552 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3553 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3556 minAmplitude, maxAmplitude, seed );
3565 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3570 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3571 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3572 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3583 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3588 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3589 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3590 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3591 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3592 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3595 minAmplitude, maxAmplitude, seed );
3604 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3609 const QVariantList pattern = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
3610 QVector< double > dashPattern;
3611 dashPattern.reserve( pattern.size() );
3612 for (
const QVariant &value : std::as_const( pattern ) )
3615 double v = value.toDouble( &ok );
3622 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must be an array of numbers" ) );
3627 if ( dashPattern.size() % 2 != 0 )
3629 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must contain an even number of elements" ) );
3633 const QString startRuleString = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).trimmed();
3635 if ( startRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3637 else if ( startRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3639 else if ( startRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3641 else if ( startRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3643 else if ( startRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3647 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( startRuleString ) );
3651 const QString endRuleString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
3653 if ( endRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3655 else if ( endRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3657 else if ( endRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3659 else if ( endRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3661 else if ( endRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3665 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( endRuleString ) );
3669 const QString adjustString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
3671 if ( adjustString.compare( QLatin1String(
"both" ), Qt::CaseInsensitive ) == 0 )
3673 else if ( adjustString.compare( QLatin1String(
"dash" ), Qt::CaseInsensitive ) == 0 )
3675 else if ( adjustString.compare( QLatin1String(
"gap" ), Qt::CaseInsensitive ) == 0 )
3679 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern size adjustment" ).arg( adjustString ) );
3683 const double patternOffset = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
3694 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3699 const long long count = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3701 if ( densified.
isNull() )
3709 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3714 const double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3716 if ( densified.
isNull() )
3725 if ( values.size() == 1 && QgsExpressionUtils::isList( values.at( 0 ) ) )
3727 list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
3734 QVector< QgsGeometry > parts;
3735 parts.reserve( list.size() );
3736 for (
const QVariant &value : std::as_const( list ) )
3738 QgsGeometry part = QgsExpressionUtils::getGeometry( value, parent );
3749 if ( values.count() < 2 || values.count() > 4 )
3751 parent->
setEvalErrorString( QObject::tr(
"Function make_point requires 2-4 arguments" ) );
3755 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3756 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3757 double z = values.count() >= 3 ? QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) : 0.0;
3758 double m = values.count() >= 4 ? QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) : 0.0;
3759 switch ( values.count() )
3773 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3774 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3775 double m = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3781 if ( values.empty() )
3786 QVector<QgsPoint> points;
3787 points.reserve( values.count() );
3789 auto addPoint = [&points](
const QgsGeometry & geom )
3797 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3804 for (
const QVariant &value : values )
3806 if ( value.userType() == QMetaType::Type::QVariantList )
3808 const QVariantList list = value.toList();
3809 for (
const QVariant &v : list )
3811 addPoint( QgsExpressionUtils::getGeometry( v, parent ) );
3816 addPoint( QgsExpressionUtils::getGeometry( value, parent ) );
3820 if ( points.count() < 2 )
3828 if ( values.count() < 1 )
3830 parent->
setEvalErrorString( QObject::tr(
"Function make_polygon requires an argument" ) );
3834 QgsGeometry outerRing = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3842 auto polygon = std::make_unique< QgsPolygon >();
3844 const QgsCurve *exteriorRing = qgsgeometry_cast< QgsCurve * >( outerRing.
constGet() );
3851 exteriorRing = qgsgeometry_cast< QgsCurve * >( collection->
geometryN( 0 ) );
3856 if ( !exteriorRing )
3859 polygon->setExteriorRing( exteriorRing->
segmentize() );
3862 for (
int i = 1; i < values.count(); ++i )
3864 QgsGeometry ringGeom = QgsExpressionUtils::getGeometry( values.at( i ), parent );
3871 const QgsCurve *ring = qgsgeometry_cast< QgsCurve * >( ringGeom.
constGet() );
3878 ring = qgsgeometry_cast< QgsCurve * >( collection->
geometryN( 0 ) );
3886 polygon->addInteriorRing( ring->
segmentize() );
3889 return QVariant::fromValue(
QgsGeometry( std::move( polygon ) ) );
3894 auto tr = std::make_unique<QgsTriangle>();
3895 auto lineString = std::make_unique<QgsLineString>();
3896 lineString->clear();
3898 for (
const QVariant &value : values )
3900 QgsGeometry geom = QgsExpressionUtils::getGeometry( value, parent );
3907 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3914 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3922 lineString->addVertex( *point );
3925 tr->setExteriorRing( lineString.release() );
3927 return QVariant::fromValue(
QgsGeometry( tr.release() ) );
3932 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3939 double radius = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3940 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
3947 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3954 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3962 return QVariant::fromValue(
QgsGeometry( circ.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
3967 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3974 double majorAxis = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3975 double minorAxis = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3976 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3977 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 4 ), parent );
3983 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3990 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3997 QgsEllipse elp( *point, majorAxis, minorAxis, azimuth );
3998 return QVariant::fromValue(
QgsGeometry( elp.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
4004 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4011 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4018 unsigned int nbEdges =
static_cast<unsigned int>( QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) );
4021 parent->
setEvalErrorString( QObject::tr(
"Number of edges/sides must be greater than 2" ) );
4028 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (inscribed) or 1 (circumscribed)" ) );
4032 const QgsPoint *center = qgsgeometry_cast< const QgsPoint * >( pt1.
constGet() );
4039 center = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4046 const QgsPoint *corner = qgsgeometry_cast< const QgsPoint * >( pt2.
constGet() );
4053 corner = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4068 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4074 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4080 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
4081 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
4089 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4095 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4101 QgsGeometry pt3 = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
4110 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (distance) or 1 (projected)" ) );
4113 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
4114 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
4115 const QgsPoint *point3 = qgsgeometry_cast< const QgsPoint *>( pt3.
constGet() );
4134 return QVariant::fromValue( geom.
vertexAt( idx ) );
4142 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4144 const QVariant v = pointAt( geom, idx, parent );
4147 return QVariant( v.value<
QgsPoint>().
x() );
4153 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4155 return fcnOldXat( values, f, parent, node );
4157 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4159 return fcnOldXat( QVariantList() << values[1], f, parent, node );
4162 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4168 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4170 const QVariant v = pointAt( geom, vertexNumber, parent );
4172 return QVariant( v.value<
QgsPoint>().
x() );
4182 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4184 const QVariant v = pointAt( geom, idx, parent );
4187 return QVariant( v.value<
QgsPoint>().
y() );
4193 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4195 return fcnOldYat( values, f, parent, node );
4197 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4199 return fcnOldYat( QVariantList() << values[1], f, parent, node );
4202 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4208 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4210 const QVariant v = pointAt( geom, vertexNumber, parent );
4212 return QVariant( v.value<
QgsPoint>().
y() );
4219 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4225 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4227 const QVariant v = pointAt( geom, vertexNumber, parent );
4229 return QVariant( v.value<
QgsPoint>().
z() );
4236 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4242 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4244 const QVariant v = pointAt( geom, vertexNumber, parent );
4246 return QVariant( v.value<
QgsPoint>().
m() );
4265 return QVariant::fromValue( geom );
4273 QString wkt = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4275 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4281 const QByteArray wkb = QgsExpressionUtils::getBinaryValue( values.at( 0 ), parent );
4287 return !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4292 QString gml = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4299 ogcContext.
layer = mapLayerPtr.data();
4300 ogcContext.
transformContext = context->
variable( QStringLiteral(
"_project_transform_context" ) ).value<QgsCoordinateTransformContext>();
4304 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4319 return QVariant( area );
4323 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating area" ) );
4335 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4340 return QVariant( geom.
area() );
4354 return QVariant( len );
4358 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating length" ) );
4379 return QVariant( len );
4383 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating perimeter" ) );
4389 return f.
geometry().
isNull() ? QVariant( 0 ) : QVariant( f.geometry().constGet()->perimeter() );
4395 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4401 return QVariant( geom.
length() );
4406 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4407 return QVariant( geom.
isNull() ? 0 : geom.constGet()->nCoordinates() );
4412 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4421 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4430 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4445 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon *>( collection->
geometryN( i ) );
4446 if ( !curvePolygon )
4449 return QVariant( curvePolygon->
isEmpty() ? 0 : curvePolygon->numInteriorRings() );
4458 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4465 return QVariant( curvePolygon->
ringCount() );
4467 bool foundPoly =
false;
4475 curvePolygon = qgsgeometry_cast< QgsCurvePolygon *>( collection->
geometryN( i ) );
4476 if ( !curvePolygon )
4487 return QVariant( ringCount );
4492 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4494 QVariant result = !geomBounds.
isNull() ? QVariant::fromValue( geomBounds ) : QVariant();
4500 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4506 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4512 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4521 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4527 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4533 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4539 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4545 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4553 double max = std::numeric_limits< double >::lowest();
4557 double z = ( *it ).z();
4563 if ( max == std::numeric_limits< double >::lowest() )
4566 return QVariant( max );
4571 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4579 double min = std::numeric_limits< double >::max();
4583 double z = ( *it ).z();
4589 if ( min == std::numeric_limits< double >::max() )
4592 return QVariant( min );
4597 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4605 double min = std::numeric_limits< double >::max();
4609 double m = ( *it ).m();
4615 if ( min == std::numeric_limits< double >::max() )
4618 return QVariant( min );
4623 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4631 double max = std::numeric_limits< double >::lowest();
4635 double m = ( *it ).m();
4641 if ( max == std::numeric_limits< double >::lowest() )
4644 return QVariant( max );
4649 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4650 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom.
constGet() );
4653 parent->
setEvalErrorString( QObject::tr(
"Function `sinuosity` requires a line geometry." ) );
4662 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4666 parent->
setEvalErrorString( QObject::tr(
"Function `straight_distance_2d` requires a line geometry or a multi line geometry with a single part." ) );
4675 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4680 parent->
setEvalErrorString( QObject::tr(
"Function `roundness` requires a polygon geometry or a multi polygon geometry with a single part." ) );
4691 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4695 std::unique_ptr< QgsAbstractGeometry > flipped( geom.
constGet()->
clone() );
4697 return QVariant::fromValue(
QgsGeometry( std::move( flipped ) ) );
4702 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4706 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( fGeom.
constGet() );
4713 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
4721 return QVariant::fromValue( curve->
isClosed() );
4726 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4739 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4740 closedLine->close();
4742 result = QVariant::fromValue(
QgsGeometry( std::move( closedLine ) ) );
4752 if (
const QgsLineString *line = qgsgeometry_cast<const QgsLineString * >( collection->
geometryN( i ) ) )
4754 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4755 closedLine->close();
4757 closed->addGeometry( closedLine.release() );
4760 result = QVariant::fromValue(
QgsGeometry( std::move( closed ) ) );
4768 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4772 return QVariant::fromValue( fGeom.
isEmpty() );
4778 return QVariant::fromValue(
true );
4780 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4781 return QVariant::fromValue( fGeom.
isNull() || fGeom.
isEmpty() );
4786 if ( values.length() < 2 || values.length() > 3 )
4789 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4790 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4797 if ( values.length() == 2 )
4800 QString result = engine->relate( sGeom.
constGet() );
4801 return QVariant::fromValue( result );
4806 QString pattern = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
4807 bool result = engine->relatePattern( sGeom.
constGet(), pattern );
4808 return QVariant::fromValue( result );
4814 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4815 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4820 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4821 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4822 return fGeom.
disjoint( sGeom ) ? TVL_True : TVL_False;
4826 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4827 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4828 return fGeom.
intersects( sGeom ) ? TVL_True : TVL_False;
4832 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4833 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4834 return fGeom.
touches( sGeom ) ? TVL_True : TVL_False;
4838 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4839 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4840 return fGeom.
crosses( sGeom ) ? TVL_True : TVL_False;
4844 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4845 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4846 return fGeom.
contains( sGeom ) ? TVL_True : TVL_False;
4850 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4851 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4852 return fGeom.
overlaps( sGeom ) ? TVL_True : TVL_False;
4856 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4857 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4858 return fGeom.
within( sGeom ) ? TVL_True : TVL_False;
4863 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4864 const double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4865 const int seg = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4866 const QString endCapString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
4867 const QString joinString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
4868 const double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
4871 if ( endCapString.compare( QLatin1String(
"flat" ), Qt::CaseInsensitive ) == 0 )
4873 else if ( endCapString.compare( QLatin1String(
"square" ), Qt::CaseInsensitive ) == 0 )
4877 if ( joinString.compare( QLatin1String(
"miter" ), Qt::CaseInsensitive ) == 0 )
4879 else if ( joinString.compare( QLatin1String(
"bevel" ), Qt::CaseInsensitive ) == 0 )
4883 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4889 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4891 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4896 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4898 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4903 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4905 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4910 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4911 const QgsPoint *pt = qgsgeometry_cast<const QgsPoint *>( fGeom.
constGet() );
4918 pt = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4925 parent->
setEvalErrorString( QObject::tr(
"Function `wedge_buffer` requires a point value for the center." ) );
4929 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4930 double width = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4931 double outerRadius = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4932 double innerRadius = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
4935 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4941 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4944 parent->
setEvalErrorString( QObject::tr(
"Function `tapered_buffer` requires a line geometry." ) );
4948 double startWidth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4949 double endWidth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4950 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) );
4953 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4959 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4962 parent->
setEvalErrorString( QObject::tr(
"Function `buffer_by_m` requires a line geometry." ) );
4966 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) );
4969 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4975 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4976 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4977 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4978 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4979 if ( joinInt < 1 || joinInt > 3 )
4983 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4986 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4992 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4993 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4994 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4996 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4997 if ( joinInt < 1 || joinInt > 3 )
5001 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5004 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5010 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5011 double distStart = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5012 double distEnd = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5015 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5021 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5022 double dx = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5023 double dy = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5025 return QVariant::fromValue( fGeom );
5030 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5031 const double rotation = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5032 const QgsGeometry center = values.at( 2 ).
isValid() ? QgsExpressionUtils::getGeometry( values.at( 2 ), parent )
5034 const bool perPart = values.value( 3 ).toBool();
5041 std::unique_ptr< QgsGeometryCollection > collection( qgsgeometry_cast< QgsGeometryCollection * >( fGeom.
constGet()->
clone() ) );
5044 const QgsPointXY partCenter = ( *it )->boundingBox().center();
5045 QTransform t = QTransform::fromTranslate( partCenter.
x(), partCenter.
y() );
5046 t.rotate( -rotation );
5047 t.translate( -partCenter.
x(), -partCenter.
y() );
5048 ( *it )->transform( t );
5050 return QVariant::fromValue(
QgsGeometry( std::move( collection ) ) );
5062 parent->
setEvalErrorString( QObject::tr(
"Function 'rotate' requires a point value for the center" ) );
5070 fGeom.
rotate( rotation, pt );
5071 return QVariant::fromValue( fGeom );
5077 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5078 const double xScale = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5079 const double yScale = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5080 const QgsGeometry center = values.at( 3 ).isValid() ? QgsExpressionUtils::getGeometry( values.at( 3 ), parent )
5091 parent->
setEvalErrorString( QObject::tr(
"Function 'scale' requires a point value for the center" ) );
5099 QTransform t = QTransform::fromTranslate( pt.
x(), pt.
y() );
5100 t.scale( xScale, yScale );
5101 t.translate( -pt.
x(), -pt.
y() );
5103 return QVariant::fromValue( fGeom );
5108 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5114 const double deltaX = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5115 const double deltaY = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5117 const double rotationZ = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5119 const double scaleX = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
5120 const double scaleY = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
5122 const double deltaZ = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
5123 const double deltaM = QgsExpressionUtils::getDoubleValue( values.at( 7 ), parent );
5124 const double scaleZ = QgsExpressionUtils::getDoubleValue( values.at( 8 ), parent );
5125 const double scaleM = QgsExpressionUtils::getDoubleValue( values.at( 9 ), parent );
5136 QTransform transform;
5137 transform.translate( deltaX, deltaY );
5138 transform.rotate( rotationZ );
5139 transform.scale( scaleX, scaleY );
5140 fGeom.
transform( transform, deltaZ, scaleZ, deltaM, scaleM );
5142 return QVariant::fromValue( fGeom );
5148 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5150 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5155 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5157 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5163 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5164 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5166 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5172 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5174 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5178#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
5183 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5184 const double targetPercent = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5185 const bool allowHoles = values.value( 2 ).toBool();
5187 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5200 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5202 if ( values.length() == 2 )
5203 segments = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5211 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5217 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5219 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5225 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5231 double area,
angle, width, height;
5244 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5245 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5247 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5253 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5260 const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( fGeom.
constGet() );
5265 result = reversed ? QVariant::fromValue(
QgsGeometry( reversed ) ) : QVariant();
5273 if (
const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( collection->
geometryN( i ) ) )
5275 reversed->addGeometry( curve->
reversed() );
5282 result = reversed ? QVariant::fromValue(
QgsGeometry( std::move( reversed ) ) ) : QVariant();
5289 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5300 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->
geometryN( 0 ) );
5309 QVariant result = exterior ? QVariant::fromValue(
QgsGeometry( exterior ) ) : QVariant();
5315 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5316 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5317 return QVariant( fGeom.
distance( sGeom ) );
5322 QgsGeometry g1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5323 QgsGeometry g2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5326 if ( values.length() == 3 && values.at( 2 ).isValid() )
5328 double densify = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5329 densify = std::clamp( densify, 0.0, 1.0 );
5337 return res > -1 ? QVariant( res ) : QVariant();
5342 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5343 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5345 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5350 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5351 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5353 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5358 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5359 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5361 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5367 if ( values.length() < 1 || values.length() > 2 )
5370 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5372 if ( values.length() == 2 )
5373 prec = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5374 QString wkt = fGeom.
asWkt( prec );
5375 return QVariant( wkt );
5380 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5381 return fGeom.
isNull() ? QVariant() : QVariant( fGeom.asWkb() );
5386 if ( values.length() != 2 )
5388 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires exactly two parameters. %n given.",
nullptr, values.length() ) );
5392 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5393 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5395 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5402 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5407 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5414 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5421 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires two points as arguments." ) );
5428 if ( pt1->
y() < pt2->
y() )
5430 else if ( pt1->
y() > pt2->
y() )
5438 if ( pt1->
x() < pt2->
x() )
5440 else if ( pt1->
x() > pt2->
x() )
5441 return M_PI + ( M_PI_2 );
5446 if ( pt1->
x() < pt2->
x() )
5448 if ( pt1->
y() < pt2->
y() )
5450 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) );
5454 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5461 if ( pt1->
y() > pt2->
y() )
5463 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) )
5468 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5469 + ( M_PI + ( M_PI_2 ) );
5476 const QgsGeometry geom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5477 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5479 QString ellipsoid = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
5483 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires two valid point geometries." ) );
5491 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires point geometries or multi point geometries with a single part." ) );
5502 sourceCrs = context->
variable( QStringLiteral(
"_layer_crs" ) ).value<QgsCoordinateReferenceSystem>();
5505 if ( ellipsoid.isEmpty() )
5507 ellipsoid = context->
variable( QStringLiteral(
"project_ellipsoid" ) ).toString();
5513 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires a valid source CRS." ) );
5521 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires a valid ellipsoid acronym or ellipsoid authority ID." ) );
5527 const double bearing = da.
bearing( point1, point2 );
5528 if ( std::isfinite( bearing ) )
5530 return std::fmod( bearing + 2 * M_PI, 2 * M_PI );
5543 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5547 parent->
setEvalErrorString( QStringLiteral(
"'project' requires a point geometry" ) );
5551 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5552 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5553 double inclination = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5556 QgsPoint newPoint = p->
project( distance, 180.0 * azimuth / M_PI, 180.0 * inclination / M_PI );
5563 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5564 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5566 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5573 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5577 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5584 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5592 parent->
setEvalErrorString( QStringLiteral(
"Function 'inclination' requires two points as arguments." ) );
5602 if ( values.length() != 3 )
5605 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5606 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5607 double y = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5611 QVariant result = geom.
constGet() ? QVariant::fromValue( geom ) : QVariant();
5617 if ( values.length() < 2 )
5620 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5623 return values.at( 0 );
5625 QString expString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5626 QVariant cachedExpression;
5631 if ( cachedExpression.isValid() )
5638 bool asc = values.value( 2 ).toBool();
5656 Q_ASSERT( collection );
5660 QgsExpressionSorter sorter( orderBy );
5662 QList<QgsFeature> partFeatures;
5663 partFeatures.reserve( collection->
partCount() );
5664 for (
int i = 0; i < collection->
partCount(); ++i )
5670 sorter.sortFeatures( partFeatures, unconstedContext );
5674 Q_ASSERT( orderedGeom );
5679 for (
const QgsFeature &feature : std::as_const( partFeatures ) )
5684 QVariant result = QVariant::fromValue(
QgsGeometry( orderedGeom ) );
5687 delete unconstedContext;
5694 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5695 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5699 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5705 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5706 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5710 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5716 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5717 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5721 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5727 const QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5728 const double m = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5729 const bool use3DDistance = values.at( 2 ).toBool();
5731 double x, y, z, distance;
5754 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5757 parent->
setEvalErrorString( QObject::tr(
"line_substring requires a curve geometry input" ) );
5763 curve = qgsgeometry_cast< const QgsCurve * >( lineGeom.
constGet() );
5770 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
5777 double startDistance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5778 double endDistance = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5780 std::unique_ptr< QgsCurve > substring( curve->
curveSubstring( startDistance, endDistance ) );
5782 return !result.isNull() ? QVariant::fromValue( result ) : QVariant();
5787 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5788 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5795 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5796 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5801 vertex = count + vertex;
5809 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5810 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5815 vertex = count + vertex;
5823 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5824 QgsGeometry pointGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5828 return distance >= 0 ? distance : QVariant();
5833 const QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5834 const double m = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5835 const bool use3DDistance = values.at( 2 ).toBool();
5837 double x, y, z, distance;
5846 return found ? distance : QVariant();
5851 if ( values.length() == 2 && values.at( 1 ).toInt() != 0 )
5853 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5854 return qgsRound( number, QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
5857 if ( values.length() >= 1 )
5859 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5860 return QVariant( qlonglong( std::round( number ) ) );
5875 const double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5876 const int places = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5877 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5884 const bool omitGroupSeparator = values.value( 3 ).toBool();
5885 const bool trimTrailingZeros = values.value( 4 ).toBool();
5887 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5888 if ( !omitGroupSeparator )
5889 locale.setNumberOptions( locale.numberOptions() & ~QLocale::NumberOption::OmitGroupSeparator );
5891 locale.setNumberOptions( locale.numberOptions() | QLocale::NumberOption::OmitGroupSeparator );
5893 QString res = locale.toString( value,
'f', places );
5895 if ( trimTrailingZeros )
5897#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
5898 const QChar decimal = locale.decimalPoint();
5899 const QChar zeroDigit = locale.zeroDigit();
5901 const QChar decimal = locale.decimalPoint().at( 0 );
5902 const QChar zeroDigit = locale.zeroDigit().at( 0 );
5905 if ( res.contains( decimal ) )
5907 int trimPoint = res.length() - 1;
5909 while ( res.at( trimPoint ) == zeroDigit )
5912 if ( res.at( trimPoint ) == decimal )
5915 res.truncate( trimPoint + 1 );
5924 QDateTime datetime = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
5925 const QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5926 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5929 if ( format.indexOf(
"Z" ) > 0 )
5930 datetime = datetime.toUTC();
5932 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5933 return locale.toString( datetime, format );
5938 const QVariant variant = values.at( 0 );
5940 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
5941 if ( !color.isValid() )
5944 const float alpha = color.alphaF();
5945 if ( color.spec() == QColor::Spec::Cmyk )
5947 const float avg = ( color.cyanF() + color.magentaF() + color.yellowF() ) / 3;
5948 color = QColor::fromCmykF( avg, avg, avg, color.blackF(), alpha );
5952 const float avg = ( color.redF() + color.greenF() + color.blueF() ) / 3;
5953 color.setRgbF( avg, avg, avg, alpha );
5956 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
5963 double ratio = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5968 else if ( ratio < 0 )
5973 int red =
static_cast<int>( color1.red() * ( 1 - ratio ) + color2.red() * ratio );
5974 int green =
static_cast<int>( color1.green() * ( 1 - ratio ) + color2.green() * ratio );
5975 int blue =
static_cast<int>( color1.blue() * ( 1 - ratio ) + color2.blue() * ratio );
5976 int alpha =
static_cast<int>( color1.alpha() * ( 1 - ratio ) + color2.alpha() * ratio );
5978 QColor newColor( red, green, blue, alpha );
5985 const QVariant variant1 = values.at( 0 );
5986 const QVariant variant2 = values.at( 1 );
5988 if ( variant1.userType() != variant2.userType() )
5990 parent->
setEvalErrorString( QObject::tr(
"Both color arguments must have the same type (string or color object)" ) );
5995 const QColor color1 = QgsExpressionUtils::getColorValue( variant1, parent, isQColor );
5996 if ( !color1.isValid() )
5999 const QColor color2 = QgsExpressionUtils::getColorValue( variant2, parent, isQColor );
6000 if ( !color2.isValid() )
6003 if ( ( color1.spec() == QColor::Cmyk ) != ( color2.spec() == QColor::Cmyk ) )
6005 parent->
setEvalErrorString( QObject::tr(
"Both color arguments must have compatible color type (CMYK or RGB/HSV/HSL)" ) );
6009 const float ratio =
static_cast<float>( std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0., 1. ) );
6015 const float alpha = color1.alphaF() * ( 1 - ratio ) + color2.alphaF() * ratio;
6016 if ( color1.spec() == QColor::Spec::Cmyk )
6018 float cyan = color1.cyanF() * ( 1 - ratio ) + color2.cyanF() * ratio;
6019 float magenta = color1.magentaF() * ( 1 - ratio ) + color2.magentaF() * ratio;
6020 float yellow = color1.yellowF() * ( 1 - ratio ) + color2.yellowF() * ratio;
6021 float black = color1.blackF() * ( 1 - ratio ) + color2.blackF() * ratio;
6022 newColor = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6026 float red = color1.redF() * ( 1 - ratio ) + color2.redF() * ratio;
6027 float green = color1.greenF() * ( 1 - ratio ) + color2.greenF() * ratio;
6028 float blue = color1.blueF() * ( 1 - ratio ) + color2.blueF() * ratio;
6029 newColor = QColor::fromRgbF( red, green, blue, alpha );
6034 return isQColor ? QVariant( newColor ) : QVariant(
QgsSymbolLayerUtils::encodeColor( newColor ) );
6039 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
6040 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6041 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6042 QColor color = QColor( red, green, blue );
6043 if ( ! color.isValid() )
6045 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( red ).arg( green ).arg( blue ) );
6046 color = QColor( 0, 0, 0 );
6049 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6054 const float red = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6055 const float green = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6056 const float blue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6057 const float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6058 QColor color = QColor::fromRgbF( red, green, blue, alpha );
6059 if ( ! color.isValid() )
6061 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
6070 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
6071 QVariant value = node->
eval( parent, context );
6075 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
6077 value = node->
eval( parent, context );
6085 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
6087 QVariant value = node->
eval( parent, context );
6089 if ( value.toBool() )
6091 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
6093 value = node->
eval( parent, context );
6098 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
6100 value = node->
eval( parent, context );
6108 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
6109 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6110 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6111 int alpha = QgsExpressionUtils::getNativeIntValue( values.at( 3 ), parent );
6112 QColor color = QColor( red, green, blue, alpha );
6113 if ( ! color.isValid() )
6115 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
6116 color = QColor( 0, 0, 0 );
6125 if ( values.at( 0 ).userType() == qMetaTypeId< QgsGradientColorRamp>() )
6127 expRamp = QgsExpressionUtils::getRamp( values.at( 0 ), parent );
6132 QString rampName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
6136 parent->
setEvalErrorString( QObject::tr(
"\"%1\" is not a valid color ramp" ).arg( rampName ) );
6141 double value = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
6142 QColor color = ramp->
color( value );
6155 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6157 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6159 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6161 QColor color = QColor::fromHslF( hue, saturation, lightness );
6163 if ( ! color.isValid() )
6165 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( lightness ) );
6166 color = QColor( 0, 0, 0 );
6169 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6175 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6177 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6179 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6181 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
6183 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
6184 if ( ! color.isValid() )
6186 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
6187 color = QColor( 0, 0, 0 );
6194 float hue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6195 float saturation = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6196 float lightness = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6197 float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6199 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
6200 if ( ! color.isValid() )
6202 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
6212 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6214 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6216 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6218 QColor color = QColor::fromHsvF( hue, saturation, value );
6220 if ( ! color.isValid() )
6222 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( value ) );
6223 color = QColor( 0, 0, 0 );
6226 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6232 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6234 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6236 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6238 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
6240 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
6241 if ( ! color.isValid() )
6243 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
6244 color = QColor( 0, 0, 0 );
6251 float hue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6252 float saturation = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6253 float value = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6254 float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6255 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
6257 if ( ! color.isValid() )
6259 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
6268 const float cyan = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6269 const float magenta = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6270 const float yellow = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6271 const float black = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6272 const float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ) ), 0.f, 1.f );
6274 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6275 if ( ! color.isValid() )
6277 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
6287 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
6289 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6291 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6293 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
6295 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black );
6297 if ( ! color.isValid() )
6299 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ) );
6300 color = QColor( 0, 0, 0 );
6303 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6309 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
6311 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6313 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6315 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
6317 double alpha = QgsExpressionUtils::getIntValue( values.at( 4 ), parent ) / 255.0;
6319 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6320 if ( ! color.isValid() )
6322 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
6323 color = QColor( 0, 0, 0 );
6330 const QVariant variant = values.at( 0 );
6332 const QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6333 if ( !color.isValid() )
6336 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6337 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6339 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6340 return color.green();
6341 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6342 return color.blue();
6343 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6344 return color.alpha();
6345 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6346 return static_cast< double >( color.hsvHueF() * 360 );
6347 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6348 return static_cast< double >( color.hsvSaturationF() * 100 );
6349 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6350 return static_cast< double >( color.valueF() * 100 );
6351 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6352 return static_cast< double >( color.hslHueF() * 360 );
6353 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6354 return static_cast< double >( color.hslSaturationF() * 100 );
6355 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6356 return static_cast< double >( color.lightnessF() * 100 );
6357 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6358 return static_cast< double >( color.cyanF() * 100 );
6359 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6360 return static_cast< double >( color.magentaF() * 100 );
6361 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6362 return static_cast< double >( color.yellowF() * 100 );
6363 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6364 return static_cast< double >( color.blackF() * 100 );
6366 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6372 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
6375 parent->
setEvalErrorString( QObject::tr(
"A minimum of two colors is required to create a ramp" ) );
6379 QList< QColor > colors;
6381 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
6384 if ( !colors.last().isValid() )
6386 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( it.value().toString() ) );
6390 double step = it.key().toDouble();
6391 if ( it == map.constBegin() )
6396 else if ( it == map.constEnd() )
6406 bool discrete = values.at( 1 ).toBool();
6408 if ( colors.empty() )
6411 return QVariant::fromValue(
QgsGradientColorRamp( colors.first(), colors.last(), discrete, stops ) );
6416 const QVariant variant = values.at( 0 );
6418 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6419 if ( !color.isValid() )
6422 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6423 int value = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6424 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6425 color.setRed( std::clamp( value, 0, 255 ) );
6426 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6427 color.setGreen( std::clamp( value, 0, 255 ) );
6428 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6429 color.setBlue( std::clamp( value, 0, 255 ) );
6430 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6431 color.setAlpha( std::clamp( value, 0, 255 ) );
6432 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6433 color.setHsv( std::clamp( value, 0, 359 ), color.hsvSaturation(), color.value(), color.alpha() );
6434 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6435 color.setHsvF( color.hsvHueF(), std::clamp( value, 0, 100 ) / 100.0, color.valueF(), color.alphaF() );
6436 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6437 color.setHsvF( color.hsvHueF(), color.hsvSaturationF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6438 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6439 color.setHsl( std::clamp( value, 0, 359 ), color.hslSaturation(), color.lightness(), color.alpha() );
6440 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6441 color.setHslF( color.hslHueF(), std::clamp( value, 0, 100 ) / 100.0, color.lightnessF(), color.alphaF() );
6442 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6443 color.setHslF( color.hslHueF(), color.hslSaturationF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6444 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6445 color.setCmykF( std::clamp( value, 0, 100 ) / 100.0, color.magentaF(), color.yellowF(), color.blackF(), color.alphaF() );
6446 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6447 color.setCmykF( color.cyanF(), std::clamp( value, 0, 100 ) / 100.0, color.yellowF(), color.blackF(), color.alphaF() );
6448 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6449 color.setCmykF( color.cyanF(), color.magentaF(), std::clamp( value, 0, 100 ) / 100.0, color.blackF(), color.alphaF() );
6450 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6451 color.setCmykF( color.cyanF(), color.magentaF(), color.yellowF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6454 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6457 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6462 const QVariant variant = values.at( 0 );
6464 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6465 if ( !color.isValid() )
6468 color = color.darker( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6470 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6475 const QVariant variant = values.at( 0 );
6477 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6478 if ( !color.isValid() )
6481 color = color.lighter( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6483 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6488 QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6491 return QVariant::fromValue( geom );
6497 const QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6505 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
6510 return QVariant::fromValue( fGeom );
6513 return QVariant::fromValue( fGeom );
6522 return QVariant::fromValue( fGeom );
6535 bool foundLayer =
false;
6536 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6539 if ( !featureSource || !foundLayer )
6544 const QgsFeatureId fid = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
6557 result = QVariant::fromValue( fet );
6565 bool foundLayer =
false;
6566 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6569 if ( !featureSource || !foundLayer )
6574 QString cacheValueKey;
6575 if ( values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
6577 QVariantMap attributeMap = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
6579 QMap <QString, QVariant>::const_iterator i = attributeMap.constBegin();
6580 QString filterString;
6581 for ( ; i != attributeMap.constEnd(); ++i )
6583 if ( !filterString.isEmpty() )
6585 filterString.append(
" AND " );
6589 cacheValueKey = QStringLiteral(
"getfeature:%1:%2" ).arg( featureSource->id(), filterString );
6598 QString attribute = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6599 int attributeId = featureSource->fields().lookupField( attribute );
6600 if ( attributeId == -1 )
6605 const QVariant &attVal = values.at( 2 );
6607 cacheValueKey = QStringLiteral(
"getfeature:%1:%2:%3" ).arg( featureSource->id(), QString::number( attributeId ), attVal.toString() );
6630 res = QVariant::fromValue( fet );
6645 if ( !values.isEmpty() )
6648 if ( col && ( values.size() == 1 || !values.at( 1 ).isValid() ) )
6649 fieldName = col->
name();
6650 else if ( values.size() == 2 )
6651 fieldName = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6654 QVariant value = values.at( 0 );
6659 if ( fieldIndex == -1 )
6661 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: Field not found %2" ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6667 QgsVectorLayer *layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
6670 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName, value.toString() );
6679 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName );
6697 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: function cannot be evaluated without a context." ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6705 const QVariant data = values.at( 0 );
6706 const QMimeDatabase db;
6707 return db.mimeTypeForData( data.toByteArray() ).name();
6712 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6714 bool foundLayer =
false;
6715 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [layerProperty](
QgsMapLayer * layer )-> QVariant
6721 if ( QString::compare( layerProperty, QStringLiteral(
"name" ), Qt::CaseInsensitive ) == 0 )
6722 return layer->name();
6723 else if ( QString::compare( layerProperty, QStringLiteral(
"id" ), Qt::CaseInsensitive ) == 0 )
6725 else if ( QString::compare( layerProperty, QStringLiteral(
"title" ), Qt::CaseInsensitive ) == 0 )
6726 return !layer->metadata().title().isEmpty() ? layer->metadata().title() : layer->serverProperties()->title();
6727 else if ( QString::compare( layerProperty, QStringLiteral(
"abstract" ), Qt::CaseInsensitive ) == 0 )
6728 return !layer->metadata().abstract().isEmpty() ? layer->metadata().abstract() : layer->serverProperties()->abstract();
6729 else if ( QString::compare( layerProperty, QStringLiteral(
"keywords" ), Qt::CaseInsensitive ) == 0 )
6731 QStringList keywords;
6732 const QgsAbstractMetadataBase::KeywordMap keywordMap = layer->metadata().keywords();
6733 for ( auto it = keywordMap.constBegin(); it != keywordMap.constEnd(); ++it )
6735 keywords.append( it.value() );
6737 if ( !keywords.isEmpty() )
6739 return layer->serverProperties()->keywordList();
6741 else if ( QString::compare( layerProperty, QStringLiteral(
"data_url" ), Qt::CaseInsensitive ) == 0 )
6743 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution" ), Qt::CaseInsensitive ) == 0 )
6745 return !layer->
metadata().
rights().isEmpty() ? QVariant( layer->
metadata().
rights() ) : QVariant( layer->serverProperties()->attribution() );
6747 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution_url" ), Qt::CaseInsensitive ) == 0 )
6749 else if ( QString::compare( layerProperty, QStringLiteral(
"source" ), Qt::CaseInsensitive ) == 0 )
6751 else if ( QString::compare( layerProperty, QStringLiteral(
"min_scale" ), Qt::CaseInsensitive ) == 0 )
6753 else if ( QString::compare( layerProperty, QStringLiteral(
"max_scale" ), Qt::CaseInsensitive ) == 0 )
6755 else if ( QString::compare( layerProperty, QStringLiteral(
"is_editable" ), Qt::CaseInsensitive ) == 0 )
6757 else if ( QString::compare( layerProperty, QStringLiteral(
"crs" ), Qt::CaseInsensitive ) == 0 )
6759 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_definition" ), Qt::CaseInsensitive ) == 0 )
6761 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_description" ), Qt::CaseInsensitive ) == 0 )
6763 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_ellipsoid" ), Qt::CaseInsensitive ) == 0 )
6765 else if ( QString::compare( layerProperty, QStringLiteral(
"extent" ), Qt::CaseInsensitive ) == 0 )
6768 QVariant result = QVariant::fromValue( extentGeom );
6771 else if ( QString::compare( layerProperty, QStringLiteral(
"distance_units" ), Qt::CaseInsensitive ) == 0 )
6773 else if ( QString::compare( layerProperty, QStringLiteral(
"path" ), Qt::CaseInsensitive ) == 0 )
6776 return decodedUri.value( QStringLiteral(
"path" ) );
6778 else if ( QString::compare( layerProperty, QStringLiteral(
"type" ), Qt::CaseInsensitive ) == 0 )
6780 switch ( layer->
type() )
6783 return QCoreApplication::translate(
"expressions",
"Vector" );
6785 return QCoreApplication::translate(
"expressions",
"Raster" );
6787 return QCoreApplication::translate(
"expressions",
"Mesh" );
6789 return QCoreApplication::translate(
"expressions",
"Vector Tile" );
6791 return QCoreApplication::translate(
"expressions",
"Plugin" );
6793 return QCoreApplication::translate(
"expressions",
"Annotation" );
6795 return QCoreApplication::translate(
"expressions",
"Point Cloud" );
6797 return QCoreApplication::translate(
"expressions",
"Group" );
6799 return QCoreApplication::translate(
"expressions",
"Tiled Scene" );
6805 QgsVectorLayer *vLayer = qobject_cast< QgsVectorLayer * >( layer );
6808 if ( QString::compare( layerProperty, QStringLiteral(
"storage_type" ), Qt::CaseInsensitive ) == 0 )
6810 else if ( QString::compare( layerProperty, QStringLiteral(
"geometry_type" ), Qt::CaseInsensitive ) == 0 )
6812 else if ( QString::compare( layerProperty, QStringLiteral(
"feature_count" ), Qt::CaseInsensitive ) == 0 )
6828 const QString uriPart = values.at( 1 ).toString();
6830 bool foundLayer =
false;
6832 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, uriPart](
QgsMapLayer * layer )-> QVariant
6834 if ( !layer->dataProvider() )
6836 parent->setEvalErrorString( QObject::tr(
"Layer %1 has invalid data provider" ).arg( layer->name() ) );
6842 if ( !uriPart.isNull() )
6844 return decodedUri.value( uriPart );
6854 parent->
setEvalErrorString( QObject::tr(
"Function `decode_uri` requires a valid layer." ) );
6865 const int band = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6866 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6868 bool foundLayer =
false;
6869 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, band, layerProperty](
QgsMapLayer * layer )-> QVariant
6871 QgsRasterLayer *rl = qobject_cast< QgsRasterLayer * >( layer );
6875 if ( band < 1 || band > rl->bandCount() )
6877 parent->setEvalErrorString( QObject::tr(
"Invalid band number %1 for layer" ).arg( band ) );
6883 if ( QString::compare( layerProperty, QStringLiteral(
"avg" ), Qt::CaseInsensitive ) == 0 )
6885 else if ( QString::compare( layerProperty, QStringLiteral(
"stdev" ), Qt::CaseInsensitive ) == 0 )
6887 else if ( QString::compare( layerProperty, QStringLiteral(
"min" ), Qt::CaseInsensitive ) == 0 )
6889 else if ( QString::compare( layerProperty, QStringLiteral(
"max" ), Qt::CaseInsensitive ) == 0 )
6891 else if ( QString::compare( layerProperty, QStringLiteral(
"range" ), Qt::CaseInsensitive ) == 0 )
6893 else if ( QString::compare( layerProperty, QStringLiteral(
"sum" ), Qt::CaseInsensitive ) == 0 )
6897 parent->
setEvalErrorString( QObject::tr(
"Invalid raster statistic: '%1'" ).arg( layerProperty ) );
6925 parent->
setEvalErrorString( QObject::tr(
"Function `raster_statistic` requires a valid raster layer." ) );
6942 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6943 bool ascending = values.value( 1 ).toBool();
6944 std::sort( list.begin(), list.end(), [ascending]( QVariant a, QVariant b ) ->
bool { return ( !ascending ? qgsVariantLessThan( b, a ) : qgsVariantLessThan( a, b ) ); } );
6950 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).length();
6955 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).contains( values.at( 1 ) ) );
6960 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).count( values.at( 1 ) ) );
6965 QVariantList listA = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6966 QVariantList listB = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
6968 for (
const auto &item : listB )
6970 if ( listA.contains( item ) )
6974 return QVariant( match == listB.count() );
6979 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).indexOf( values.at( 1 ) );
6984 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6985 const int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6986 if ( pos < list.length() && pos >= 0 )
return list.at( pos );
6987 else if ( pos < 0 && ( list.length() + pos ) >= 0 )
6988 return list.at( list.length() + pos );
6994 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6995 return list.value( 0 );
7000 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7001 return list.value( list.size() - 1 );
7006 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7007 return list.isEmpty() ? QVariant() : *std::min_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
7012 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7013 return list.isEmpty() ? QVariant() : *std::max_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
7018 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7021 for (
const QVariant &item : list )
7023 switch ( item.userType() )
7025 case QMetaType::Int:
7026 case QMetaType::UInt:
7027 case QMetaType::LongLong:
7028 case QMetaType::ULongLong:
7029 case QMetaType::Float:
7030 case QMetaType::Double:
7031 total += item.toDouble();
7036 return i == 0 ? QVariant() : total / i;
7041 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7042 QVariantList numbers;
7043 for (
const auto &item : list )
7045 switch ( item.userType() )
7047 case QMetaType::Int:
7048 case QMetaType::UInt:
7049 case QMetaType::LongLong:
7050 case QMetaType::ULongLong:
7051 case QMetaType::Float:
7052 case QMetaType::Double:
7053 numbers.append( item );
7057 std::sort( numbers.begin(), numbers.end(), []( QVariant a, QVariant b ) ->
bool { return ( qgsVariantLessThan( a, b ) ); } );
7058 const int count = numbers.count();
7063 else if ( count % 2 )
7065 return numbers.at( count / 2 );
7069 return ( numbers.at( count / 2 - 1 ).toDouble() + numbers.at( count / 2 ).toDouble() ) / 2;
7075 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7078 for (
const QVariant &item : list )
7080 switch ( item.userType() )
7082 case QMetaType::Int:
7083 case QMetaType::UInt:
7084 case QMetaType::LongLong:
7085 case QMetaType::ULongLong:
7086 case QMetaType::Float:
7087 case QMetaType::Double:
7088 total += item.toDouble();
7093 return i == 0 ? QVariant() : total;
7096static QVariant convertToSameType(
const QVariant &value, QMetaType::Type type )
7098 QVariant result = value;
7099 result.convert(
static_cast<int>( type ) );
7105 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7106 QHash< QVariant, int > hash;
7107 for (
const auto &item : list )
7111 const QList< int > occurrences = hash.values();
7112 if ( occurrences.empty() )
7113 return QVariantList();
7115 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
7117 const QString option = values.at( 1 ).toString();
7118 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
7120 return convertToSameType( hash.keys( maxValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7122 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
7124 if ( hash.isEmpty() )
7127 return QVariant( hash.key( maxValue ) );
7129 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
7131 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( maxValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) ), context, parent, node );
7133 else if ( option.compare( QLatin1String(
"real_majority" ), Qt::CaseInsensitive ) == 0 )
7135 if ( maxValue * 2 <= list.size() )
7138 return QVariant( hash.key( maxValue ) );
7149 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7150 QHash< QVariant, int > hash;
7151 for (
const auto &item : list )
7155 const QList< int > occurrences = hash.values();
7156 if ( occurrences.empty() )
7157 return QVariantList();
7159 const int minValue = *std::min_element( occurrences.constBegin(), occurrences.constEnd() );
7161 const QString option = values.at( 1 ).toString();
7162 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
7164 return convertToSameType( hash.keys( minValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7166 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
7168 if ( hash.isEmpty() )
7171 return QVariant( hash.key( minValue ) );
7173 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
7175 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( minValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) ), context, parent, node );
7177 else if ( option.compare( QLatin1String(
"real_minority" ), Qt::CaseInsensitive ) == 0 )
7179 if ( hash.isEmpty() )
7183 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
7184 if ( maxValue * 2 > list.size() )
7185 hash.remove( hash.key( maxValue ) );
7187 return convertToSameType( hash.keys(),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7198 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7199 list.append( values.at( 1 ) );
7200 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7205 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7206 list.prepend( values.at( 1 ) );
7207 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7212 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7213 list.insert( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), values.at( 2 ) );
7214 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7219 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7220 int position = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7222 position = position + list.length();
7223 if ( position >= 0 && position < list.length() )
7224 list.removeAt( position );
7225 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7233 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7235 const QVariant toRemove = values.at( 1 );
7238 list.erase( std::remove_if( list.begin(), list.end(), [](
const QVariant & element )
7240 return QgsVariantUtils::isNull( element );
7245 list.removeAll( toRemove );
7247 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7252 if ( values.count() == 2 && values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
7254 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
7256 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7257 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
7259 int index = list.indexOf( it.key() );
7260 while ( index >= 0 )
7262 list.replace( index, it.value() );
7263 index = list.indexOf( it.key() );
7267 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7269 else if ( values.count() == 3 )
7271 QVariantList before;
7273 bool isSingleReplacement =
false;
7275 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).userType() != QMetaType::Type::QStringList )
7277 before = QVariantList() << values.at( 1 );
7281 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
7284 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
7286 after = QVariantList() << values.at( 2 );
7287 isSingleReplacement =
true;
7291 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
7294 if ( !isSingleReplacement && before.length() != after.length() )
7296 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
7300 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7301 for (
int i = 0; i < before.length(); i++ )
7303 int index = list.indexOf( before.at( i ) );
7304 while ( index >= 0 )
7306 list.replace( index, after.at( isSingleReplacement ? 0 : i ) );
7307 index = list.indexOf( before.at( i ) );
7311 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7315 parent->
setEvalErrorString( QObject::tr(
"Function array_replace requires 2 or 3 arguments" ) );
7322 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7323 QVariantList list_new;
7325 for (
const QVariant &cur :
QgsExpressionUtils::getListValue( values.at( 1 ), parent ) )
7327 while ( list.removeOne( cur ) )
7329 list_new.append( cur );
7333 list_new.append( list );
7335 return convertToSameType( list_new,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7341 for (
const QVariant &cur : values )
7343 list += QgsExpressionUtils::getListValue( cur, parent );
7345 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7350 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7351 int start_pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7352 const int end_pos = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
7353 int slice_length = 0;
7355 if ( start_pos < 0 )
7357 start_pos = list.length() + start_pos;
7361 slice_length = end_pos - start_pos + 1;
7365 slice_length = list.length() + end_pos - start_pos + 1;
7368 if ( slice_length < 0 )
7372 list = list.mid( start_pos, slice_length );
7378 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7379 std::reverse( list.begin(), list.end() );
7385 const QVariantList array1 = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7386 const QVariantList array2 = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
7387 for (
const QVariant &cur : array2 )
7389 if ( array1.contains( cur ) )
7390 return QVariant(
true );
7392 return QVariant(
false );
7397 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7399 QVariantList distinct;
7401 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7403 if ( !distinct.contains( *it ) )
7405 distinct += ( *it );
7414 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7415 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7416 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7420 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7422 str += ( !( *it ).toString().isEmpty() ) ? ( *it ).toString() : empty;
7423 if ( it != ( array.constEnd() - 1 ) )
7429 return QVariant( str );
7434 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7435 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7436 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7438 QStringList list = str.split( delimiter );
7441 for ( QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
7443 array += ( !( *it ).isEmpty() ) ? *it : empty;
7451 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7452 QJsonDocument document = QJsonDocument::fromJson( str.toUtf8() );
7453 if ( document.isNull() )
7456 return document.toVariant();
7462 QJsonDocument document = QJsonDocument::fromVariant( values.at( 0 ) );
7463 return QString( document.toJson( QJsonDocument::Compact ) );
7468 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7469 if ( str.isEmpty() )
7470 return QVariantMap();
7471 str = str.trimmed();
7478 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7485 for (
int i = 0; i + 1 < values.length(); i += 2 )
7487 result.insert( QgsExpressionUtils::getStringValue( values.at( i ), parent ), values.at( i + 1 ) );
7494 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7495 const QString prefix = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7496 QVariantMap resultMap;
7498 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7500 resultMap.insert( QString( it.key() ).prepend( prefix ), it.value() );
7508 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).value( values.at( 1 ).toString() );
7513 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).contains( values.at( 1 ).toString() );
7518 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7519 map.remove( values.at( 1 ).toString() );
7525 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7526 map.insert( values.at( 1 ).toString(), values.at( 2 ) );
7533 for (
const QVariant &cur : values )
7535 const QVariantMap curMap = QgsExpressionUtils::getMapValue( cur, parent );
7536 for ( QVariantMap::const_iterator it = curMap.constBegin(); it != curMap.constEnd(); ++it )
7537 result.insert( it.key(), it.value() );
7544 return QStringList( QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).keys() );
7549 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).values();
7554 const QString envVarName = values.at( 0 ).toString();
7555 if ( !QProcessEnvironment::systemEnvironment().contains( envVarName ) )
7558 return QProcessEnvironment::systemEnvironment().value( envVarName );
7563 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7566 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"base_file_name" ) ) );
7569 return QFileInfo( file ).completeBaseName();
7574 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7577 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_suffix" ) ) );
7580 return QFileInfo( file ).completeSuffix();
7585 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7588 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_exists" ) ) );
7591 return QFileInfo::exists( file );
7596 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7599 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_name" ) ) );
7602 return QFileInfo( file ).fileName();
7607 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7610 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_file" ) ) );
7613 return QFileInfo( file ).isFile();
7618 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7621 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_directory" ) ) );
7624 return QFileInfo( file ).isDir();
7629 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7632 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_path" ) ) );
7635 return QDir::toNativeSeparators( QFileInfo( file ).path() );
7640 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7643 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_size" ) ) );
7646 return QFileInfo( file ).size();
7649static QVariant fcnHash(
const QString &str,
const QCryptographicHash::Algorithm
algorithm )
7651 return QString( QCryptographicHash::hash( str.toUtf8(),
algorithm ).toHex() );
7657 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7658 QString method = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).toLower();
7660 if ( method == QLatin1String(
"md4" ) )
7662 hash = fcnHash( str, QCryptographicHash::Md4 );
7664 else if ( method == QLatin1String(
"md5" ) )
7666 hash = fcnHash( str, QCryptographicHash::Md5 );
7668 else if ( method == QLatin1String(
"sha1" ) )
7670 hash = fcnHash( str, QCryptographicHash::Sha1 );
7672 else if ( method == QLatin1String(
"sha224" ) )
7674 hash = fcnHash( str, QCryptographicHash::Sha224 );
7676 else if ( method == QLatin1String(
"sha256" ) )
7678 hash = fcnHash( str, QCryptographicHash::Sha256 );
7680 else if ( method == QLatin1String(
"sha384" ) )
7682 hash = fcnHash( str, QCryptographicHash::Sha384 );
7684 else if ( method == QLatin1String(
"sha512" ) )
7686 hash = fcnHash( str, QCryptographicHash::Sha512 );
7688 else if ( method == QLatin1String(
"sha3_224" ) )
7690 hash = fcnHash( str, QCryptographicHash::Sha3_224 );
7692 else if ( method == QLatin1String(
"sha3_256" ) )
7694 hash = fcnHash( str, QCryptographicHash::Sha3_256 );
7696 else if ( method == QLatin1String(
"sha3_384" ) )
7698 hash = fcnHash( str, QCryptographicHash::Sha3_384 );
7700 else if ( method == QLatin1String(
"sha3_512" ) )
7702 hash = fcnHash( str, QCryptographicHash::Sha3_512 );
7704 else if ( method == QLatin1String(
"keccak_224" ) )
7706 hash = fcnHash( str, QCryptographicHash::Keccak_224 );
7708 else if ( method == QLatin1String(
"keccak_256" ) )
7710 hash = fcnHash( str, QCryptographicHash::Keccak_256 );
7712 else if ( method == QLatin1String(
"keccak_384" ) )
7714 hash = fcnHash( str, QCryptographicHash::Keccak_384 );
7716 else if ( method == QLatin1String(
"keccak_512" ) )
7718 hash = fcnHash( str, QCryptographicHash::Keccak_512 );
7722 parent->
setEvalErrorString( QObject::tr(
"Hash method %1 is not available on this system." ).arg( str ) );
7729 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Md5 );
7734 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Sha256 );
7739 const QByteArray input = values.at( 0 ).toByteArray();
7740 return QVariant( QString( input.toBase64() ) );
7745 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7747 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7749 query.addQueryItem( it.key(), it.value().toString() );
7751 return query.toString( QUrl::ComponentFormattingOption::FullyEncoded );
7756 const QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7757 const QByteArray base64 = value.toLocal8Bit();
7758 const QByteArray decoded = QByteArray::fromBase64( base64 );
7759 return QVariant( decoded );
7764static 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 )
7769 parent->
setEvalErrorString( QStringLiteral(
"This function was called without an expression context." ) );
7773 const QVariant sourceLayerRef = context->
variable( QStringLiteral(
"layer" ) );
7776 QgsVectorLayer *sourceLayer = QgsExpressionUtils::getVectorLayer( sourceLayerRef, context, parent );
7785 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
7788 const bool layerCanBeCached = node->
isStatic( parent, context );
7789 QVariant targetLayerValue = node->
eval( parent, context );
7793 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
7795 QString subExpString = node->dump();
7797 bool testOnly = ( subExpString ==
"NULL" );
7800 QgsVectorLayer *targetLayer = QgsExpressionUtils::getVectorLayer( targetLayerValue, context, parent );
7804 parent->
setEvalErrorString( QObject::tr(
"Layer '%1' could not be loaded." ).arg( targetLayerValue.toString() ) );
7809 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
7811 QString filterString = node->dump();
7812 if ( filterString !=
"NULL" )
7814 request.setFilterExpression( filterString );
7818 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
7820 QVariant limitValue = node->eval( parent, context );
7822 qlonglong limit = QgsExpressionUtils::getIntValue( limitValue, parent );
7825 double max_distance = 0;
7826 if ( isNearestFunc )
7828 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
7830 QVariant distanceValue = node->eval( parent, context );
7832 max_distance = QgsExpressionUtils::getDoubleValue( distanceValue, parent );
7836 node = QgsExpressionUtils::getNode( values.at( isNearestFunc ? 5 : 4 ), parent );
7838 QVariant cacheValue = node->eval( parent, context );
7840 bool cacheEnabled = cacheValue.toBool();
7846 double minOverlap { -1 };
7847 double minInscribedCircleRadius { -1 };
7848 bool returnDetails =
false;
7849 bool sortByMeasure =
false;
7850 bool sortAscending =
false;
7851 bool requireMeasures =
false;
7852 bool overlapOrRadiusFilter =
false;
7853 if ( isIntersectsFunc )
7856 node = QgsExpressionUtils::getNode( values.at( 5 ), parent );
7858 const QVariant minOverlapValue = node->eval( parent, context );
7860 minOverlap = QgsExpressionUtils::getDoubleValue( minOverlapValue, parent );
7861 node = QgsExpressionUtils::getNode( values.at( 6 ), parent );
7863 const QVariant minInscribedCircleRadiusValue = node->eval( parent, context );
7865 minInscribedCircleRadius = QgsExpressionUtils::getDoubleValue( minInscribedCircleRadiusValue, parent );
7866 node = QgsExpressionUtils::getNode( values.at( 7 ), parent );
7868 returnDetails = !testOnly && node->eval( parent, context ).toBool();
7869 node = QgsExpressionUtils::getNode( values.at( 8 ), parent );
7871 const QString sorting { node->eval( parent, context ).toString().toLower() };
7872 sortByMeasure = !testOnly && ( sorting.startsWith(
"asc" ) || sorting.startsWith(
"des" ) );
7873 sortAscending = sorting.startsWith(
"asc" );
7874 requireMeasures = sortByMeasure || returnDetails;
7875 overlapOrRadiusFilter = minInscribedCircleRadius != -1 || minOverlap != -1;
7882 if ( sourceLayer && targetLayer->crs() != sourceLayer->crs() )
7885 request.setDestinationCrs( sourceLayer->crs(), TransformContext );
7888 bool sameLayers = ( sourceLayer && sourceLayer->id() == targetLayer->id() );
7891 if ( bboxGrow != 0 )
7893 intDomain.
grow( bboxGrow );
7896 const QString cacheBase { QStringLiteral(
"%1:%2:%3" ).arg( targetLayer->id(), subExpString, filterString ) };
7902 QList<QgsFeature> features;
7903 if ( isNearestFunc || ( layerCanBeCached && cacheEnabled ) )
7907 const QString cacheLayer { QStringLiteral(
"ovrlaylyr:%1" ).arg( cacheBase ) };
7908 const QString cacheIndex { QStringLiteral(
"ovrlayidx:%1" ).arg( cacheBase ) };
7912 cachedTarget = targetLayer->
materialize( request );
7913 if ( layerCanBeCached )
7914 context->
setCachedValue( cacheLayer, QVariant::fromValue( cachedTarget ) );
7924 if ( layerCanBeCached )
7925 context->
setCachedValue( cacheIndex, QVariant::fromValue( spatialIndex ) );
7932 QList<QgsFeatureId> fidsList;
7933 if ( isNearestFunc )
7935 fidsList = spatialIndex.
nearestNeighbor( geometry, sameLayers ? limit + 1 : limit, max_distance );
7939 fidsList = spatialIndex.
intersects( intDomain );
7942 QListIterator<QgsFeatureId> i( fidsList );
7943 while ( i.hasNext() )
7946 if ( sameLayers && feat.
id() == fId2 )
7948 features.append( cachedTarget->
getFeature( fId2 ) );
7956 request.setFilterRect( intDomain );
7961 if ( sameLayers && feat.
id() == feat2.
id() )
7963 features.append( feat2 );
7971 const QString expCacheKey { QStringLiteral(
"exp:%1" ).arg( cacheBase ) };
7972 const QString ctxCacheKey { QStringLiteral(
"ctx:%1" ).arg( cacheBase ) };
7978 subExpression.
prepare( &subContext );
7991 auto testLinestring = [ = ](
const QgsGeometry intersection,
double & overlapValue ) ->
bool
7993 bool testResult {
false };
7995 QVector<double> overlapValues;
7999 const QgsCurve *geom = qgsgeometry_cast< const QgsCurve * >( *it );
8001 if ( minOverlap != -1 || requireMeasures )
8003 overlapValue = geom->
length();
8004 overlapValues.append( overlapValue );
8005 if ( minOverlap != -1 )
8007 if ( overlapValue >= minOverlap )
8019 if ( ! overlapValues.isEmpty() )
8021 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
8028 auto testPolygon = [ = ](
const QgsGeometry intersection,
double & radiusValue,
double & overlapValue ) ->
bool
8031 bool testResult {
false };
8033 QVector<double> overlapValues;
8034 QVector<double> radiusValues;
8037 const QgsCurvePolygon *geom = qgsgeometry_cast< const QgsCurvePolygon * >( *it );
8039 if ( minOverlap != -1 || requireMeasures )
8041 overlapValue = geom->
area();
8042 overlapValues.append( geom->
area() );
8043 if ( minOverlap != - 1 )
8045 if ( overlapValue >= minOverlap )
8057 if ( minInscribedCircleRadius != -1 || requireMeasures )
8060 const double width = bbox.
width();
8061 const double height = bbox.
height();
8062 const double size = width > height ? width : height;
8063 const double tolerance = size / 100.0;
8065 testResult = radiusValue >= minInscribedCircleRadius;
8066 radiusValues.append( radiusValues );
8071 if ( !radiusValues.isEmpty() )
8073 radiusValue = *std::max_element( radiusValues.cbegin(), radiusValues.cend() );
8076 if ( ! overlapValues.isEmpty() )
8078 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
8088 QVariantList results;
8090 QListIterator<QgsFeature> i( features );
8091 while ( i.hasNext() && ( sortByMeasure || limit == -1 || foundCount < limit ) )
8097 if ( ! relationFunction || ( geometry.*relationFunction )( feat2.
geometry() ) )
8100 double overlapValue = -1;
8101 double radiusValue = -1;
8103 if ( isIntersectsFunc && ( requireMeasures || overlapOrRadiusFilter ) )
8116 for (
const auto &geom : std::as_const( geometries ) )
8118 switch ( geom.type() )
8122 poly.append( geom.asPolygon() );
8127 line.append( geom.asPolyline() );
8132 point.append( geom.asPoint() );
8143 switch ( geometry.
type() )
8171 switch ( intersection.
type() )
8178 bool testResult { testPolygon( intersection, radiusValue, overlapValue ) };
8180 if ( ! testResult && overlapOrRadiusFilter )
8193 if ( minInscribedCircleRadius != -1 )
8199 const bool testResult { testLinestring( intersection, overlapValue ) };
8201 if ( ! testResult && overlapOrRadiusFilter )
8214 if ( minInscribedCircleRadius != -1 )
8219 bool testResult {
false };
8220 if ( minOverlap != -1 || requireMeasures )
8240 testResult = testLinestring( feat2.
geometry(), overlapValue );
8245 testResult = testPolygon( feat2.
geometry(), radiusValue, overlapValue );
8251 if ( ! testResult && overlapOrRadiusFilter )
8279 const QVariant expResult = subExpression.
evaluate( &subContext );
8281 if ( requireMeasures )
8283 QVariantMap resultRecord;
8284 resultRecord.insert( QStringLiteral(
"id" ), feat2.
id() );
8285 resultRecord.insert( QStringLiteral(
"result" ), expResult );
8287 resultRecord.insert( QStringLiteral(
"overlap" ), overlapValue );
8289 if ( radiusValue != -1 )
8291 resultRecord.insert( QStringLiteral(
"radius" ), radiusValue );
8293 results.append( resultRecord );
8297 results.append( expResult );
8303 results.append( feat2.
id() );
8317 if ( requireMeasures )
8319 if ( sortByMeasure )
8321 std::sort( results.begin(), results.end(), [ sortAscending ](
const QVariant & recordA,
const QVariant & recordB ) ->
bool
8323 return sortAscending ?
8324 recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble()
8325 : recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble();
8329 if ( limit > 0 && results.size() > limit )
8331 results.erase( results.begin() + limit );
8334 if ( ! returnDetails )
8336 QVariantList expResults;
8337 for (
auto it = results.constBegin(); it != results.constEnd(); ++it )
8339 expResults.append( it->toMap().value( QStringLiteral(
"result" ) ) );
8349 QVariantList disjoint_results;
8358 if ( !results.contains( feat2.
id() ) )
8361 disjoint_results.append( subExpression.
evaluate( &subContext ) );
8364 return disjoint_results;
8407 return executeGeomOverlay( values, context, parent,
nullptr,
false, 0,
true );
8416 QMutexLocker locker( &sFunctionsMutex );
8418 QList<QgsExpressionFunction *> &functions = *sFunctions();
8420 if ( functions.isEmpty() )
8458 functions << randFunc;
8462 functions << randfFunc;
8465 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max" ), -1, fcnMax, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8466 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min" ), -1, fcnMin, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8473 <<
new QgsStaticExpressionFunction( QStringLiteral(
"pi" ), 0, fcnPi, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$pi" ) )
8478 <<
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" ) )
8479 <<
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" ) )
8480 <<
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" ) )
8485 <<
new QgsStaticExpressionFunction( QStringLiteral(
"coalesce" ), -1, fcnCoalesce, QStringLiteral(
"Conditionals" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8499 QStringLiteral(
"Aggregates" ),
8508 if ( !node->
args() )
8511 QSet<QString> referencedVars;
8523 return referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() );
8532 if ( !node->
args() )
8533 return QSet<QString>();
8535 QSet<QString> referencedCols;
8536 QSet<QString> referencedVars;
8551 if ( referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() ) )
8554 return referencedCols;
8567 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count" ), aggParams, fcnAggregateCount, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8568 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_distinct" ), aggParams, fcnAggregateCountDistinct, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8569 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_missing" ), aggParams, fcnAggregateCountMissing, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8570 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minimum" ), aggParams, fcnAggregateMin, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8571 <<
new QgsStaticExpressionFunction( QStringLiteral(
"maximum" ), aggParams, fcnAggregateMax, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8572 <<
new QgsStaticExpressionFunction( QStringLiteral(
"sum" ), aggParams, fcnAggregateSum, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8573 <<
new QgsStaticExpressionFunction( QStringLiteral(
"mean" ), aggParams, fcnAggregateMean, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8574 <<
new QgsStaticExpressionFunction( QStringLiteral(
"median" ), aggParams, fcnAggregateMedian, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8575 <<
new QgsStaticExpressionFunction( QStringLiteral(
"stdev" ), aggParams, fcnAggregateStdev, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8576 <<
new QgsStaticExpressionFunction( QStringLiteral(
"range" ), aggParams, fcnAggregateRange, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8577 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minority" ), aggParams, fcnAggregateMinority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8578 <<
new QgsStaticExpressionFunction( QStringLiteral(
"majority" ), aggParams, fcnAggregateMajority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8579 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q1" ), aggParams, fcnAggregateQ1, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8580 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q3" ), aggParams, fcnAggregateQ3, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8581 <<
new QgsStaticExpressionFunction( QStringLiteral(
"iqr" ), aggParams, fcnAggregateIQR, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8582 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min_length" ), aggParams, fcnAggregateMinLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8583 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max_length" ), aggParams, fcnAggregateMaxLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8584 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect" ), aggParams, fcnAggregateCollectGeometry, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8585 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate" ), aggParamsConcat, fcnAggregateStringConcat, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8586 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate_unique" ), aggParamsConcat, fcnAggregateStringConcatUnique, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8587 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array_agg" ), aggParamsArray, fcnAggregateArray, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8592 <<
new QgsStaticExpressionFunction( QStringLiteral(
"now" ), 0, fcnNow, QStringLiteral(
"Date and Time" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$now" ) )
8595 fcnAge, QStringLiteral(
"Date and Time" ) )
8609 fcnMakeDate, QStringLiteral(
"Date and Time" ) )
8613 fcnMakeTime, QStringLiteral(
"Date and Time" ) )
8620 fcnMakeDateTime, QStringLiteral(
"Date and Time" ) )
8628 fcnMakeInterval, QStringLiteral(
"Date and Time" ) )
8653 false, QSet< QString >(),
false, QStringList(), true )
8654 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concat" ), -1, fcnConcat, QStringLiteral(
"String" ), QString(),
false, QSet<QString>(),
false, QStringList(), true )
8672 fcnColorMixRgb, QStringLiteral(
"Color" ) )
8676 fcnColorMix, QStringLiteral(
"Color" ) )
8680 fcnColorRgb, QStringLiteral(
"Color" ) )
8685 fcnColorRgbF, QStringLiteral(
"Color" ) )
8690 fncColorRgba, QStringLiteral(
"Color" ) )
8699 fcnCreateRamp, QStringLiteral(
"Color" ) )
8703 fcnColorHsl, QStringLiteral(
"Color" ) )
8708 fncColorHsla, QStringLiteral(
"Color" ) )
8713 fcnColorHslF, QStringLiteral(
"Color" ) )
8717 fcnColorHsv, QStringLiteral(
"Color" ) )
8722 fncColorHsva, QStringLiteral(
"Color" ) )
8727 fcnColorHsvF, QStringLiteral(
"Color" ) )
8732 fcnColorCmyk, QStringLiteral(
"Color" ) )
8738 fncColorCmyka, QStringLiteral(
"Color" ) )
8744 fcnColorCmykF, QStringLiteral(
"Color" ) )
8747 fncColorPart, QStringLiteral(
"Color" ) )
8750 fncDarker, QStringLiteral(
"Color" ) )
8753 fncLighter, QStringLiteral(
"Color" ) )
8758 fcnBaseFileName, QStringLiteral(
"Files and Paths" ) )
8760 fcnFileSuffix, QStringLiteral(
"Files and Paths" ) )
8762 fcnFileExists, QStringLiteral(
"Files and Paths" ) )
8764 fcnFileName, QStringLiteral(
"Files and Paths" ) )
8766 fcnPathIsFile, QStringLiteral(
"Files and Paths" ) )
8768 fcnPathIsDir, QStringLiteral(
"Files and Paths" ) )
8770 fcnFilePath, QStringLiteral(
"Files and Paths" ) )
8772 fcnFileSize, QStringLiteral(
"Files and Paths" ) )
8775 fcnExif, QStringLiteral(
"Files and Paths" ) )
8777 fcnExifGeoTag, QStringLiteral(
"GeometryGroup" ) )
8781 fcnGenericHash, QStringLiteral(
"Conversions" ) )
8783 fcnHashMd5, QStringLiteral(
"Conversions" ) )
8785 fcnHashSha256, QStringLiteral(
"Conversions" ) )
8789 fcnToBase64, QStringLiteral(
"Conversions" ) )
8791 fcnFromBase64, QStringLiteral(
"Conversions" ) )
8797 geomFunc->setIsStatic(
false );
8798 functions << geomFunc;
8802 functions << areaFunc;
8808 functions << lengthFunc;
8812 functions << perimeterFunc;
8818 fcnRoundness, QStringLiteral(
"GeometryGroup" ) );
8832 QMap< QString, QgsExpressionFunction::FcnEval > geometry_overlay_definitions
8834 { QStringLiteral(
"overlay_intersects" ), fcnGeomOverlayIntersects },
8835 { QStringLiteral(
"overlay_contains" ), fcnGeomOverlayContains },
8836 { QStringLiteral(
"overlay_crosses" ), fcnGeomOverlayCrosses },
8837 { QStringLiteral(
"overlay_equals" ), fcnGeomOverlayEquals },
8838 { QStringLiteral(
"overlay_touches" ), fcnGeomOverlayTouches },
8839 { QStringLiteral(
"overlay_disjoint" ), fcnGeomOverlayDisjoint },
8840 { QStringLiteral(
"overlay_within" ), fcnGeomOverlayWithin },
8842 QMapIterator< QString, QgsExpressionFunction::FcnEval > i( geometry_overlay_definitions );
8843 while ( i.hasNext() )
8860 functions << fcnGeomOverlayFunc;
8873 functions << fcnGeomOverlayNearestFunc;
8886 fcnNodesToPoints, QStringLiteral(
"GeometryGroup" ) )
8888 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect_geometries" ), -1, fcnCollectGeometries, QStringLiteral(
"GeometryGroup" ) )
8893 fcnMakePointM, QStringLiteral(
"GeometryGroup" ) )
8899 fcnMakeTriangle, QStringLiteral(
"GeometryGroup" ) )
8904 fcnMakeCircle, QStringLiteral(
"GeometryGroup" ) )
8911 fcnMakeEllipse, QStringLiteral(
"GeometryGroup" ) )
8917 fcnMakeRegularPolygon, QStringLiteral(
"GeometryGroup" ) )
8921 fcnMakeSquare, QStringLiteral(
"GeometryGroup" ) )
8927 fcnMakeRectangleFrom3Points, QStringLiteral(
"GeometryGroup" ) )
8931#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
8937 }, fcnGeomMakeValid, QStringLiteral(
"GeometryGroup" ) );
8946 functions << xAtFunc;
8951 functions << yAtFunc;
8967 fcnDisjoint, QStringLiteral(
"GeometryGroup" ) )
8970 fcnIntersects, QStringLiteral(
"GeometryGroup" ) )
8973 fcnTouches, QStringLiteral(
"GeometryGroup" ) )
8976 fcnCrosses, QStringLiteral(
"GeometryGroup" ) )
8979 fcnContains, QStringLiteral(
"GeometryGroup" ) )
8982 fcnOverlaps, QStringLiteral(
"GeometryGroup" ) )
8985 fcnWithin, QStringLiteral(
"GeometryGroup" ) )
8989 fcnTranslate, QStringLiteral(
"GeometryGroup" ) )
8994 fcnRotate, QStringLiteral(
"GeometryGroup" ) )
8999 fcnScale, QStringLiteral(
"GeometryGroup" ) )
9010 fcnAffineTransform, QStringLiteral(
"GeometryGroup" ) )
9017 fcnBuffer, QStringLiteral(
"GeometryGroup" ) )
9019 fcnForceRHR, QStringLiteral(
"GeometryGroup" ) )
9021 fcnForcePolygonCW, QStringLiteral(
"GeometryGroup" ) )
9023 fcnForcePolygonCCW, QStringLiteral(
"GeometryGroup" ) )
9033 , fcnTaperedBuffer, QStringLiteral(
"GeometryGroup" ) )
9036 , fcnBufferByM, QStringLiteral(
"GeometryGroup" ) )
9042 fcnOffsetCurve, QStringLiteral(
"GeometryGroup" ) )
9048 fcnSingleSidedBuffer, QStringLiteral(
"GeometryGroup" ) )
9052 fcnExtend, QStringLiteral(
"GeometryGroup" ) )
9061 fcnInteriorRingN, QStringLiteral(
"GeometryGroup" ) )
9064 fcnGeometryN, QStringLiteral(
"GeometryGroup" ) )
9071 }, fcnSharedPaths, QStringLiteral(
"GeometryGroup" ) )
9085 }, fcnTriangularWave, QStringLiteral(
"GeometryGroup" ) )
9094 }, fcnTriangularWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9101 }, fcnSquareWave, QStringLiteral(
"GeometryGroup" ) )
9110 }, fcnSquareWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9117 }, fcnRoundWave, QStringLiteral(
"GeometryGroup" ) )
9126 }, fcnRoundWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9135 }, fcnApplyDashPattern, QStringLiteral(
"GeometryGroup" ) )
9140 }, fcnDensifyByCount, QStringLiteral(
"GeometryGroup" ) )
9145 }, fcnDensifyByDistance, QStringLiteral(
"GeometryGroup" ) )
9157#
if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
9164 fcnOrientedBBox, QStringLiteral(
"GeometryGroup" ) )
9167 fcnMainAngle, QStringLiteral(
"GeometryGroup" ) )
9171 fcnMinimalCircle, QStringLiteral(
"GeometryGroup" ) )
9174 fcnDifference, QStringLiteral(
"GeometryGroup" ) )
9177 fcnDistance, QStringLiteral(
"GeometryGroup" ) )
9180 fcnHausdorffDistance, QStringLiteral(
"GeometryGroup" ) )
9183 fcnIntersection, QStringLiteral(
"GeometryGroup" ) )
9186 fcnSymDifference, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"symDifference" ) )
9189 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
9192 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
9195 fcnGeomToWKT, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"geomToWKT" ) )
9197 fcnGeomToWKB, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false )
9202 fcnTransformGeometry, QStringLiteral(
"GeometryGroup" ) )
9206 fcnExtrude, QStringLiteral(
"GeometryGroup" ), QString() )
9208 fcnGeomIsMultipart, QStringLiteral(
"GeometryGroup" ) )
9210 fcnZMax, QStringLiteral(
"GeometryGroup" ) )
9212 fcnZMin, QStringLiteral(
"GeometryGroup" ) )
9214 fcnMMax, QStringLiteral(
"GeometryGroup" ) )
9216 fcnMMin, QStringLiteral(
"GeometryGroup" ) )
9218 fcnSinuosity, QStringLiteral(
"GeometryGroup" ) )
9220 fcnStraightDistance2d, QStringLiteral(
"GeometryGroup" ) );
9226 fcnOrderParts, QStringLiteral(
"GeometryGroup" ), QString() );
9231 const QList< QgsExpressionNode *> argList = node->
args()->list();
9234 if ( !argNode->isStatic( parent, context ) )
9242 QString expString = argNode->
eval( parent, context ).toString();
9246 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9258 QString
expression = argNode->
eval( parent, context ).toString();
9260 e.prepare( context );
9266 functions << orderPartsFunc;
9271 fcnClosestPoint, QStringLiteral(
"GeometryGroup" ) )
9274 fcnShortestLine, QStringLiteral(
"GeometryGroup" ) )
9279 fcnLineInterpolatePointByM, QStringLiteral(
"GeometryGroup" ) )
9286 fcnLineLocateM, QStringLiteral(
"GeometryGroup" ) )
9299 functions << idFunc;
9303 functions << currentFeatureFunc;
9305 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" ) );
9307 functions << uuidFunc;
9314 fcnGetFeature, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"QgsExpressionUtils::getFeature" ) )
9317 fcnGetFeatureById, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false );
9322 functions << attributesFunc;
9326 functions << representAttributesFunc;
9334 functions << validateFeature;
9343 functions << validateAttribute;
9346 QStringLiteral(
"maptip" ),
9349 QStringLiteral(
"Record and Attributes" ),
9355 functions << maptipFunc;
9358 QStringLiteral(
"display_expression" ),
9360 fcnFeatureDisplayExpression,
9361 QStringLiteral(
"Record and Attributes" ),
9367 functions << displayFunc;
9370 QStringLiteral(
"is_selected" ),
9373 QStringLiteral(
"Record and Attributes" ),
9379 functions << isSelectedFunc;
9383 QStringLiteral(
"num_selected" ),
9386 QStringLiteral(
"Record and Attributes" ),
9394 QStringLiteral(
"sqlite_fetch_and_increment" ),
9402 fcnSqliteFetchAndIncrement,
9403 QStringLiteral(
"Record and Attributes" )
9427 parent->
setEvalErrorString( tr(
"If represent_value is called with 1 parameter, it must be an attribute." ) );
9437 parent->
setEvalErrorString( tr(
"represent_value must be called with exactly 1 or 2 parameters." ) );
9443 functions << representValueFunc;
9449 fcnGetLayerProperty, QStringLiteral(
"Map Layers" ) )
9454 fcnDecodeUri, QStringLiteral(
"Map Layers" ) )
9458 fcnMimeType, QStringLiteral(
"General" ) )
9475 QgsExpressionNode *argNode = node->args()->at( 0 );
9477 if ( !argNode->isStatic( parent, context ) )
9480 const QString varName = argNode->eval( parent, context ).toString();
9481 if ( varName == QLatin1String(
"feature" ) || varName == QLatin1String(
"id" ) || varName == QLatin1String(
"geometry" ) )
9484 const QgsExpressionContextScope *scope = context->activeScopeForVariable( varName );
9485 return scope ? scope->isStatic( varName ) : false;
9493 if ( node && node->
args()->
count() > 0 )
9498 if ( literal->value() == QLatin1String(
"geometry" ) || literal->value() == QLatin1String(
"feature" ) )
9515 QgsExpressionNode *argNode = node->args()->at( 0 );
9517 if ( argNode->isStatic( parent, context ) )
9519 QString expString = argNode->eval( parent, context ).toString();
9521 QgsExpression e( expString );
9523 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9530 functions << evalTemplateFunction;
9538 QgsExpressionNode *argNode = node->args()->at( 0 );
9540 if ( argNode->isStatic( parent, context ) )
9542 QString expString = argNode->eval( parent, context ).toString();
9544 QgsExpression e( expString );
9546 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9554 functions << evalFunc;
9560 const QList< QgsExpressionNode *> argList = node->
args()->list();
9563 if ( !argNode->
isStatic( parent, context ) )
9575 functions << attributeFunc;
9586 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array" ), -1, fcnArray, QStringLiteral(
"Arrays" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
9635 fcnMapPrefixKeys, QStringLiteral(
"Maps" ) )
9637 fcnMapToHtmlTable, QStringLiteral(
"Maps" ) )
9639 fcnMapToHtmlDefinitionList, QStringLiteral(
"Maps" ) )
9641 fcnToFormUrlEncode, QStringLiteral(
"Maps" ) )
9650 *sOwnedFunctions() << func;
9651 *sBuiltinFunctions() << func->name();
9652 sBuiltinFunctions()->append( func->aliases() );
9666 QMutexLocker locker( &sFunctionsMutex );
9667 sFunctions()->append( function );
9668 if ( transferOwnership )
9669 sOwnedFunctions()->append( function );
9684 QMutexLocker locker( &sFunctionsMutex );
9685 sFunctions()->removeAt( fnIdx );
9686 sFunctionIndexMap.clear();
9694 qDeleteAll( *sOwnedFunctions() );
9695 sOwnedFunctions()->clear();
9700 if ( sBuiltinFunctions()->isEmpty() )
9704 return *sBuiltinFunctions();
9711 QStringLiteral(
"Arrays" ) )
9722 if ( args->
count() < 2 )
9725 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9735 QVariantList result;
9737 if ( args->
count() < 2 )
9741 QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9744 std::unique_ptr< QgsExpressionContext > tempContext;
9747 tempContext = std::make_unique< QgsExpressionContext >();
9748 subContext = tempContext.get();
9755 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it, ++i )
9759 result << args->
at( 1 )->
eval( parent, subContext );
9784 if ( args->
count() < 2 )
9788 args->
at( 0 )->
prepare( parent, context );
9792 subContext = *context;
9799 args->
at( 1 )->
prepare( parent, &subContext );
9809 QStringLiteral(
"Arrays" ) )
9820 if ( args->
count() < 2 )
9823 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9833 QVariantList result;
9835 if ( args->
count() < 2 )
9839 const QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9842 std::unique_ptr< QgsExpressionContext > tempContext;
9845 tempContext = std::make_unique< QgsExpressionContext >();
9846 subContext = tempContext.get();
9853 if ( args->
count() >= 3 )
9855 const QVariant limitVar = args->
at( 2 )->
eval( parent, context );
9857 if ( QgsExpressionUtils::isIntSafe( limitVar ) )
9859 limit = limitVar.toInt();
9867 for (
const QVariant &value : array )
9870 if ( args->
at( 1 )->
eval( parent, subContext ).toBool() )
9874 if ( limit > 0 && limit == result.size() )
9901 if ( args->
count() < 2 )
9905 args->
at( 0 )->
prepare( parent, context );
9909 subContext = *context;
9915 args->
at( 1 )->
prepare( parent, &subContext );
9924 QStringLiteral(
"General" ) )
9935 if ( args->
count() < 3 )
9939 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9941 QVariant
name = args->
at( 0 )->
eval( parent, context );
9942 QVariant value = args->
at( 1 )->
eval( parent, context );
9945 appendTemporaryVariable( context,
name.toString(), value );
9946 if ( args->
at( 2 )->
isStatic( parent, context ) )
9948 popTemporaryVariable( context );
9959 if ( args->
count() < 3 )
9963 QVariant
name = args->
at( 0 )->
eval( parent, context );
9964 QVariant value = args->
at( 1 )->
eval( parent, context );
9967 std::unique_ptr< QgsExpressionContext > tempContext;
9968 if ( !updatedContext )
9970 tempContext = std::make_unique< QgsExpressionContext >();
9971 updatedContext = tempContext.get();
9974 appendTemporaryVariable( updatedContext,
name.toString(), value );
9975 result = args->
at( 2 )->
eval( parent, updatedContext );
9978 popTemporaryVariable( updatedContext );
9999 if ( args->
count() < 3 )
10004 QVariant value = args->
at( 1 )->
prepare( parent, context );
10007 std::unique_ptr< QgsExpressionContext > tempContext;
10008 if ( !updatedContext )
10010 tempContext = std::make_unique< QgsExpressionContext >();
10011 updatedContext = tempContext.get();
10014 appendTemporaryVariable( updatedContext,
name.toString(), value );
10015 args->
at( 2 )->
prepare( parent, updatedContext );
10018 popTemporaryVariable( updatedContext );
10023void QgsWithVariableExpressionFunction::popTemporaryVariable(
const QgsExpressionContext *context )
const
10026 delete updatedContext->
popScope();
10029void QgsWithVariableExpressionFunction::appendTemporaryVariable(
const QgsExpressionContext *context,
const QString &name,
const QVariant &value )
const
@ Left
Buffer to left of line.
DashPatternSizeAdjustment
Dash pattern size adjustment options.
@ ScaleDashOnly
Only dash lengths are adjusted.
@ ScaleBothDashAndGap
Both the dash and gap lengths are adjusted equally.
@ ScaleGapOnly
Only gap lengths are adjusted.
@ Success
Operation succeeded.
@ Visvalingam
The simplification gives each point in a line an importance weighting, so that least important points...
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
JoinStyle
Join styles for buffers.
@ Bevel
Use beveled joins.
@ Round
Use rounded joins.
@ Miter
Use mitered joins.
RasterBandStatistic
Available raster band statistics.
@ StdDev
Standard deviation.
@ NoStatistic
No statistic.
@ Group
Composite group layer. Added in QGIS 3.24.
@ Plugin
Plugin based layer.
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
EndCapStyle
End cap styles for buffers.
@ Flat
Flat cap (in line with start/end of line)
@ Square
Square cap (extends past start/end of line by buffer distance)
Aggregate
Available aggregates to calculate.
@ StringMinimumLength
Minimum length of string (string fields only)
@ FirstQuartile
First quartile (numeric fields only)
@ Mean
Mean of values (numeric fields only)
@ Median
Median of values (numeric fields only)
@ StringMaximumLength
Maximum length of string (string fields only)
@ Range
Range of values (max - min) (numeric and datetime fields only)
@ StringConcatenateUnique
Concatenate unique values with a joining string (string fields only). Specify the delimiter using set...
@ Minority
Minority of values.
@ CountMissing
Number of missing (null) values.
@ ArrayAggregate
Create an array of values.
@ Majority
Majority of values.
@ StDevSample
Sample standard deviation of values (numeric fields only)
@ ThirdQuartile
Third quartile (numeric fields only)
@ CountDistinct
Number of distinct values.
@ StringConcatenate
Concatenate values with a joining string (string fields only). Specify the delimiter using setDelimit...
@ GeometryCollect
Create a multipart geometry from aggregated geometries.
@ InterQuartileRange
Inter quartile range (IQR) (numeric fields only)
DashPatternLineEndingRule
Dash pattern line ending rules.
@ HalfDash
Start or finish the pattern with a half length dash.
@ HalfGap
Start or finish the pattern with a half length gap.
@ FullGap
Start or finish the pattern with a full gap.
@ FullDash
Start or finish the pattern with a full dash.
MakeValidMethod
Algorithms to use when repairing invalid geometries.
@ Linework
Combines all rings into a set of noded lines and then extracts valid polygons from that linework.
@ Structure
Structured method, first makes all rings valid and then merges shells and subtracts holes from shells...
@ GeometryCollection
GeometryCollection.
Abstract base class for all geometries.
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
virtual QgsAbstractGeometry * boundary() const =0
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
virtual const QgsAbstractGeometry * simplifiedTypeRef() const
Returns a reference to the simplest lossless representation of this geometry, e.g.
bool isMeasure() const
Returns true if the geometry contains m values.
virtual QgsRectangle boundingBox() const
Returns the minimal bounding box for the geometry.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
part_iterator parts_end()
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
virtual double length() const
Returns the planar, 2-dimensional length of the geometry.
virtual QgsCoordinateSequence coordinateSequence() const =0
Retrieves the sequence of geometries, rings and nodes.
virtual int partCount() const =0
Returns count of parts contained in the geometry.
part_iterator parts_begin()
Returns STL-style iterator pointing to the first part of the geometry.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
static Qgis::Aggregate stringToAggregate(const QString &string, bool *ok=nullptr)
Converts a string to a aggregate type.
static QgsFieldFormatterRegistry * fieldFormatterRegistry()
Gets the registry of available field formatters.
Handles the array_filter(array, expression) expression function.
QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Returns result of evaluating the function.
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Evaluates the function, first evaluating all required arguments before passing them to the function's...
QgsArrayFilterExpressionFunction()
Handles the array loopingarray_Foreach(array, expression) expression function.
QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Returns result of evaluating the function.
QgsArrayForeachExpressionFunction()
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Evaluates the function, first evaluating all required arguments before passing them to the function's...
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
Abstract base class for color ramps.
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QString toProj() const
Returns a Proj string representation of this CRS.
QString ellipsoidAcronym() const
Returns the ellipsoid acronym for the ellipsoid used by the CRS.
Qgis::DistanceUnit mapUnits
Contains information about the context in which a coordinate transform is executed.
Custom exception class for Coordinate Reference System related exceptions.
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
bool isEmpty() const override
Returns true if the geometry is empty.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
double area() const override
Returns the planar, 2-dimensional area of the geometry.
double roundness() const
Returns the roundness of the curve polygon.
int ringCount(int part=0) const override
Returns the number of rings of which this geometry is built.
Abstract base class for curved geometry type.
double sinuosity() const
Returns the curve sinuosity, which is the ratio of the curve length() to curve straightDistance2d().
QgsCurve * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
virtual QgsCurve * curveSubstring(double startDistance, double endDistance) const =0
Returns a new curve representing a substring of this curve.
virtual bool isClosed() const
Returns true if the curve is closed.
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
double straightDistance2d() const
Returns the straight distance of the curve, i.e.
virtual QgsCurve * reversed() const =0
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
double measureArea(const QgsGeometry &geometry) const
Measures the area of a geometry.
double convertLengthMeasurement(double length, Qgis::DistanceUnit toUnits) const
Takes a length measurement calculated by this QgsDistanceArea object and converts it to a different d...
double measurePerimeter(const QgsGeometry &geometry) const
Measures the perimeter of a polygon geometry.
double measureLength(const QgsGeometry &geometry) const
Measures the length of a geometry.
double bearing(const QgsPointXY &p1, const QgsPointXY &p2) const
Computes the bearing (in radians) between two points.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
double convertAreaMeasurement(double area, Qgis::AreaUnit toUnits) const
Takes an area measurement calculated by this QgsDistanceArea object and converts it to a different ar...
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
bool isStatic(const QString &name) const
Tests whether the variable with the specified name is static and can be cached.
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
static void registerContextFunctions()
Registers all known core functions provided by QgsExpressionContextScope objects.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
void setCachedValue(const QString &key, const QVariant &value) const
Sets a value to cache within the expression context.
QString uniqueHash(bool &ok, const QSet< QString > &variables=QSet< QString >()) const
Returns a unique hash representing the current state of the context.
QgsGeometry geometry() const
Convenience function for retrieving the geometry for the context, if set.
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
QgsExpressionContextScope * activeScopeForVariable(const QString &name)
Returns the currently active scope from the context for a specified variable name.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly by the expression to check if evaluation sh...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
bool hasGeometry() const
Returns true if the context has a geometry associated with it.
bool hasCachedValue(const QString &key) const
Returns true if the expression context contains a cached value with a matching key.
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
QVariant cachedValue(const QString &key) const
Returns the matching cached value, if set.
bool hasFeature() const
Returns true if the context has a feature associated with it.
QgsFields fields() const
Convenience function for retrieving the fields for the context, if set.
Represents a single parameter passed to a function.
A abstract base class for defining QgsExpression functions.
QList< QgsExpressionFunction::Parameter > ParameterList
List of parameters, used for function definition.
bool operator==(const QgsExpressionFunction &other) const
virtual bool isDeprecated() const
Returns true if the function is deprecated and should not be presented as a valid option to users in ...
virtual bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
Will be called during prepare to determine if the function is static.
virtual QStringList aliases() const
Returns a list of possible aliases for the function.
bool lazyEval() const
true if this function should use lazy evaluation.
static bool allParamsStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context)
This will return true if all the params for the provided function node are static within the constrai...
QString name() const
The name of the function.
virtual QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
Evaluates the function, first evaluating all required arguments before passing them to the function's...
virtual QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)=0
Returns result of evaluating the function.
virtual QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const
Returns a set of field names which are required for this function.
virtual bool handlesNull() const
Returns true if the function handles NULL values in arguments by itself, and the default NULL value h...
virtual bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
This will be called during the prepare step() of an expression if it is not static.
virtual bool usesGeometry(const QgsExpressionNodeFunction *node) const
Does this function use a geometry object.
An expression node which takes it value from a feature's field.
QString name() const
The name of the column.
An expression node for expression functions.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
An expression node for literal values.
A list of expression nodes.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
QgsExpressionNode * at(int i)
Gets the node at position i in the list.
int count() const
Returns the number of nodes in the list.
Abstract base class for all nodes that can appear in an expression.
virtual QString dump() const =0
Dump this node into a serialized (part) of an expression.
QVariant eval(QgsExpression *parent, const QgsExpressionContext *context)
Evaluate this node with the given context and parent.
virtual bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const =0
Returns true if this node can be evaluated for a static value.
bool prepare(QgsExpression *parent, const QgsExpressionContext *context)
Prepare this node for evaluation.
virtual QSet< QString > referencedColumns() const =0
Abstract virtual method which returns a list of columns required to evaluate this node.
virtual QSet< QString > referencedVariables() const =0
Returns a set of all variables which are used in this expression.
A set of expression-related functions.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
static const QList< QgsExpressionFunction * > & Functions()
QString expression() const
Returns the original, unmodified expression string.
static void cleanRegisteredFunctions()
Deletes all registered functions whose ownership have been transferred to the expression engine.
Qgis::DistanceUnit distanceUnits() const
Returns the desired distance units for calculations involving geomCalculator(), e....
static bool registerFunction(QgsExpressionFunction *function, bool transferOwnership=false)
Registers a function to the expression engine.
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
static const QStringList & BuiltinFunctions()
static QString replaceExpressionText(const QString &action, const QgsExpressionContext *context, const QgsDistanceArea *distanceArea=nullptr)
This function replaces each expression between [% and %] in the string with the result of its evaluat...
static PRIVATE QString helpText(QString name)
Returns the help text for a specified function.
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value, QMetaType::Type fieldType=QMetaType::Type::UnknownType)
Create an expression allowing to evaluate if a field is equal to a value.
static bool unregisterFunction(const QString &name)
Unregisters a function from the expression engine.
Qgis::AreaUnit areaUnits() const
Returns the desired areal units for calculations involving geomCalculator(), e.g.,...
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions)
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QVariant evaluate()
Evaluate the feature and return the result.
QgsDistanceArea * geomCalculator()
Returns calculator used for distance and area calculations (used by $length, $area and $perimeter fun...
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
Represents a list of OrderByClauses, with the most important first and the least important last.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsFeatureRequest & setRequestMayBeNested(bool requestMayBeNested)
In case this request may be run nested within another already running iteration on the same connectio...
QgsFeatureRequest & setTimeout(int timeout)
Sets the timeout (in milliseconds) for the maximum time we should wait during feature requests before...
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
void setFeedback(QgsFeedback *feedback)
Attach a feedback object that can be queried regularly by the iterator to check if it should be cance...
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Sets the feature ID that should be fetched.
QgsVectorLayer * materialize(const QgsFeatureRequest &request, QgsFeedback *feedback=nullptr)
Materializes a request (query) made against this feature source, by running it over the source and re...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
bool isValid() const
Returns the validity of this feature.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
ConstraintStrength
Strength of constraints.
@ ConstraintStrengthNotSet
Constraint is not set.
@ ConstraintStrengthSoft
User is warned if constraint is violated but feature can still be accepted.
@ ConstraintStrengthHard
Constraint must be honored before feature can be accepted.
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Container of fields for a vector layer.
Q_INVOKABLE int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
int size() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
virtual bool removeGeometry(int nr)
Removes a geometry from the collection.
QgsGeometryCollection * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
int partCount() const override
Returns count of parts contained in the geometry.
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
static QVector< QgsLineString * > extractLineStrings(const QgsAbstractGeometry *geom)
Returns list of linestrings extracted from the passed geometry.
A geometry is the spatial representation of a feature.
double hausdorffDistanceDensify(const QgsGeometry &geom, double densifyFraction) const
Returns the Hausdorff distance between this geometry and geom.
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Returns a copy of the geometry which has been densified by adding the specified number of extra nodes...
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
double lineLocatePoint(const QgsGeometry &point) const
Returns a distance representing the location along this linestring of the closest point on this lines...
QgsGeometry difference(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing the points making up this geometry that do not make up other.
double length() const
Returns the planar, 2-dimensional length of geometry.
QgsGeometry offsetCurve(double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
QgsGeometry poleOfInaccessibility(double precision, double *distanceToBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
QgsGeometry squareWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs square waves along the boundary of the geometry, with the specified wavelength and amplitu...
QgsGeometry triangularWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs triangular waves along the boundary of the geometry, with the specified wavelength and amp...
bool vertexIdFromVertexNr(int number, QgsVertexId &id) const
Calculates the vertex ID from a vertex number.
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
bool touches(const QgsGeometry &geometry) const
Returns true if the geometry touches another geometry.
QgsGeometry applyDashPattern(const QVector< double > &pattern, Qgis::DashPatternLineEndingRule startRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternLineEndingRule endRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternSizeAdjustment adjustment=Qgis::DashPatternSizeAdjustment::ScaleBothDashAndGap, double patternOffset=0) const
Applies a dash pattern to a geometry, returning a MultiLineString geometry which is the input geometr...
QgsGeometry roundWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs rounded (sine-like) waves along the boundary of the geometry, with the specified wavelengt...
QgsGeometry nearestPoint(const QgsGeometry &other) const
Returns the nearest (closest) point on this geometry to another geometry.
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
static QgsGeometry fromMultiPolylineXY(const QgsMultiPolylineXY &multiline)
Creates a new geometry from a QgsMultiPolylineXY object.
QgsGeometry makeValid(Qgis::MakeValidMethod method=Qgis::MakeValidMethod::Linework, bool keepCollapsed=false) const
Attempts to make an invalid geometry valid without losing vertices.
QString lastError() const
Returns an error string referring to the last error encountered either when this geometry was created...
QgsGeometry combine(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing all the points in this geometry and other (a union geometry operation...
QgsGeometry variableWidthBufferByM(int segments) const
Calculates a variable width buffer for a (multi)linestring geometry, where the width at each node is ...
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
QgsMultiPointXY asMultiPoint() const
Returns the contents of the geometry as a multi-point.
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
bool disjoint(const QgsGeometry &geometry) const
Returns true if the geometry is disjoint of another geometry.
QVector< QgsGeometry > asGeometryCollection() const
Returns contents of the geometry as a list of geometries.
QgsGeometry roundWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized rounded (sine-like) waves along the boundary of the geometry,...
double distance(const QgsGeometry &geom) const
Returns the minimum distance between this geometry and another geometry.
QgsGeometry interpolate(double distance) const
Returns an interpolated point on the geometry at the specified distance.
QgsGeometry extrude(double x, double y)
Returns an extruded version of this geometry.
static QgsGeometry fromMultiPointXY(const QgsMultiPointXY &multipoint)
Creates a new geometry from a QgsMultiPointXY object.
QgsGeometry singleSidedBuffer(double distance, int segments, Qgis::BufferSide side, Qgis::JoinStyle joinStyle=Qgis::JoinStyle::Round, double miterLimit=2.0) const
Returns a single sided buffer for a (multi)line geometry.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
static Q_INVOKABLE QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
bool contains(const QgsPointXY *p) const
Returns true if the geometry contains the point p.
QgsGeometry forceRHR() const
Forces geometries to respect the Right-Hand-Rule, in which the area that is bounded by a polygon is t...
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
bool equals(const QgsGeometry &geometry) const
Test if this geometry is exactly equal to another geometry.
bool isGeosValid(Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const
Checks validity of the geometry using GEOS.
QgsGeometry taperedBuffer(double startWidth, double endWidth, int segments) const
Calculates a variable width buffer ("tapered buffer") for a (multi)curve geometry.
bool within(const QgsGeometry &geometry) const
Returns true if the geometry is completely within another geometry.
QgsGeometry orientedMinimumBoundingBox(double &area, double &angle, double &width, double &height) const
Returns the oriented minimum bounding box for the geometry, which is the smallest (by area) rotated r...
double area() const
Returns the planar, 2-dimensional area of the geometry.
bool isMultipart() const
Returns true if WKB of the geometry is of WKBMulti* type.
QgsGeometry centroid() const
Returns the center of mass of a geometry.
bool crosses(const QgsGeometry &geometry) const
Returns true if the geometry crosses another geometry.
double hausdorffDistance(const QgsGeometry &geom) const
Returns the Hausdorff distance between this geometry and geom.
QgsGeometry concaveHull(double targetPercent, bool allowHoles=false) const
Returns a possibly concave polygon that contains all the points in the geometry.
QgsGeometry convexHull() const
Returns the smallest convex polygon that contains all the points in the geometry.
QgsGeometry sharedPaths(const QgsGeometry &other) const
Find paths shared between the two given lineal geometries (this and other).
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
QgsGeometry intersection(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing the points shared by this geometry and other.
QgsGeometry symDifference(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing the points making up this geometry that do not make up other.
QgsGeometry minimalEnclosingCircle(QgsPointXY ¢er, double &radius, unsigned int segments=36) const
Returns the minimal enclosing circle for the geometry.
QgsGeometry mergeLines() const
Merges any connected lines in a LineString/MultiLineString geometry and converts them to single line ...
static QgsGeometry fromMultiPolygonXY(const QgsMultiPolygonXY &multipoly)
Creates a new geometry from a QgsMultiPolygonXY.
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
double distanceToVertex(int vertex) const
Returns the distance along this geometry from its first vertex to the specified vertex.
QgsAbstractGeometry::const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
QgsGeometry forcePolygonClockwise() const
Forces geometries to respect the exterior ring is clockwise, interior rings are counter-clockwise con...
static QgsGeometry createWedgeBuffer(const QgsPoint ¢er, double azimuth, double angularWidth, double outerRadius, double innerRadius=0)
Creates a wedge shaped buffer from a center point.
QgsGeometry extendLine(double startDistance, double endDistance) const
Extends a (multi)line geometry by extrapolating out the start or end of the line by a specified dista...
QgsGeometry triangularWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized triangular waves along the boundary of the geometry, with the specified wavelen...
QgsGeometry squareWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized square waves along the boundary of the geometry, with the specified wavelength ...
QgsGeometry simplify(double tolerance) const
Returns a simplified version of this geometry using a specified tolerance value.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Qgis::GeometryOperationResult rotate(double rotation, const QgsPointXY ¢er)
Rotate this geometry around the Z axis.
Qgis::GeometryOperationResult translate(double dx, double dy, double dz=0.0, double dm=0.0)
Translates this geometry by dx, dy, dz and dm.
double interpolateAngle(double distance) const
Returns the angle parallel to the linestring or polygon boundary at the specified distance along the ...
double angleAtVertex(int vertex) const
Returns the bisector angle for this geometry at the specified vertex.
QgsGeometry smooth(unsigned int iterations=1, double offset=0.25, double minimumDistance=-1.0, double maxAngle=180.0) const
Smooths a geometry by rounding off corners using the Chaikin algorithm.
QgsGeometry forcePolygonCounterClockwise() const
Forces geometries to respect the exterior ring is counter-clockwise, interior rings are clockwise con...
Q_INVOKABLE QString asWkt(int precision=17) const
Exports the geometry to WKT.
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
bool intersects(const QgsRectangle &rectangle) const
Returns true if this geometry exactly intersects with a rectangle.
QgsAbstractGeometry::vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
bool overlaps(const QgsGeometry &geometry) const
Returns true if the geometry overlaps another geometry.
QgsGeometry shortestLine(const QgsGeometry &other) const
Returns the shortest line joining this geometry to another geometry.
Does vector analysis using the GEOS library and handles import, export, and exception handling.
std::unique_ptr< QgsAbstractGeometry > maximumInscribedCircle(double tolerance, QString *errorMsg=nullptr) const
Returns the maximum inscribed circle.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
Represents a color stop within a QgsGradientColorRamp color ramp.
A representation of the interval between two datetime values.
bool isValid() const
Returns true if the interval is valid.
double days() const
Returns the interval duration in days.
double weeks() const
Returns the interval duration in weeks.
double months() const
Returns the interval duration in months (based on a 30 day month).
double seconds() const
Returns the interval duration in seconds.
double years() const
Returns the interval duration in years (based on an average year length)
double hours() const
Returns the interval duration in hours.
double minutes() const
Returns the interval duration in minutes.
Line string geometry type, with support for z-dimension and m-values.
bool lineLocatePointByM(double m, double &x, double &y, double &z, double &distanceFromStart, bool use3DDistance=true) const
Attempts to locate a point on the linestring by m value.
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
QString dataUrl() const
Returns the DataUrl of the layer used by QGIS Server in GetCapabilities request.
QString attributionUrl() const
Returns the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Base class for all map layer types.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QString source() const
Returns the source for the layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
QgsCoordinateReferenceSystem crs
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
QgsLayerMetadata metadata
QString publicSource(bool hidePassword=false) const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
virtual bool isEditable() const
Returns true if the layer can be edited.
double minimumScale() const
Returns the minimum map scale (i.e.
virtual Q_INVOKABLE QgsDataProvider * dataProvider()
Returns the layer's data provider, it may be nullptr.
double maximumScale() const
Returns the maximum map scale (i.e.
Implementation of GeometrySimplifier using the "MapToPixel" algorithm.
@ SimplifyGeometry
The geometries can be simplified using the current map2pixel context state.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
Multi line string geometry collection.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
Multi point geometry collection.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
Custom exception class which is raised when an operation is not supported.
static QgsGeometry geometryFromGML(const QString &xmlString, const QgsOgcUtils::Context &context=QgsOgcUtils::Context())
Static method that creates geometry from GML.
A class to represent a 2D point.
bool isEmpty() const
Returns true if the geometry is empty.
Point geometry type, with support for z-dimension and m-values.
double inclination(const QgsPoint &other) const
Calculates Cartesian inclination between this point and other one (starting from zenith = 0 to nadir ...
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override
Checks validity of the geometry, and returns true if the geometry is valid.
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which corresponds to this point projected by a specified distance with specified ...
QgsRelationManager * relationManager
static QgsProject * instance()
Returns the QgsProject singleton instance.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
Quadrilateral geometry type.
static QgsQuadrilateral squareFromDiagonal(const QgsPoint &p1, const QgsPoint &p2)
Construct a QgsQuadrilateral as a square from a diagonal.
QgsPolygon * toPolygon(bool force2D=false) const
Returns the quadrilateral as a new polygon.
static QgsQuadrilateral rectangleFrom3Points(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &p3, ConstructionOption mode)
Construct a QgsQuadrilateral as a Rectangle from 3 points.
ConstructionOption
A quadrilateral can be constructed from 3 points where the second distance can be determined by the t...
@ Distance
Second distance is equal to the distance between 2nd and 3rd point.
@ Projected
Second distance is equal to the distance of the perpendicular projection of the 3rd point on the segm...
The Field class represents a Raster Attribute Table field, including its name, usage and type.
The RasterBandStats struct is a container for statistics about a single raster band.
double mean
The mean cell value for the band. NO_DATA values are excluded.
double stdDev
The standard deviation of the cell values.
double minimumValue
The minimum cell value in the raster band.
double sum
The sum of all cells in the band. NO_DATA values are excluded.
double maximumValue
The maximum cell value in the raster band.
double range
The range is the distance between min & max.
A rectangle specified with double values.
void grow(double delta)
Grows the rectangle in place by the specified amount.
Regular Polygon geometry type.
ConstructionOption
A regular polygon can be constructed inscribed in a circle or circumscribed about a circle.
@ CircumscribedCircle
Circumscribed about a circle (the radius is the distance from the center to the midpoints of the side...
@ InscribedCircle
Inscribed in a circle (the radius is the distance between the center and vertices)
QgsPolygon * toPolygon() const
Returns as a polygon.
QList< QgsRelation > relationsByName(const QString &name) const
Returns a list of relations with matching names.
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id.
Represents a relationship between two vector layers.
QgsVectorLayer * referencedLayer
QgsVectorLayer * referencingLayer
QString getRelatedFeaturesFilter(const QgsFeature &feature) const
Returns a filter expression which returns all the features on the referencing (child) layer which hav...
A spatial index for QgsFeature objects.
@ FlagStoreFeatureGeometries
Indicates that the spatial index should also store feature geometries. This requires more memory,...
QList< QgsFeatureId > nearestNeighbor(const QgsPointXY &point, int neighbors=1, double maxDistance=0) const
Returns nearest neighbors to a point.
QList< QgsFeatureId > intersects(const QgsRectangle &rectangle) const
Returns a list of features with a bounding box which intersects the specified rectangle.
static QString quotedIdentifier(const QString &identifier)
Returns a properly quoted version of identifier.
static QString quotedValue(const QVariant &value)
Returns a properly quoted and escaped version of value for use in SQL strings.
c++ helper class for defining QgsExpression functions.
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
void setIsStaticFunction(const std::function< bool(const QgsExpressionNodeFunction *, QgsExpression *, const QgsExpressionContext *) > &isStatic)
Set a function that will be called in the prepare step to determine if the function is static or not.
QStringList aliases() const override
Returns a list of possible aliases for the function.
void setPrepareFunction(const std::function< bool(const QgsExpressionNodeFunction *, QgsExpression *, const QgsExpressionContext *)> &prepareFunc)
Set a function that will be called in the prepare step to determine if the function is static or not.
void setUsesGeometryFunction(const std::function< bool(const QgsExpressionNodeFunction *node)> &usesGeometry)
Set a function that will be called when determining if the function requires feature geometry or not.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
void setIsStatic(bool isStatic)
Tag this function as either static or not static.
QgsStaticExpressionFunction(const QString &fnname, int params, FcnEval fcn, const QString &group, const QString &helpText=QString(), bool usesGeometry=false, const QSet< QString > &referencedColumns=QSet< QString >(), bool lazyEval=false, const QStringList &aliases=QStringList(), bool handlesNull=false)
Static function for evaluation against a QgsExpressionContext, using an unnamed list of parameter val...
QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const override
Returns a set of field names which are required for this function.
bool usesGeometry(const QgsExpressionNodeFunction *node) const override
Does this function use a geometry object.
Utility functions for working with strings.
static int hammingDistance(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the Hamming distance between two strings.
static QString soundex(const QString &string)
Returns the Soundex representation of a string.
static int levenshteinDistance(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the Levenshtein edit distance between two strings.
static QString longestCommonSubstring(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the longest common substring between two strings.
static QString wordWrap(const QString &string, int length, bool useMaxLineLength=true, const QString &customDelimiter=QString())
Automatically wraps a string by inserting new line characters at appropriate locations in the string.
const QgsColorRamp * colorRampRef(const QString &name) const
Returns a const pointer to a symbol (doesn't create new instance)
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Contains utility functions for working with symbols and symbol layers.
static QColor decodeColor(const QString &str)
static QString encodeColor(const QColor &color)
static bool runOnMainThread(const Func &func, QgsFeedback *feedback=nullptr)
Guarantees that func is executed on the main thread.
This class allows including a set of layers in a database-side transaction, provided the layer data p...
virtual bool executeSql(const QString &sql, QString &error, bool isDirty=false, const QString &name=QString())=0
Execute the sql string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
virtual QgsTransaction * transaction() const
Returns the transaction this data provider is included in, if any.
static bool validateAttribute(const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors, QgsFieldConstraints::ConstraintStrength strength=QgsFieldConstraints::ConstraintStrengthNotSet, QgsFieldConstraints::ConstraintOrigin origin=QgsFieldConstraints::ConstraintOriginNotSet)
Tests a feature attribute value to check whether it passes all constraints which are present on the c...
Represents a vector layer which manages a vector based data sets.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QVariant aggregate(Qgis::Aggregate aggregate, const QString &fieldOrExpression, const QgsAggregateCalculator::AggregateParameters ¶meters=QgsAggregateCalculator::AggregateParameters(), QgsExpressionContext *context=nullptr, bool *ok=nullptr, QgsFeatureIds *fids=nullptr, QgsFeedback *feedback=nullptr, QString *error=nullptr) const
Calculates an aggregated value from the layer's features.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QString displayExpression
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
QgsEditorWidgetSetup editorWidgetSetup(int index) const
Returns the editor widget setup for the field at the specified index.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
Q_INVOKABLE QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.
Handles the with_variable(name, value, node) expression function.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
QgsWithVariableExpressionFunction()
QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Evaluates the function, first evaluating all required arguments before passing them to the function's...
QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Returns result of evaluating the function.
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
static QString geometryDisplayString(Qgis::GeometryType type)
Returns a display string for a geometry type.
static bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
Unique pointer for sqlite3 databases, which automatically closes the database when the pointer goes o...
sqlite3_statement_unique_ptr prepare(const QString &sql, int &resultCode) const
Prepares a sql statement, returning the result.
QString errorMessage() const
Returns the most recent error message encountered by the database.
int open_v2(const QString &path, int flags, const char *zVfs)
Opens the database at the specified file path.
int exec(const QString &sql, QString &errorMessage) const
Executes the sql command in the database.
Unique pointer for sqlite3 prepared statements, which automatically finalizes the statement when the ...
int step()
Steps to the next record in the statement, returning the sqlite3 result code.
qlonglong columnAsInt64(int column) const
Gets column value from the current statement row as a long long integer (64 bits).
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
CORE_EXPORT QString build(const QVariantMap &map)
Build a hstore-formatted string from a QVariantMap.
CORE_EXPORT QVariantMap parse(const QString &string)
Returns a QVariantMap object containing the key and values from a hstore-formatted string.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QVector< QgsRingSequence > QgsCoordinateSequence
QVector< QgsPointSequence > QgsRingSequence
QVector< QgsPoint > QgsPointSequence
QList< QgsGradientStop > QgsGradientStopsList
List of gradient stops.
Q_DECLARE_METATYPE(QgsDatabaseQueryLogEntry)
Q_GLOBAL_STATIC(QReadWriteLock, sDefinitionCacheLock)
QList< QgsExpressionFunction * > ExpressionFunctionList
QVariant fcnRampColor(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
#define ENSURE_GEOM_TYPE(f, g, geomtype)
QVariant fcnRampColorObject(const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction *)
bool(QgsGeometry::* RelationFunction)(const QgsGeometry &geometry) const
#define ENSURE_NO_EVAL_ERROR
#define FEAT_FROM_CONTEXT(c, f)
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
QVector< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
QLineF segment(int index, QRectF rect, double radius)
const QgsCoordinateReferenceSystem & crs
A bundle of parameters controlling aggregate calculation.
QString filter
Optional filter for calculating aggregate over a subset of features, or an empty string to use all fe...
QString delimiter
Delimiter to use for joining values with the StringConcatenate aggregate.
QgsFeatureRequest::OrderBy orderBy
Optional order by clauses.
Single variable definition for use within a QgsExpressionContextScope.
The Context struct stores the current layer and coordinate transform context.
const QgsMapLayer * layer
QgsCoordinateTransformContext transformContext
Utility class for identifying a unique vertex within a geometry.