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();
1554 const QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1555 const qlonglong number = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1556 return string.repeated( std::max(
static_cast< int >( number ), 0 ) );
1561 if ( values.count() == 2 && values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
1563 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1564 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
1565 QVector< QPair< QString, QString > > mapItems;
1567 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
1569 mapItems.append( qMakePair( it.key(), it.value().toString() ) );
1573 std::sort( mapItems.begin(),
1575 [](
const QPair< QString, QString > &pair1,
1576 const QPair< QString, QString > &pair2 )
1578 return ( pair1.first.length() > pair2.first.length() );
1581 for (
auto it = mapItems.constBegin(); it != mapItems.constEnd(); ++it )
1583 str = str.replace( it->first, it->second );
1586 return QVariant( str );
1588 else if ( values.count() == 3 )
1590 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1591 QVariantList before;
1593 bool isSingleReplacement =
false;
1595 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).userType() != QMetaType::Type::QStringList )
1597 before = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1601 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
1604 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
1606 after = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1607 isSingleReplacement =
true;
1611 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
1614 if ( !isSingleReplacement && before.length() != after.length() )
1616 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
1620 for (
int i = 0; i < before.length(); i++ )
1622 str = str.replace( before.at( i ).toString(), after.at( isSingleReplacement ? 0 : i ).toString() );
1625 return QVariant( str );
1629 parent->
setEvalErrorString( QObject::tr(
"Function replace requires 2 or 3 arguments" ) );
1636 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1637 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1638 QString after = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1640 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1641 if ( !re.isValid() )
1643 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1646 return QVariant( str.replace( re, after ) );
1651 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1652 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1654 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1655 if ( !re.isValid() )
1657 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1660 return QVariant( ( str.indexOf( re ) + 1 ) );
1665 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1666 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1667 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1669 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1670 if ( !re.isValid() )
1672 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1676 QRegularExpressionMatch matches = re.match( str );
1677 if ( matches.hasMatch() )
1680 QStringList list = matches.capturedTexts();
1683 for ( QStringList::const_iterator it = ++list.constBegin(); it != list.constEnd(); ++it )
1685 array += ( !( *it ).isEmpty() ) ? *it : empty;
1688 return QVariant( array );
1698 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1699 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1701 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1702 if ( !re.isValid() )
1704 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1709 QRegularExpressionMatch match = re.match( str );
1710 if ( match.hasMatch() )
1713 if ( match.lastCapturedIndex() > 0 )
1716 return QVariant( match.captured( 1 ) );
1721 return QVariant( match.captured( 0 ) );
1726 return QVariant(
"" );
1732 QString uuid = QUuid::createUuid().toString();
1733 if ( values.at( 0 ).toString().compare( QStringLiteral(
"WithoutBraces" ), Qt::CaseInsensitive ) == 0 )
1734 uuid = QUuid::createUuid().toString( QUuid::StringFormat::WithoutBraces );
1735 else if ( values.at( 0 ).toString().compare( QStringLiteral(
"Id128" ), Qt::CaseInsensitive ) == 0 )
1736 uuid = QUuid::createUuid().toString( QUuid::StringFormat::Id128 );
1742 if ( !values.at( 0 ).isValid() || !values.at( 1 ).isValid() )
1745 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1746 int from = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1749 if ( values.at( 2 ).isValid() )
1750 len = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
1756 from = str.size() + from;
1762 else if ( from > 0 )
1770 len = str.size() + len - from;
1777 return QVariant( str.mid( from, len ) );
1782 return QVariant( f.
id() );
1787 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1788 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
1789 bool foundLayer =
false;
1790 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, geom](
QgsMapLayer * mapLayer )
1792 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer * >( mapLayer );
1793 if ( !layer || !layer->dataProvider() )
1795 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1799 if ( bandNb < 1 || bandNb > layer->bandCount() )
1801 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster band number." ) );
1807 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid point geometry." ) );
1815 if ( multiPoint.count() == 1 )
1817 point = multiPoint[0];
1826 double value = layer->dataProvider()->sample( point, bandNb );
1827 return std::isnan( value ) ? QVariant() : value;
1833 parent->
setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1844 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1845 const double value = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1847 bool foundLayer =
false;
1848 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, value](
QgsMapLayer * mapLayer )-> QVariant
1850 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer *>( mapLayer );
1851 if ( !layer || !layer->dataProvider() )
1853 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1857 if ( bandNb < 1 || bandNb > layer->bandCount() )
1859 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster band number." ) );
1863 if ( std::isnan( value ) )
1865 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster value." ) );
1869 if ( ! layer->dataProvider()->attributeTable( bandNb ) )
1874 const QVariantList data = layer->dataProvider()->attributeTable( bandNb )->row( value );
1875 if ( data.isEmpty() )
1881 const QList<QgsRasterAttributeTable::Field> fields { layer->dataProvider()->attributeTable( bandNb )->fields() };
1882 for (
int idx = 0; idx < static_cast<int>( fields.count( ) ) && idx < static_cast<int>( data.count() ); ++idx )
1885 if ( field.isColor() || field.isRamp() )
1889 result.insert( fields.at( idx ).name, data.at( idx ) );
1897 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1918 if ( values.size() == 1 )
1920 attr = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1923 else if ( values.size() == 2 )
1925 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
1926 attr = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1930 parent->
setEvalErrorString( QObject::tr(
"Function `attribute` requires one or two parameters. %n given.",
nullptr, values.length() ) );
1939 QString table { R
"html(
1942 <tr><th>%1</th></tr>
1945 <tr><td>%2</td></tr>
1949 if ( values.size() == 1 )
1951 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1955 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_table` requires one parameter. %n given.",
nullptr, values.length() ) );
1959 if ( dict.isEmpty() )
1964 QStringList headers;
1967 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
1969 headers.push_back( it.key().toHtmlEscaped() );
1970 cells.push_back( it.value().toString( ).toHtmlEscaped() );
1973 return table.arg( headers.join( QLatin1String(
"</th><th>" ) ), cells.join( QLatin1String(
"</td><td>" ) ) );
1978 QString table { R
"html(
1983 if ( values.size() == 1 )
1985 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1989 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_dl` requires one parameter. %n given.",
nullptr, values.length() ) );
1993 if ( dict.isEmpty() )
2000 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
2002 rows.append( QStringLiteral(
"<dt>%1</dt><dd>%2</dd>" ).arg( it.key().toHtmlEscaped(), it.value().toString().toHtmlEscaped() ) );
2005 return table.arg( rows );
2013 layer = context->
variable( QStringLiteral(
"layer" ) );
2018 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
2020 layer = node->
eval( parent, context );
2031 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2035 const QString strength = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).toLower();
2036 if ( strength == QLatin1String(
"hard" ) )
2040 else if ( strength == QLatin1String(
"soft" ) )
2045 bool foundLayer =
false;
2046 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
2048 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2051 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2057 for (
int i = 0; i < fields.
size(); i++ )
2072 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2084 layer = context->
variable( QStringLiteral(
"layer" ) );
2089 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
2091 layer = node->
eval( parent, context );
2102 feature = QgsExpressionUtils::getFeature( values.at( 2 ), parent );
2106 const QString strength = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).toLower();
2107 if ( strength == QLatin1String(
"hard" ) )
2111 else if ( strength == QLatin1String(
"soft" ) )
2116 const QString attributeName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2118 bool foundLayer =
false;
2119 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, attributeName, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
2121 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2128 if ( fieldIndex == -1 )
2130 parent->
setEvalErrorString( QObject::tr(
"The attribute name did not match any field for the given feature" ) );
2141 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2157 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2162 for (
int i = 0; i < fields.
count(); ++i )
2176 if ( values.isEmpty() )
2179 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2181 else if ( values.size() == 1 )
2183 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2184 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2186 else if ( values.size() == 2 )
2188 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2189 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2193 parent->
setEvalErrorString( QObject::tr(
"Function `represent_attributes` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2200 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: layer could not be resolved." ) );
2206 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: feature could not be resolved." ) );
2212 for (
int fieldIndex = 0; fieldIndex < fields.
count(); ++fieldIndex )
2214 const QString fieldName { fields.
at( fieldIndex ).
name() };
2215 const QVariant attributeVal = feature.
attribute( fieldIndex );
2216 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer->
id(), fieldName, attributeVal.toString() );
2219 result.insert( fieldName, context->
cachedValue( cacheValueKey ) );
2228 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer->
id(), fieldName );
2240 QString value( fieldFormatter->
representValue( layer, fieldIndex, setup.
config(), cache, attributeVal ) );
2242 result.insert( fields.
at( fieldIndex ).
name(), value );
2258 bool evaluate =
true;
2262 if ( values.isEmpty() )
2265 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2267 else if ( values.size() == 1 )
2269 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2270 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2272 else if ( values.size() == 2 )
2274 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2275 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2277 else if ( values.size() == 3 )
2279 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2280 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2281 evaluate = values.value( 2 ).toBool();
2287 parent->
setEvalErrorString( QObject::tr(
"Function `maptip` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2291 parent->
setEvalErrorString( QObject::tr(
"Function `display` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2323 subContext.setFeature( feature );
2332 exp.prepare( &subContext );
2333 return exp.evaluate( &subContext ).toString();
2339 return fcnCoreFeatureMaptipDisplay( values, context, parent,
false );
2344 return fcnCoreFeatureMaptipDisplay( values, context, parent,
true );
2351 if ( values.isEmpty() )
2354 layer = context->
variable( QStringLiteral(
"layer" ) );
2356 else if ( values.size() == 1 )
2358 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2359 layer = context->
variable( QStringLiteral(
"layer" ) );
2361 else if ( values.size() == 2 )
2363 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2364 layer = values.at( 0 );
2368 parent->
setEvalErrorString( QObject::tr(
"Function `is_selected` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2372 bool foundLayer =
false;
2373 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [feature](
QgsMapLayer * mapLayer ) -> QVariant
2375 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2376 if ( !layer || !feature.
isValid() )
2393 if ( values.isEmpty() )
2394 layer = context->
variable( QStringLiteral(
"layer" ) );
2395 else if ( values.count() == 1 )
2396 layer = values.at( 0 );
2399 parent->
setEvalErrorString( QObject::tr(
"Function `num_selected` requires no more than one parameter. %n given.",
nullptr, values.length() ) );
2403 bool foundLayer =
false;
2404 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [](
QgsMapLayer * mapLayer ) -> QVariant
2406 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2422 static QMap<QString, qlonglong> counterCache;
2423 QVariant functionResult;
2425 auto fetchAndIncrementFunc = [ values, parent, &functionResult ](
QgsMapLayer * mapLayer,
const QString & databaseArgument )
2429 const QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( mapLayer );
2434 database = decodedUri.value( QStringLiteral(
"path" ) ).toString();
2435 if ( database.isEmpty() )
2437 parent->
setEvalErrorString( QObject::tr(
"Could not extract file path from layer `%1`." ).arg( layer->
name() ) );
2442 database = databaseArgument;
2445 const QString table = values.at( 1 ).toString();
2446 const QString idColumn = values.at( 2 ).toString();
2447 const QString filterAttribute = values.at( 3 ).toString();
2448 const QVariant filterValue = values.at( 4 ).toString();
2449 const QVariantMap defaultValues = values.at( 5 ).toMap();
2455 if ( sqliteDb.
open_v2( database, SQLITE_OPEN_READWRITE,
nullptr ) != SQLITE_OK )
2458 functionResult = QVariant();
2462 QString errorMessage;
2463 QString currentValSql;
2465 qlonglong nextId = 0;
2466 bool cachedMode =
false;
2467 bool valueRetrieved =
false;
2469 QString cacheString = QStringLiteral(
"%1:%2:%3:%4:%5" ).arg( database, table, idColumn, filterAttribute, filterValue.toString() );
2476 auto cachedCounter = counterCache.find( cacheString );
2478 if ( cachedCounter != counterCache.end() )
2480 qlonglong &cachedValue = cachedCounter.value();
2481 nextId = cachedValue;
2483 cachedValue = nextId;
2484 valueRetrieved =
true;
2489 if ( !cachedMode || !valueRetrieved )
2491 int result = SQLITE_ERROR;
2494 if ( !filterAttribute.isNull() )
2499 sqliteStatement = sqliteDb.
prepare( currentValSql, result );
2501 if ( result == SQLITE_OK )
2504 if ( sqliteStatement.
step() == SQLITE_ROW )
2510 if ( cachedMode && result == SQLITE_OK )
2512 counterCache.insert( cacheString, nextId );
2516 counterCache.remove( cacheString );
2519 valueRetrieved =
true;
2523 if ( valueRetrieved )
2532 if ( !filterAttribute.isNull() )
2538 for ( QVariantMap::const_iterator iter = defaultValues.constBegin(); iter != defaultValues.constEnd(); ++iter )
2541 vals << iter.value().toString();
2544 upsertSql += QLatin1String(
" (" ) + cols.join(
',' ) +
')';
2545 upsertSql += QLatin1String(
" VALUES " );
2546 upsertSql +=
'(' + vals.join(
',' ) +
')';
2548 int result = SQLITE_ERROR;
2552 if ( transaction->
executeSql( upsertSql, errorMessage ) )
2559 result = sqliteDb.
exec( upsertSql, errorMessage );
2561 if ( result == SQLITE_OK )
2563 functionResult = QVariant( nextId );
2568 parent->
setEvalErrorString( QStringLiteral(
"Could not increment value: SQLite error: \"%1\" (%2)." ).arg( errorMessage, QString::number( result ) ) );
2569 functionResult = QVariant();
2574 functionResult = QVariant();
2577 bool foundLayer =
false;
2578 QgsExpressionUtils::executeLambdaForMapLayer( values.at( 0 ), context, parent, [&fetchAndIncrementFunc](
QgsMapLayer * layer )
2580 fetchAndIncrementFunc( layer, QString() );
2584 const QString databasePath = values.at( 0 ).toString();
2587 fetchAndIncrementFunc(
nullptr, databasePath );
2591 return functionResult;
2604 QString definition = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2609 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to cordinate reference system" ).arg( definition ) );
2612 return QVariant::fromValue(
crs );
2618 for (
const QVariant &value : values )
2621 concat += QgsExpressionUtils::getStringValue( value, parent );
2628 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2629 return string.indexOf( QgsExpressionUtils::getStringValue( values.at( 1 ), parent ) ) + 1;
2634 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2635 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2636 return string.right( pos );
2641 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2642 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2643 return string.left( pos );
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.leftJustified( length, fill.at( 0 ),
true );
2656 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2657 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2658 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2659 return string.rightJustified( length, fill.at( 0 ),
true );
2664 if ( values.size() < 1 )
2666 parent->
setEvalErrorString( QObject::tr(
"Function format requires at least 1 argument" ) );
2670 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2671 for (
int n = 1; n < values.length(); n++ )
2673 string =
string.arg( QgsExpressionUtils::getStringValue( values.at( n ), parent ) );
2681 return QVariant( QDateTime::currentDateTime() );
2686 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2687 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2688 if ( format.isEmpty() && !language.isEmpty() )
2690 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Date when the language is specified" ) );
2691 return QVariant( QDate() );
2694 if ( format.isEmpty() && language.isEmpty() )
2695 return QVariant( QgsExpressionUtils::getDateValue( values.at( 0 ), parent ) );
2697 QString datestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2698 QLocale locale = QLocale();
2699 if ( !language.isEmpty() )
2701 locale = QLocale( language );
2704 QDate date = locale.toDate( datestring, format );
2705 if ( !date.isValid() )
2707 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Date" ).arg( datestring ) );
2710 return QVariant( date );
2715 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2716 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2717 if ( format.isEmpty() && !language.isEmpty() )
2719 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Time when the language is specified" ) );
2720 return QVariant( QTime() );
2723 if ( format.isEmpty() && language.isEmpty() )
2724 return QVariant( QgsExpressionUtils::getTimeValue( values.at( 0 ), parent ) );
2726 QString timestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2727 QLocale locale = QLocale();
2728 if ( !language.isEmpty() )
2730 locale = QLocale( language );
2733 QTime time = locale.toTime( timestring, format );
2734 if ( !time.isValid() )
2736 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Time" ).arg( timestring ) );
2739 return QVariant( time );
2744 return QVariant::fromValue( QgsExpressionUtils::getInterval( values.at( 0 ), parent ) );
2753 double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
2754 QString axis = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2755 int precision = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
2757 QString formatString;
2758 if ( values.count() > 3 )
2759 formatString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
2762 if ( formatString.compare( QLatin1String(
"suffix" ), Qt::CaseInsensitive ) == 0 )
2766 else if ( formatString.compare( QLatin1String(
"aligned" ), Qt::CaseInsensitive ) == 0 )
2770 else if ( ! formatString.isEmpty() )
2772 parent->
setEvalErrorString( QObject::tr(
"Invalid formatting parameter: '%1'. It must be empty, or 'suffix' or 'aligned'." ).arg( formatString ) );
2776 if ( axis.compare( QLatin1String(
"x" ), Qt::CaseInsensitive ) == 0 )
2780 else if ( axis.compare( QLatin1String(
"y" ), Qt::CaseInsensitive ) == 0 )
2786 parent->
setEvalErrorString( QObject::tr(
"Invalid axis name: '%1'. It must be either 'x' or 'y'." ).arg( axis ) );
2794 return floatToDegreeFormat( format, values, context, parent, node );
2801 value = QgsCoordinateUtils::dmsToDecimal( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), &ok );
2803 return ok ? QVariant( value ) : QVariant();
2809 return floatToDegreeFormat( format, values, context, parent, node );
2814 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2815 QDateTime d2 = QgsExpressionUtils::getDateTimeValue( values.at( 1 ), parent );
2816 qint64 seconds = d2.secsTo( d1 );
2817 return QVariant::fromValue(
QgsInterval( seconds ) );
2822 if ( !values.at( 0 ).canConvert<QDate>() )
2825 QDate date = QgsExpressionUtils::getDateValue( values.at( 0 ), parent );
2826 if ( !date.isValid() )
2831 return date.dayOfWeek() % 7;
2836 QVariant value = values.at( 0 );
2837 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2840 return QVariant( inter.
days() );
2844 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2845 return QVariant( d1.date().day() );
2851 QVariant value = values.at( 0 );
2852 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2855 return QVariant( inter.
years() );
2859 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2860 return QVariant( d1.date().year() );
2866 QVariant value = values.at( 0 );
2867 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2870 return QVariant( inter.
months() );
2874 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2875 return QVariant( d1.date().month() );
2881 QVariant value = values.at( 0 );
2882 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2885 return QVariant( inter.
weeks() );
2889 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2890 return QVariant( d1.date().weekNumber() );
2896 QVariant value = values.at( 0 );
2897 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2900 return QVariant( inter.
hours() );
2904 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2905 return QVariant( t1.hour() );
2911 QVariant value = values.at( 0 );
2912 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2915 return QVariant( inter.
minutes() );
2919 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2920 return QVariant( t1.minute() );
2926 QVariant value = values.at( 0 );
2927 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2930 return QVariant( inter.
seconds() );
2934 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2935 return QVariant( t1.second() );
2941 QDateTime dt = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2944 return QVariant( dt.toMSecsSinceEpoch() );
2954 long long millisecs_since_epoch = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
2956 return QVariant( QDateTime::fromMSecsSinceEpoch( millisecs_since_epoch ) );
2961 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2964 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif" ) ) );
2967 QString tag = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2973 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2976 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif_geotag" ) ) );
2983#define ENSURE_GEOM_TYPE(f, g, geomtype) \
2984 if ( !(f).hasGeometry() ) \
2985 return QVariant(); \
2986 QgsGeometry g = (f).geometry(); \
2987 if ( (g).type() != (geomtype) ) \
2994 if ( g.isMultipart() )
2996 return g.asMultiPoint().at( 0 ).x();
3000 return g.asPoint().x();
3008 if ( g.isMultipart() )
3010 return g.asMultiPoint().at( 0 ).y();
3014 return g.asPoint().y();
3028 if ( g.isEmpty() || !abGeom->
is3D() )
3033 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( g.constGet() );
3039 if (
const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( g.constGet() ) )
3041 if ( collection->numGeometries() > 0 )
3043 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3054 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3060 return QVariant( isValid );
3065 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3069 const QString methodString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).trimmed();
3070#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
3075 if ( methodString.compare( QLatin1String(
"linework" ), Qt::CaseInsensitive ) == 0 )
3077 else if ( methodString.compare( QLatin1String(
"structure" ), Qt::CaseInsensitive ) == 0 )
3080 const bool keepCollapsed = values.value( 2 ).toBool();
3085 valid = geom.
makeValid( method, keepCollapsed );
3089 parent->
setEvalErrorString( QObject::tr(
"The make_valid parameters require a newer GEOS library version" ) );
3093 return QVariant::fromValue( valid );
3098 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3104 for (
int i = 0; i < multiGeom.size(); ++i )
3106 array += QVariant::fromValue( multiGeom.at( i ) );
3114 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3126 QVariant result( centroid.
asPoint().
x() );
3132 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3144 QVariant result( centroid.
asPoint().
y() );
3150 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3160 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3168 if ( collection->numGeometries() == 1 )
3170 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3181 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3191 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3199 if ( collection->numGeometries() == 1 )
3201 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3212 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3217 int idx = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
3244 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3261 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3278 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3283 bool ignoreClosing =
false;
3284 if ( values.length() > 1 )
3286 ignoreClosing = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3296 bool skipLast =
false;
3297 if ( ignoreClosing && ring.count() > 2 && ring.first() == ring.last() )
3302 for (
int i = 0; i < ( skipLast ? ring.count() - 1 : ring.count() ); ++ i )
3314 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3325 for (
int i = 0; i < line->numPoints() - 1; ++i )
3329 << line->pointN( i )
3330 << line->pointN( i + 1 ) );
3341 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3351 if ( collection->numGeometries() == 1 )
3353 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->geometryN( 0 ) );
3358 if ( !curvePolygon )
3362 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3368 QVariant result = curve ? QVariant::fromValue(
QgsGeometry( curve ) ) : QVariant();
3374 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3384 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3390 QVariant result = part ? QVariant::fromValue(
QgsGeometry( part ) ) : QVariant();
3396 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3405 return QVariant::fromValue(
QgsGeometry( boundary ) );
3410 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3419 return QVariant::fromValue( merged );
3424 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3428 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3433 if ( sharedPaths.
isNull() )
3436 return QVariant::fromValue( sharedPaths );
3442 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3447 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3450 if ( simplified.
isNull() )
3458 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3463 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3468 if ( simplified.
isNull() )
3476 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3481 int iterations = std::min( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), 10 );
3482 double offset = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0.0, 0.5 );
3483 double minLength = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3484 double maxAngle = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ), 0.0, 180.0 );
3486 QgsGeometry smoothed = geom.
smooth(
static_cast<unsigned int>( iterations ), offset, minLength, maxAngle );
3495 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3500 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3501 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3502 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3513 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3518 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3519 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3520 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3521 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3522 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3525 minAmplitude, maxAmplitude, seed );
3534 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3539 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3540 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3541 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3552 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3557 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3558 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3559 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3560 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3561 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3564 minAmplitude, maxAmplitude, seed );
3573 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3578 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3579 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3580 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3591 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3596 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3597 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3598 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3599 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3600 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3603 minAmplitude, maxAmplitude, seed );
3612 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3617 const QVariantList pattern = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
3618 QVector< double > dashPattern;
3619 dashPattern.reserve( pattern.size() );
3620 for (
const QVariant &value : std::as_const( pattern ) )
3623 double v = value.toDouble( &ok );
3630 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must be an array of numbers" ) );
3635 if ( dashPattern.size() % 2 != 0 )
3637 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must contain an even number of elements" ) );
3641 const QString startRuleString = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).trimmed();
3643 if ( startRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3645 else if ( startRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3647 else if ( startRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3649 else if ( startRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3651 else if ( startRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3655 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( startRuleString ) );
3659 const QString endRuleString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
3661 if ( endRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3663 else if ( endRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3665 else if ( endRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3667 else if ( endRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3669 else if ( endRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3673 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( endRuleString ) );
3677 const QString adjustString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
3679 if ( adjustString.compare( QLatin1String(
"both" ), Qt::CaseInsensitive ) == 0 )
3681 else if ( adjustString.compare( QLatin1String(
"dash" ), Qt::CaseInsensitive ) == 0 )
3683 else if ( adjustString.compare( QLatin1String(
"gap" ), Qt::CaseInsensitive ) == 0 )
3687 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern size adjustment" ).arg( adjustString ) );
3691 const double patternOffset = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
3702 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3707 const long long count = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3709 if ( densified.
isNull() )
3717 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3722 const double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3724 if ( densified.
isNull() )
3733 if ( values.size() == 1 && QgsExpressionUtils::isList( values.at( 0 ) ) )
3735 list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
3742 QVector< QgsGeometry > parts;
3743 parts.reserve( list.size() );
3744 for (
const QVariant &value : std::as_const( list ) )
3746 QgsGeometry part = QgsExpressionUtils::getGeometry( value, parent );
3757 if ( values.count() < 2 || values.count() > 4 )
3759 parent->
setEvalErrorString( QObject::tr(
"Function make_point requires 2-4 arguments" ) );
3763 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3764 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3765 double z = values.count() >= 3 ? QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) : 0.0;
3766 double m = values.count() >= 4 ? QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) : 0.0;
3767 switch ( values.count() )
3781 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3782 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3783 double m = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3789 if ( values.empty() )
3794 QVector<QgsPoint> points;
3795 points.reserve( values.count() );
3797 auto addPoint = [&points](
const QgsGeometry & geom )
3805 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3812 for (
const QVariant &value : values )
3814 if ( value.userType() == QMetaType::Type::QVariantList )
3816 const QVariantList list = value.toList();
3817 for (
const QVariant &v : list )
3819 addPoint( QgsExpressionUtils::getGeometry( v, parent ) );
3824 addPoint( QgsExpressionUtils::getGeometry( value, parent ) );
3828 if ( points.count() < 2 )
3836 if ( values.count() < 1 )
3838 parent->
setEvalErrorString( QObject::tr(
"Function make_polygon requires an argument" ) );
3842 QgsGeometry outerRing = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3850 auto polygon = std::make_unique< QgsPolygon >();
3852 const QgsCurve *exteriorRing = qgsgeometry_cast< const QgsCurve * >( outerRing.
constGet() );
3859 exteriorRing = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
3864 if ( !exteriorRing )
3867 polygon->setExteriorRing( exteriorRing->
segmentize() );
3870 for (
int i = 1; i < values.count(); ++i )
3872 QgsGeometry ringGeom = QgsExpressionUtils::getGeometry( values.at( i ), parent );
3879 const QgsCurve *ring = qgsgeometry_cast< const QgsCurve * >( ringGeom.
constGet() );
3886 ring = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
3894 polygon->addInteriorRing( ring->
segmentize() );
3897 return QVariant::fromValue(
QgsGeometry( std::move( polygon ) ) );
3902 auto tr = std::make_unique<QgsTriangle>();
3903 auto lineString = std::make_unique<QgsLineString>();
3904 lineString->clear();
3906 for (
const QVariant &value : values )
3908 QgsGeometry geom = QgsExpressionUtils::getGeometry( value, parent );
3915 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3922 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3930 lineString->addVertex( *point );
3933 tr->setExteriorRing( lineString.release() );
3935 return QVariant::fromValue(
QgsGeometry( tr.release() ) );
3940 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3947 double radius = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3948 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
3955 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3962 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3970 return QVariant::fromValue(
QgsGeometry( circ.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
3975 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3982 double majorAxis = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3983 double minorAxis = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3984 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3985 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 4 ), parent );
3991 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3998 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4005 QgsEllipse elp( *point, majorAxis, minorAxis, azimuth );
4006 return QVariant::fromValue(
QgsGeometry( elp.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
4012 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4019 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4026 unsigned int nbEdges =
static_cast<unsigned int>( QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) );
4029 parent->
setEvalErrorString( QObject::tr(
"Number of edges/sides must be greater than 2" ) );
4036 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (inscribed) or 1 (circumscribed)" ) );
4040 const QgsPoint *center = qgsgeometry_cast< const QgsPoint * >( pt1.
constGet() );
4047 center = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4054 const QgsPoint *corner = qgsgeometry_cast< const QgsPoint * >( pt2.
constGet() );
4061 corner = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4076 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4082 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4088 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
4089 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
4097 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4103 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4109 QgsGeometry pt3 = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
4118 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (distance) or 1 (projected)" ) );
4121 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
4122 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
4123 const QgsPoint *point3 = qgsgeometry_cast< const QgsPoint *>( pt3.
constGet() );
4142 return QVariant::fromValue( geom.
vertexAt( idx ) );
4150 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4152 const QVariant v = pointAt( geom, idx, parent );
4155 return QVariant( v.value<
QgsPoint>().
x() );
4161 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4163 return fcnOldXat( values, f, parent, node );
4165 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4167 return fcnOldXat( QVariantList() << values[1], f, parent, node );
4170 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4176 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4178 const QVariant v = pointAt( geom, vertexNumber, parent );
4180 return QVariant( v.value<
QgsPoint>().
x() );
4190 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4192 const QVariant v = pointAt( geom, idx, parent );
4195 return QVariant( v.value<
QgsPoint>().
y() );
4201 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4203 return fcnOldYat( values, f, parent, node );
4205 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4207 return fcnOldYat( QVariantList() << values[1], f, parent, node );
4210 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4216 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4218 const QVariant v = pointAt( geom, vertexNumber, parent );
4220 return QVariant( v.value<
QgsPoint>().
y() );
4227 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4233 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4235 const QVariant v = pointAt( geom, vertexNumber, parent );
4237 return QVariant( v.value<
QgsPoint>().
z() );
4244 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4250 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4252 const QVariant v = pointAt( geom, vertexNumber, parent );
4254 return QVariant( v.value<
QgsPoint>().
m() );
4273 return QVariant::fromValue( geom );
4281 QString wkt = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4283 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4289 const QByteArray wkb = QgsExpressionUtils::getBinaryValue( values.at( 0 ), parent );
4295 return !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4300 QString gml = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4307 ogcContext.
layer = mapLayerPtr.data();
4308 ogcContext.
transformContext = context->
variable( QStringLiteral(
"_project_transform_context" ) ).value<QgsCoordinateTransformContext>();
4312 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4327 return QVariant( area );
4331 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating area" ) );
4343 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4348 return QVariant( geom.
area() );
4362 return QVariant( len );
4366 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating length" ) );
4387 return QVariant( len );
4391 parent->
setEvalErrorString( QObject::tr(
"An error occurred while calculating perimeter" ) );
4397 return f.
geometry().
isNull() ? QVariant( 0 ) : QVariant( f.geometry().constGet()->perimeter() );
4403 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4409 return QVariant( geom.
length() );
4414 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4415 return QVariant( geom.
isNull() ? 0 : geom.constGet()->nCoordinates() );
4420 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4429 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4438 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4453 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon *>( collection->
geometryN( i ) );
4454 if ( !curvePolygon )
4457 return QVariant( curvePolygon->
isEmpty() ? 0 : curvePolygon->numInteriorRings() );
4466 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4473 return QVariant( curvePolygon->
ringCount() );
4475 bool foundPoly =
false;
4483 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon *>( collection->
geometryN( i ) );
4484 if ( !curvePolygon )
4495 return QVariant( ringCount );
4500 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4502 QVariant result = !geomBounds.
isNull() ? QVariant::fromValue( geomBounds ) : QVariant();
4508 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4514 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4520 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4529 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4535 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4541 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4547 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4553 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4561 double max = std::numeric_limits< double >::lowest();
4565 double z = ( *it ).z();
4571 if ( max == std::numeric_limits< double >::lowest() )
4574 return QVariant( max );
4579 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4587 double min = std::numeric_limits< double >::max();
4591 double z = ( *it ).z();
4597 if ( min == std::numeric_limits< double >::max() )
4600 return QVariant( min );
4605 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4613 double min = std::numeric_limits< double >::max();
4617 double m = ( *it ).m();
4623 if ( min == std::numeric_limits< double >::max() )
4626 return QVariant( min );
4631 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4639 double max = std::numeric_limits< double >::lowest();
4643 double m = ( *it ).m();
4649 if ( max == std::numeric_limits< double >::lowest() )
4652 return QVariant( max );
4657 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4658 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom.
constGet() );
4661 parent->
setEvalErrorString( QObject::tr(
"Function `sinuosity` requires a line geometry." ) );
4670 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4674 parent->
setEvalErrorString( QObject::tr(
"Function `straight_distance_2d` requires a line geometry or a multi line geometry with a single part." ) );
4683 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4688 parent->
setEvalErrorString( QObject::tr(
"Function `roundness` requires a polygon geometry or a multi polygon geometry with a single part." ) );
4699 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4703 std::unique_ptr< QgsAbstractGeometry > flipped( geom.
constGet()->
clone() );
4705 return QVariant::fromValue(
QgsGeometry( std::move( flipped ) ) );
4710 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4714 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( fGeom.
constGet() );
4721 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
4729 return QVariant::fromValue( curve->
isClosed() );
4734 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4747 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4748 closedLine->close();
4750 result = QVariant::fromValue(
QgsGeometry( std::move( closedLine ) ) );
4762 if (
const QgsLineString *line = qgsgeometry_cast<const QgsLineString * >( collection->
geometryN( i ) ) )
4764 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4765 closedLine->close();
4767 closed->addGeometry( closedLine.release() );
4770 result = QVariant::fromValue(
QgsGeometry( std::move( closed ) ) );
4778 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4782 return QVariant::fromValue( fGeom.
isEmpty() );
4788 return QVariant::fromValue(
true );
4790 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4791 return QVariant::fromValue( fGeom.
isNull() || fGeom.
isEmpty() );
4796 if ( values.length() < 2 || values.length() > 3 )
4799 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4800 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4807 if ( values.length() == 2 )
4810 QString result = engine->relate( sGeom.
constGet() );
4811 return QVariant::fromValue( result );
4816 QString pattern = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
4817 bool result = engine->relatePattern( sGeom.
constGet(), pattern );
4818 return QVariant::fromValue( result );
4824 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4825 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4830 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4831 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4832 return fGeom.
disjoint( sGeom ) ? TVL_True : TVL_False;
4836 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4837 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4838 return fGeom.
intersects( sGeom ) ? TVL_True : TVL_False;
4842 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4843 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4844 return fGeom.
touches( sGeom ) ? TVL_True : TVL_False;
4848 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4849 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4850 return fGeom.
crosses( sGeom ) ? TVL_True : TVL_False;
4854 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4855 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4856 return fGeom.
contains( sGeom ) ? TVL_True : TVL_False;
4860 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4861 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4862 return fGeom.
overlaps( sGeom ) ? TVL_True : TVL_False;
4866 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4867 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4868 return fGeom.
within( sGeom ) ? TVL_True : TVL_False;
4873 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4874 const double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4875 const int seg = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4876 const QString endCapString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
4877 const QString joinString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
4878 const double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
4881 if ( endCapString.compare( QLatin1String(
"flat" ), Qt::CaseInsensitive ) == 0 )
4883 else if ( endCapString.compare( QLatin1String(
"square" ), Qt::CaseInsensitive ) == 0 )
4887 if ( joinString.compare( QLatin1String(
"miter" ), Qt::CaseInsensitive ) == 0 )
4889 else if ( joinString.compare( QLatin1String(
"bevel" ), Qt::CaseInsensitive ) == 0 )
4893 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4899 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4901 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4906 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4908 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4913 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4915 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4920 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4921 const QgsPoint *pt = qgsgeometry_cast<const QgsPoint *>( fGeom.
constGet() );
4928 pt = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4935 parent->
setEvalErrorString( QObject::tr(
"Function `wedge_buffer` requires a point value for the center." ) );
4939 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4940 double width = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4941 double outerRadius = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4942 double innerRadius = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
4945 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4951 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4954 parent->
setEvalErrorString( QObject::tr(
"Function `tapered_buffer` requires a line geometry." ) );
4958 double startWidth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4959 double endWidth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4960 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) );
4963 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4969 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4972 parent->
setEvalErrorString( QObject::tr(
"Function `buffer_by_m` requires a line geometry." ) );
4976 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) );
4979 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4985 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4986 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4987 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4988 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4989 if ( joinInt < 1 || joinInt > 3 )
4993 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4996 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5002 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5003 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5004 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
5006 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
5007 if ( joinInt < 1 || joinInt > 3 )
5011 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5014 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5020 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5021 double distStart = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5022 double distEnd = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5025 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5031 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5032 double dx = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5033 double dy = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5035 return QVariant::fromValue( fGeom );
5040 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5041 const double rotation = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5042 const QgsGeometry center = values.at( 2 ).
isValid() ? QgsExpressionUtils::getGeometry( values.at( 2 ), parent )
5044 const bool perPart = values.value( 3 ).toBool();
5051 std::unique_ptr< QgsGeometryCollection > collection( qgsgeometry_cast< QgsGeometryCollection * >( fGeom.
constGet()->
clone() ) );
5054 const QgsPointXY partCenter = ( *it )->boundingBox().center();
5055 QTransform t = QTransform::fromTranslate( partCenter.
x(), partCenter.
y() );
5056 t.rotate( -rotation );
5057 t.translate( -partCenter.
x(), -partCenter.
y() );
5058 ( *it )->transform( t );
5060 return QVariant::fromValue(
QgsGeometry( std::move( collection ) ) );
5072 parent->
setEvalErrorString( QObject::tr(
"Function 'rotate' requires a point value for the center" ) );
5080 fGeom.
rotate( rotation, pt );
5081 return QVariant::fromValue( fGeom );
5087 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5088 const double xScale = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5089 const double yScale = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5090 const QgsGeometry center = values.at( 3 ).isValid() ? QgsExpressionUtils::getGeometry( values.at( 3 ), parent )
5101 parent->
setEvalErrorString( QObject::tr(
"Function 'scale' requires a point value for the center" ) );
5109 QTransform t = QTransform::fromTranslate( pt.
x(), pt.
y() );
5110 t.scale( xScale, yScale );
5111 t.translate( -pt.
x(), -pt.
y() );
5113 return QVariant::fromValue( fGeom );
5118 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5124 const double deltaX = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5125 const double deltaY = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5127 const double rotationZ = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5129 const double scaleX = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
5130 const double scaleY = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
5132 const double deltaZ = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
5133 const double deltaM = QgsExpressionUtils::getDoubleValue( values.at( 7 ), parent );
5134 const double scaleZ = QgsExpressionUtils::getDoubleValue( values.at( 8 ), parent );
5135 const double scaleM = QgsExpressionUtils::getDoubleValue( values.at( 9 ), parent );
5146 QTransform transform;
5147 transform.translate( deltaX, deltaY );
5148 transform.rotate( rotationZ );
5149 transform.scale( scaleX, scaleY );
5150 fGeom.
transform( transform, deltaZ, scaleZ, deltaM, scaleM );
5152 return QVariant::fromValue( fGeom );
5158 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5160 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5165 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5167 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5173 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5174 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5176 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5182 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5184 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5188#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
5193 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5194 const double targetPercent = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5195 const bool allowHoles = values.value( 2 ).toBool();
5197 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5210 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5212 if ( values.length() == 2 )
5213 segments = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5221 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5227 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5229 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5235 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5241 double area,
angle, width, height;
5254 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5255 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5257 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5268 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent,
true );
5274 const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( fGeom.
constGet() );
5279 result = reversed ? QVariant::fromValue(
QgsGeometry( reversed ) ) : QVariant();
5287 if (
const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( collection->
geometryN( i ) ) )
5289 reversed->addGeometry( curve->
reversed() );
5296 result = reversed ? QVariant::fromValue(
QgsGeometry( std::move( reversed ) ) ) : QVariant();
5302 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
5303 std::reverse(
string.begin(),
string.end() );
5309 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5320 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->
geometryN( 0 ) );
5329 QVariant result = exterior ? QVariant::fromValue(
QgsGeometry( exterior ) ) : QVariant();
5335 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5336 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5337 return QVariant( fGeom.
distance( sGeom ) );
5342 QgsGeometry g1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5343 QgsGeometry g2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5346 if ( values.length() == 3 && values.at( 2 ).isValid() )
5348 double densify = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5349 densify = std::clamp( densify, 0.0, 1.0 );
5357 return res > -1 ? QVariant( res ) : QVariant();
5362 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5363 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5365 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5370 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5371 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5373 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5378 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5379 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5381 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5387 if ( values.length() < 1 || values.length() > 2 )
5390 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5392 if ( values.length() == 2 )
5393 prec = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5394 QString wkt = fGeom.
asWkt( prec );
5395 return QVariant( wkt );
5400 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5401 return fGeom.
isNull() ? QVariant() : QVariant( fGeom.asWkb() );
5406 if ( values.length() != 2 )
5408 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires exactly two parameters. %n given.",
nullptr, values.length() ) );
5412 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5413 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5415 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5422 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5427 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5434 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5441 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires two points as arguments." ) );
5448 if ( pt1->
y() < pt2->
y() )
5450 else if ( pt1->
y() > pt2->
y() )
5458 if ( pt1->
x() < pt2->
x() )
5460 else if ( pt1->
x() > pt2->
x() )
5461 return M_PI + ( M_PI_2 );
5466 if ( pt1->
x() < pt2->
x() )
5468 if ( pt1->
y() < pt2->
y() )
5470 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) );
5474 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5481 if ( pt1->
y() > pt2->
y() )
5483 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) )
5488 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5489 + ( M_PI + ( M_PI_2 ) );
5496 const QgsGeometry geom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5497 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5499 QString ellipsoid = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
5503 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires two valid point geometries." ) );
5511 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires point geometries or multi point geometries with a single part." ) );
5522 sourceCrs = context->
variable( QStringLiteral(
"_layer_crs" ) ).value<QgsCoordinateReferenceSystem>();
5525 if ( ellipsoid.isEmpty() )
5527 ellipsoid = context->
variable( QStringLiteral(
"project_ellipsoid" ) ).toString();
5533 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires a valid source CRS." ) );
5541 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires a valid ellipsoid acronym or ellipsoid authority ID." ) );
5547 const double bearing = da.
bearing( point1, point2 );
5548 if ( std::isfinite( bearing ) )
5550 return std::fmod( bearing + 2 * M_PI, 2 * M_PI );
5563 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5567 parent->
setEvalErrorString( QStringLiteral(
"'project' requires a point geometry" ) );
5571 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5572 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5573 double inclination = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5576 QgsPoint newPoint = p->
project( distance, 180.0 * azimuth / M_PI, 180.0 * inclination / M_PI );
5583 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5584 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5586 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5593 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5597 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5604 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5612 parent->
setEvalErrorString( QStringLiteral(
"Function 'inclination' requires two points as arguments." ) );
5622 if ( values.length() != 3 )
5625 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5626 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5627 double y = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5631 QVariant result = geom.
constGet() ? QVariant::fromValue( geom ) : QVariant();
5637 if ( values.length() < 2 )
5640 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5643 return values.at( 0 );
5645 QString expString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5646 QVariant cachedExpression;
5651 if ( cachedExpression.isValid() )
5658 bool asc = values.value( 2 ).toBool();
5676 Q_ASSERT( collection );
5680 QgsExpressionSorter sorter( orderBy );
5682 QList<QgsFeature> partFeatures;
5683 partFeatures.reserve( collection->
partCount() );
5684 for (
int i = 0; i < collection->
partCount(); ++i )
5690 sorter.sortFeatures( partFeatures, unconstedContext );
5694 Q_ASSERT( orderedGeom );
5699 for (
const QgsFeature &feature : std::as_const( partFeatures ) )
5704 QVariant result = QVariant::fromValue(
QgsGeometry( orderedGeom ) );
5707 delete unconstedContext;
5714 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5715 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5719 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5725 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5726 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5730 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5736 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5737 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5741 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5747 const QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5748 const double m = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5749 const bool use3DDistance = values.at( 2 ).toBool();
5751 double x, y, z, distance;
5774 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5777 parent->
setEvalErrorString( QObject::tr(
"line_substring requires a curve geometry input" ) );
5783 curve = qgsgeometry_cast< const QgsCurve * >( lineGeom.
constGet() );
5790 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
5797 double startDistance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5798 double endDistance = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5800 std::unique_ptr< QgsCurve > substring( curve->
curveSubstring( startDistance, endDistance ) );
5802 return !result.isNull() ? QVariant::fromValue( result ) : QVariant();
5807 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5808 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5815 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5816 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5821 vertex = count + vertex;
5829 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5830 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5835 vertex = count + vertex;
5843 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5844 QgsGeometry pointGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5848 return distance >= 0 ? distance : QVariant();
5853 const QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5854 const double m = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5855 const bool use3DDistance = values.at( 2 ).toBool();
5857 double x, y, z, distance;
5866 return found ? distance : QVariant();
5871 if ( values.length() == 2 && values.at( 1 ).toInt() != 0 )
5873 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5874 return qgsRound( number, QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
5877 if ( values.length() >= 1 )
5879 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5880 return QVariant( qlonglong( std::round( number ) ) );
5895 const double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5896 const int places = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5897 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5904 const bool omitGroupSeparator = values.value( 3 ).toBool();
5905 const bool trimTrailingZeros = values.value( 4 ).toBool();
5907 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5908 if ( !omitGroupSeparator )
5909 locale.setNumberOptions( locale.numberOptions() & ~QLocale::NumberOption::OmitGroupSeparator );
5911 locale.setNumberOptions( locale.numberOptions() | QLocale::NumberOption::OmitGroupSeparator );
5913 QString res = locale.toString( value,
'f', places );
5915 if ( trimTrailingZeros )
5917#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
5918 const QChar decimal = locale.decimalPoint();
5919 const QChar zeroDigit = locale.zeroDigit();
5921 const QChar decimal = locale.decimalPoint().at( 0 );
5922 const QChar zeroDigit = locale.zeroDigit().at( 0 );
5925 if ( res.contains( decimal ) )
5927 int trimPoint = res.length() - 1;
5929 while ( res.at( trimPoint ) == zeroDigit )
5932 if ( res.at( trimPoint ) == decimal )
5935 res.truncate( trimPoint + 1 );
5944 QDateTime datetime = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
5945 const QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5946 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5949 if ( format.indexOf(
"Z" ) > 0 )
5950 datetime = datetime.toUTC();
5952 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5953 return locale.toString( datetime, format );
5958 const QVariant variant = values.at( 0 );
5960 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
5961 if ( !color.isValid() )
5964 const float alpha = color.alphaF();
5965 if ( color.spec() == QColor::Spec::Cmyk )
5967 const float avg = ( color.cyanF() + color.magentaF() + color.yellowF() ) / 3;
5968 color = QColor::fromCmykF( avg, avg, avg, color.blackF(), alpha );
5972 const float avg = ( color.redF() + color.greenF() + color.blueF() ) / 3;
5973 color.setRgbF( avg, avg, avg, alpha );
5976 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
5983 double ratio = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5988 else if ( ratio < 0 )
5993 int red =
static_cast<int>( color1.red() * ( 1 - ratio ) + color2.red() * ratio );
5994 int green =
static_cast<int>( color1.green() * ( 1 - ratio ) + color2.green() * ratio );
5995 int blue =
static_cast<int>( color1.blue() * ( 1 - ratio ) + color2.blue() * ratio );
5996 int alpha =
static_cast<int>( color1.alpha() * ( 1 - ratio ) + color2.alpha() * ratio );
5998 QColor newColor( red, green, blue, alpha );
6005 const QVariant variant1 = values.at( 0 );
6006 const QVariant variant2 = values.at( 1 );
6008 if ( variant1.userType() != variant2.userType() )
6010 parent->
setEvalErrorString( QObject::tr(
"Both color arguments must have the same type (string or color object)" ) );
6015 const QColor color1 = QgsExpressionUtils::getColorValue( variant1, parent, isQColor );
6016 if ( !color1.isValid() )
6019 const QColor color2 = QgsExpressionUtils::getColorValue( variant2, parent, isQColor );
6020 if ( !color2.isValid() )
6023 if ( ( color1.spec() == QColor::Cmyk ) != ( color2.spec() == QColor::Cmyk ) )
6025 parent->
setEvalErrorString( QObject::tr(
"Both color arguments must have compatible color type (CMYK or RGB/HSV/HSL)" ) );
6029 const float ratio =
static_cast<float>( std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0., 1. ) );
6035 const float alpha = color1.alphaF() * ( 1 - ratio ) + color2.alphaF() * ratio;
6036 if ( color1.spec() == QColor::Spec::Cmyk )
6038 float cyan = color1.cyanF() * ( 1 - ratio ) + color2.cyanF() * ratio;
6039 float magenta = color1.magentaF() * ( 1 - ratio ) + color2.magentaF() * ratio;
6040 float yellow = color1.yellowF() * ( 1 - ratio ) + color2.yellowF() * ratio;
6041 float black = color1.blackF() * ( 1 - ratio ) + color2.blackF() * ratio;
6042 newColor = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6046 float red = color1.redF() * ( 1 - ratio ) + color2.redF() * ratio;
6047 float green = color1.greenF() * ( 1 - ratio ) + color2.greenF() * ratio;
6048 float blue = color1.blueF() * ( 1 - ratio ) + color2.blueF() * ratio;
6049 newColor = QColor::fromRgbF( red, green, blue, alpha );
6054 return isQColor ? QVariant( newColor ) : QVariant(
QgsSymbolLayerUtils::encodeColor( newColor ) );
6059 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
6060 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6061 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6062 QColor color = QColor( red, green, blue );
6063 if ( ! color.isValid() )
6065 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( red ).arg( green ).arg( blue ) );
6066 color = QColor( 0, 0, 0 );
6069 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6074 const float red = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6075 const float green = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6076 const float blue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6077 const float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6078 QColor color = QColor::fromRgbF( red, green, blue, alpha );
6079 if ( ! color.isValid() )
6081 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
6090 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
6091 QVariant value = node->
eval( parent, context );
6095 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
6097 value = node->
eval( parent, context );
6105 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
6107 QVariant value = node->
eval( parent, context );
6109 if ( value.toBool() )
6111 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
6113 value = node->
eval( parent, context );
6118 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
6120 value = node->
eval( parent, context );
6128 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
6129 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6130 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6131 int alpha = QgsExpressionUtils::getNativeIntValue( values.at( 3 ), parent );
6132 QColor color = QColor( red, green, blue, alpha );
6133 if ( ! color.isValid() )
6135 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
6136 color = QColor( 0, 0, 0 );
6145 if ( values.at( 0 ).userType() == qMetaTypeId< QgsGradientColorRamp>() )
6147 expRamp = QgsExpressionUtils::getRamp( values.at( 0 ), parent );
6152 QString rampName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
6130 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent ); {
…}
6156 parent->
setEvalErrorString( QObject::tr(
"\"%1\" is not a valid color ramp" ).arg( rampName ) );
6161 double value = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
6162 QColor color = ramp->
color( value );
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 QColor color = QColor::fromHslF( hue, saturation, lightness );
6183 if ( ! color.isValid() )
6185 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( lightness ) );
6186 color = QColor( 0, 0, 0 );
6189 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6195 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6197 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6199 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6201 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
6203 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
6204 if ( ! color.isValid() )
6206 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
6207 color = QColor( 0, 0, 0 );
6214 float hue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6215 float saturation = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6216 float lightness = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6217 float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6219 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
6220 if ( ! color.isValid() )
6222 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
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 QColor color = QColor::fromHsvF( hue, saturation, value );
6240 if ( ! color.isValid() )
6242 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( value ) );
6243 color = QColor( 0, 0, 0 );
6246 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6252 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6254 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6256 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6258 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
6260 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
6261 if ( ! color.isValid() )
6263 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
6264 color = QColor( 0, 0, 0 );
6271 float hue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6272 float saturation = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6273 float value = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6274 float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6275 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
6277 if ( ! color.isValid() )
6279 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
6288 const float cyan = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6289 const float magenta = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6290 const float yellow = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6291 const float black = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6292 const float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ) ), 0.f, 1.f );
6294 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6295 if ( ! color.isValid() )
6297 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
6307 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
6309 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6311 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6313 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
6315 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black );
6317 if ( ! color.isValid() )
6319 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ) );
6320 color = QColor( 0, 0, 0 );
6323 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6329 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
6331 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6333 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6335 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
6337 double alpha = QgsExpressionUtils::getIntValue( values.at( 4 ), parent ) / 255.0;
6339 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6340 if ( ! color.isValid() )
6342 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
6343 color = QColor( 0, 0, 0 );
6350 const QVariant variant = values.at( 0 );
6352 const QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6353 if ( !color.isValid() )
6356 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6357 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6359 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6360 return color.green();
6361 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6362 return color.blue();
6363 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6364 return color.alpha();
6365 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6366 return static_cast< double >( color.hsvHueF() * 360 );
6367 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6368 return static_cast< double >( color.hsvSaturationF() * 100 );
6369 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6370 return static_cast< double >( color.valueF() * 100 );
6371 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6372 return static_cast< double >( color.hslHueF() * 360 );
6373 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6374 return static_cast< double >( color.hslSaturationF() * 100 );
6375 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6376 return static_cast< double >( color.lightnessF() * 100 );
6377 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6378 return static_cast< double >( color.cyanF() * 100 );
6379 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6380 return static_cast< double >( color.magentaF() * 100 );
6381 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6382 return static_cast< double >( color.yellowF() * 100 );
6383 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6384 return static_cast< double >( color.blackF() * 100 );
6386 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6392 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
6395 parent->
setEvalErrorString( QObject::tr(
"A minimum of two colors is required to create a ramp" ) );
6399 QList< QColor > colors;
6401 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
6404 if ( !colors.last().isValid() )
6406 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( it.value().toString() ) );
6410 double step = it.key().toDouble();
6411 if ( it == map.constBegin() )
6416 else if ( it == map.constEnd() )
6426 bool discrete = values.at( 1 ).toBool();
6428 if ( colors.empty() )
6431 return QVariant::fromValue(
QgsGradientColorRamp( colors.first(), colors.last(), discrete, stops ) );
6436 const QVariant variant = values.at( 0 );
6438 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6439 if ( !color.isValid() )
6442 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6443 int value = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6444 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6445 color.setRed( std::clamp( value, 0, 255 ) );
6446 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6447 color.setGreen( std::clamp( value, 0, 255 ) );
6448 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6449 color.setBlue( std::clamp( value, 0, 255 ) );
6450 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6451 color.setAlpha( std::clamp( value, 0, 255 ) );
6452 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6453 color.setHsv( std::clamp( value, 0, 359 ), color.hsvSaturation(), color.value(), color.alpha() );
6454 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6455 color.setHsvF( color.hsvHueF(), std::clamp( value, 0, 100 ) / 100.0, color.valueF(), color.alphaF() );
6456 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6457 color.setHsvF( color.hsvHueF(), color.hsvSaturationF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6458 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6459 color.setHsl( std::clamp( value, 0, 359 ), color.hslSaturation(), color.lightness(), color.alpha() );
6460 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6461 color.setHslF( color.hslHueF(), std::clamp( value, 0, 100 ) / 100.0, color.lightnessF(), color.alphaF() );
6462 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6463 color.setHslF( color.hslHueF(), color.hslSaturationF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6464 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6465 color.setCmykF( std::clamp( value, 0, 100 ) / 100.0, color.magentaF(), color.yellowF(), color.blackF(), color.alphaF() );
6466 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6467 color.setCmykF( color.cyanF(), std::clamp( value, 0, 100 ) / 100.0, color.yellowF(), color.blackF(), color.alphaF() );
6468 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6469 color.setCmykF( color.cyanF(), color.magentaF(), std::clamp( value, 0, 100 ) / 100.0, color.blackF(), color.alphaF() );
6470 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6471 color.setCmykF( color.cyanF(), color.magentaF(), color.yellowF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6474 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6477 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6482 const QVariant variant = values.at( 0 );
6484 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6485 if ( !color.isValid() )
6488 color = color.darker( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6490 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6495 const QVariant variant = values.at( 0 );
6497 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6498 if ( !color.isValid() )
6501 color = color.lighter( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6503 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6508 QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6511 return QVariant::fromValue( geom );
6517 const QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6525 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
6530 return QVariant::fromValue( fGeom );
6533 return QVariant::fromValue( fGeom );
6542 return QVariant::fromValue( fGeom );
6555 bool foundLayer =
false;
6556 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6559 if ( !featureSource || !foundLayer )
6564 const QgsFeatureId fid = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
6577 result = QVariant::fromValue( fet );
6585 bool foundLayer =
false;
6586 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6589 if ( !featureSource || !foundLayer )
6594 QString cacheValueKey;
6595 if ( values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
6597 QVariantMap attributeMap = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
6599 QMap <QString, QVariant>::const_iterator i = attributeMap.constBegin();
6600 QString filterString;
6601 for ( ; i != attributeMap.constEnd(); ++i )
6603 if ( !filterString.isEmpty() )
6605 filterString.append(
" AND " );
6609 cacheValueKey = QStringLiteral(
"getfeature:%1:%2" ).arg( featureSource->id(), filterString );
6618 QString attribute = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6619 int attributeId = featureSource->fields().lookupField( attribute );
6620 if ( attributeId == -1 )
6625 const QVariant &attVal = values.at( 2 );
6627 cacheValueKey = QStringLiteral(
"getfeature:%1:%2:%3" ).arg( featureSource->id(), QString::number( attributeId ), attVal.toString() );
6650 res = QVariant::fromValue( fet );
6665 if ( !values.isEmpty() )
6668 if ( col && ( values.size() == 1 || !values.at( 1 ).isValid() ) )
6669 fieldName = col->
name();
6670 else if ( values.size() == 2 )
6671 fieldName = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6674 QVariant value = values.at( 0 );
6679 if ( fieldIndex == -1 )
6681 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: Field not found %2" ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6687 QgsVectorLayer *layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
6690 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName, value.toString() );
6699 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName );
6717 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: function cannot be evaluated without a context." ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6725 const QVariant data = values.at( 0 );
6726 const QMimeDatabase db;
6727 return db.mimeTypeForData( data.toByteArray() ).name();
6732 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6734 bool foundLayer =
false;
6735 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [layerProperty](
QgsMapLayer * layer )-> QVariant
6741 if ( QString::compare( layerProperty, QStringLiteral(
"name" ), Qt::CaseInsensitive ) == 0 )
6742 return layer->name();
6743 else if ( QString::compare( layerProperty, QStringLiteral(
"id" ), Qt::CaseInsensitive ) == 0 )
6745 else if ( QString::compare( layerProperty, QStringLiteral(
"title" ), Qt::CaseInsensitive ) == 0 )
6746 return !layer->metadata().title().isEmpty() ? layer->metadata().title() : layer->serverProperties()->title();
6747 else if ( QString::compare( layerProperty, QStringLiteral(
"abstract" ), Qt::CaseInsensitive ) == 0 )
6748 return !layer->metadata().abstract().isEmpty() ? layer->metadata().abstract() : layer->serverProperties()->abstract();
6749 else if ( QString::compare( layerProperty, QStringLiteral(
"keywords" ), Qt::CaseInsensitive ) == 0 )
6751 QStringList keywords;
6752 const QgsAbstractMetadataBase::KeywordMap keywordMap = layer->metadata().keywords();
6753 for ( auto it = keywordMap.constBegin(); it != keywordMap.constEnd(); ++it )
6755 keywords.append( it.value() );
6757 if ( !keywords.isEmpty() )
6759 return layer->serverProperties()->keywordList();
6761 else if ( QString::compare( layerProperty, QStringLiteral(
"data_url" ), Qt::CaseInsensitive ) == 0 )
6763 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution" ), Qt::CaseInsensitive ) == 0 )
6765 return !layer->
metadata().
rights().isEmpty() ? QVariant( layer->
metadata().
rights() ) : QVariant( layer->serverProperties()->attribution() );
6767 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution_url" ), Qt::CaseInsensitive ) == 0 )
6769 else if ( QString::compare( layerProperty, QStringLiteral(
"source" ), Qt::CaseInsensitive ) == 0 )
6771 else if ( QString::compare( layerProperty, QStringLiteral(
"min_scale" ), Qt::CaseInsensitive ) == 0 )
6773 else if ( QString::compare( layerProperty, QStringLiteral(
"max_scale" ), Qt::CaseInsensitive ) == 0 )
6775 else if ( QString::compare( layerProperty, QStringLiteral(
"is_editable" ), Qt::CaseInsensitive ) == 0 )
6777 else if ( QString::compare( layerProperty, QStringLiteral(
"crs" ), Qt::CaseInsensitive ) == 0 )
6779 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_definition" ), Qt::CaseInsensitive ) == 0 )
6781 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_description" ), Qt::CaseInsensitive ) == 0 )
6783 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_ellipsoid" ), Qt::CaseInsensitive ) == 0 )
6785 else if ( QString::compare( layerProperty, QStringLiteral(
"extent" ), Qt::CaseInsensitive ) == 0 )
6788 QVariant result = QVariant::fromValue( extentGeom );
6791 else if ( QString::compare( layerProperty, QStringLiteral(
"distance_units" ), Qt::CaseInsensitive ) == 0 )
6793 else if ( QString::compare( layerProperty, QStringLiteral(
"path" ), Qt::CaseInsensitive ) == 0 )
6796 return decodedUri.value( QStringLiteral(
"path" ) );
6798 else if ( QString::compare( layerProperty, QStringLiteral(
"type" ), Qt::CaseInsensitive ) == 0 )
6800 switch ( layer->
type() )
6803 return QCoreApplication::translate(
"expressions",
"Vector" );
6805 return QCoreApplication::translate(
"expressions",
"Raster" );
6807 return QCoreApplication::translate(
"expressions",
"Mesh" );
6809 return QCoreApplication::translate(
"expressions",
"Vector Tile" );
6811 return QCoreApplication::translate(
"expressions",
"Plugin" );
6813 return QCoreApplication::translate(
"expressions",
"Annotation" );
6815 return QCoreApplication::translate(
"expressions",
"Point Cloud" );
6817 return QCoreApplication::translate(
"expressions",
"Group" );
6819 return QCoreApplication::translate(
"expressions",
"Tiled Scene" );
6825 QgsVectorLayer *vLayer = qobject_cast< QgsVectorLayer * >( layer );
6828 if ( QString::compare( layerProperty, QStringLiteral(
"storage_type" ), Qt::CaseInsensitive ) == 0 )
6830 else if ( QString::compare( layerProperty, QStringLiteral(
"geometry_type" ), Qt::CaseInsensitive ) == 0 )
6832 else if ( QString::compare( layerProperty, QStringLiteral(
"feature_count" ), Qt::CaseInsensitive ) == 0 )
6848 const QString uriPart = values.at( 1 ).toString();
6850 bool foundLayer =
false;
6852 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, uriPart](
QgsMapLayer * layer )-> QVariant
6854 if ( !layer->dataProvider() )
6856 parent->setEvalErrorString( QObject::tr(
"Layer %1 has invalid data provider" ).arg( layer->name() ) );
6862 if ( !uriPart.isNull() )
6864 return decodedUri.value( uriPart );
6874 parent->
setEvalErrorString( QObject::tr(
"Function `decode_uri` requires a valid layer." ) );
6885 const int band = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6886 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6888 bool foundLayer =
false;
6889 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, band, layerProperty](
QgsMapLayer * layer )-> QVariant
6891 QgsRasterLayer *rl = qobject_cast< QgsRasterLayer * >( layer );
6895 if ( band < 1 || band > rl->bandCount() )
6897 parent->setEvalErrorString( QObject::tr(
"Invalid band number %1 for layer" ).arg( band ) );
6903 if ( QString::compare( layerProperty, QStringLiteral(
"avg" ), Qt::CaseInsensitive ) == 0 )
6905 else if ( QString::compare( layerProperty, QStringLiteral(
"stdev" ), Qt::CaseInsensitive ) == 0 )
6907 else if ( QString::compare( layerProperty, QStringLiteral(
"min" ), Qt::CaseInsensitive ) == 0 )
6909 else if ( QString::compare( layerProperty, QStringLiteral(
"max" ), Qt::CaseInsensitive ) == 0 )
6911 else if ( QString::compare( layerProperty, QStringLiteral(
"range" ), Qt::CaseInsensitive ) == 0 )
6913 else if ( QString::compare( layerProperty, QStringLiteral(
"sum" ), Qt::CaseInsensitive ) == 0 )
6917 parent->
setEvalErrorString( QObject::tr(
"Invalid raster statistic: '%1'" ).arg( layerProperty ) );
6945 parent->
setEvalErrorString( QObject::tr(
"Function `raster_statistic` requires a valid raster layer." ) );
6962 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6963 bool ascending = values.value( 1 ).toBool();
6964 std::sort( list.begin(), list.end(), [ascending]( QVariant a, QVariant b ) ->
bool { return ( !ascending ? qgsVariantLessThan( b, a ) : qgsVariantLessThan( a, b ) ); } );
6970 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).length();
6975 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).contains( values.at( 1 ) ) );
6980 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).count( values.at( 1 ) ) );
6985 QVariantList listA = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6986 QVariantList listB = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
6988 for (
const auto &item : listB )
6990 if ( listA.contains( item ) )
6994 return QVariant( match == listB.count() );
6999 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).indexOf( values.at( 1 ) );
7004 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7005 const int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7006 if ( pos < list.length() && pos >= 0 )
return list.at( pos );
7007 else if ( pos < 0 && ( list.length() + pos ) >= 0 )
7008 return list.at( list.length() + pos );
7014 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7015 return list.value( 0 );
7020 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7021 return list.value( list.size() - 1 );
7026 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7027 return list.isEmpty() ? QVariant() : *std::min_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
7032 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7033 return list.isEmpty() ? QVariant() : *std::max_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
7038 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7041 for (
const QVariant &item : list )
7043 switch ( item.userType() )
7045 case QMetaType::Int:
7046 case QMetaType::UInt:
7047 case QMetaType::LongLong:
7048 case QMetaType::ULongLong:
7049 case QMetaType::Float:
7050 case QMetaType::Double:
7051 total += item.toDouble();
7056 return i == 0 ? QVariant() : total / i;
7061 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7062 QVariantList numbers;
7063 for (
const auto &item : list )
7065 switch ( item.userType() )
7067 case QMetaType::Int:
7068 case QMetaType::UInt:
7069 case QMetaType::LongLong:
7070 case QMetaType::ULongLong:
7071 case QMetaType::Float:
7072 case QMetaType::Double:
7073 numbers.append( item );
7077 std::sort( numbers.begin(), numbers.end(), []( QVariant a, QVariant b ) ->
bool { return ( qgsVariantLessThan( a, b ) ); } );
7078 const int count = numbers.count();
7083 else if ( count % 2 )
7085 return numbers.at( count / 2 );
7089 return ( numbers.at( count / 2 - 1 ).toDouble() + numbers.at( count / 2 ).toDouble() ) / 2;
7095 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7098 for (
const QVariant &item : list )
7100 switch ( item.userType() )
7102 case QMetaType::Int:
7103 case QMetaType::UInt:
7104 case QMetaType::LongLong:
7105 case QMetaType::ULongLong:
7106 case QMetaType::Float:
7107 case QMetaType::Double:
7108 total += item.toDouble();
7113 return i == 0 ? QVariant() : total;
7116static QVariant convertToSameType(
const QVariant &value, QMetaType::Type type )
7118 QVariant result = value;
7119 result.convert(
static_cast<int>( type ) );
7125 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7126 QHash< QVariant, int > hash;
7127 for (
const auto &item : list )
7131 const QList< int > occurrences = hash.values();
7132 if ( occurrences.empty() )
7133 return QVariantList();
7135 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
7137 const QString option = values.at( 1 ).toString();
7138 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
7140 return convertToSameType( hash.keys( maxValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7142 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
7144 if ( hash.isEmpty() )
7147 return QVariant( hash.key( maxValue ) );
7149 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
7151 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( maxValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) ), context, parent, node );
7153 else if ( option.compare( QLatin1String(
"real_majority" ), Qt::CaseInsensitive ) == 0 )
7155 if ( maxValue * 2 <= list.size() )
7158 return QVariant( hash.key( maxValue ) );
7169 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7170 QHash< QVariant, int > hash;
7171 for (
const auto &item : list )
7175 const QList< int > occurrences = hash.values();
7176 if ( occurrences.empty() )
7177 return QVariantList();
7179 const int minValue = *std::min_element( occurrences.constBegin(), occurrences.constEnd() );
7181 const QString option = values.at( 1 ).toString();
7182 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
7184 return convertToSameType( hash.keys( minValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7186 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
7188 if ( hash.isEmpty() )
7191 return QVariant( hash.key( minValue ) );
7193 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
7195 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( minValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) ), context, parent, node );
7197 else if ( option.compare( QLatin1String(
"real_minority" ), Qt::CaseInsensitive ) == 0 )
7199 if ( hash.isEmpty() )
7203 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
7204 if ( maxValue * 2 > list.size() )
7205 hash.remove( hash.key( maxValue ) );
7207 return convertToSameType( hash.keys(),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7218 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7219 list.append( values.at( 1 ) );
7220 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7225 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7226 list.prepend( values.at( 1 ) );
7227 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7232 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7233 list.insert( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), values.at( 2 ) );
7234 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7239 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7240 int position = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7242 position = position + list.length();
7243 if ( position >= 0 && position < list.length() )
7244 list.removeAt( position );
7245 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7253 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7255 const QVariant toRemove = values.at( 1 );
7258 list.erase( std::remove_if( list.begin(), list.end(), [](
const QVariant & element )
7260 return QgsVariantUtils::isNull( element );
7265 list.removeAll( toRemove );
7267 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7272 if ( values.count() == 2 && values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
7274 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
7276 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7277 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
7279 int index = list.indexOf( it.key() );
7280 while ( index >= 0 )
7282 list.replace( index, it.value() );
7283 index = list.indexOf( it.key() );
7287 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7289 else if ( values.count() == 3 )
7291 QVariantList before;
7293 bool isSingleReplacement =
false;
7295 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).userType() != QMetaType::Type::QStringList )
7297 before = QVariantList() << values.at( 1 );
7301 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
7304 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
7306 after = QVariantList() << values.at( 2 );
7307 isSingleReplacement =
true;
7311 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
7314 if ( !isSingleReplacement && before.length() != after.length() )
7316 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
7320 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7321 for (
int i = 0; i < before.length(); i++ )
7323 int index = list.indexOf( before.at( i ) );
7324 while ( index >= 0 )
7326 list.replace( index, after.at( isSingleReplacement ? 0 : i ) );
7327 index = list.indexOf( before.at( i ) );
7331 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7335 parent->
setEvalErrorString( QObject::tr(
"Function array_replace requires 2 or 3 arguments" ) );
7342 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7343 QVariantList list_new;
7345 for (
const QVariant &cur :
QgsExpressionUtils::getListValue( values.at( 1 ), parent ) )
7347 while ( list.removeOne( cur ) )
7349 list_new.append( cur );
7353 list_new.append( list );
7355 return convertToSameType( list_new,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7361 for (
const QVariant &cur : values )
7363 list += QgsExpressionUtils::getListValue( cur, parent );
7365 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7370 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7371 int start_pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7372 const int end_pos = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
7373 int slice_length = 0;
7375 if ( start_pos < 0 )
7377 start_pos = list.length() + start_pos;
7381 slice_length = end_pos - start_pos + 1;
7385 slice_length = list.length() + end_pos - start_pos + 1;
7388 if ( slice_length < 0 )
7392 list = list.mid( start_pos, slice_length );
7398 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7399 std::reverse( list.begin(), list.end() );
7405 const QVariantList array1 = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7406 const QVariantList array2 = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
7407 for (
const QVariant &cur : array2 )
7409 if ( array1.contains( cur ) )
7410 return QVariant(
true );
7412 return QVariant(
false );
7417 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7419 QVariantList distinct;
7421 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7423 if ( !distinct.contains( *it ) )
7425 distinct += ( *it );
7434 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7435 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7436 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7440 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7442 str += ( !( *it ).toString().isEmpty() ) ? ( *it ).toString() : empty;
7443 if ( it != ( array.constEnd() - 1 ) )
7449 return QVariant( str );
7454 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7455 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7456 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7458 QStringList list = str.split( delimiter );
7461 for ( QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
7463 array += ( !( *it ).isEmpty() ) ? *it : empty;
7471 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7472 QJsonDocument document = QJsonDocument::fromJson( str.toUtf8() );
7473 if ( document.isNull() )
7476 return document.toVariant();
7482 QJsonDocument document = QJsonDocument::fromVariant( values.at( 0 ) );
7483 return QString( document.toJson( QJsonDocument::Compact ) );
7488 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7489 if ( str.isEmpty() )
7490 return QVariantMap();
7491 str = str.trimmed();
7498 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7505 for (
int i = 0; i + 1 < values.length(); i += 2 )
7507 result.insert( QgsExpressionUtils::getStringValue( values.at( i ), parent ), values.at( i + 1 ) );
7514 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7515 const QString prefix = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7516 QVariantMap resultMap;
7518 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7520 resultMap.insert( QString( it.key() ).prepend( prefix ), it.value() );
7528 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).value( values.at( 1 ).toString() );
7533 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).contains( values.at( 1 ).toString() );
7538 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7539 map.remove( values.at( 1 ).toString() );
7545 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7546 map.insert( values.at( 1 ).toString(), values.at( 2 ) );
7553 for (
const QVariant &cur : values )
7555 const QVariantMap curMap = QgsExpressionUtils::getMapValue( cur, parent );
7556 for ( QVariantMap::const_iterator it = curMap.constBegin(); it != curMap.constEnd(); ++it )
7557 result.insert( it.key(), it.value() );
7564 return QStringList( QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).keys() );
7569 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).values();
7574 const QString envVarName = values.at( 0 ).toString();
7575 if ( !QProcessEnvironment::systemEnvironment().contains( envVarName ) )
7578 return QProcessEnvironment::systemEnvironment().value( envVarName );
7583 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7586 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"base_file_name" ) ) );
7589 return QFileInfo( file ).completeBaseName();
7594 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7597 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_suffix" ) ) );
7600 return QFileInfo( file ).completeSuffix();
7605 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7608 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_exists" ) ) );
7611 return QFileInfo::exists( file );
7616 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7619 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_name" ) ) );
7622 return QFileInfo( file ).fileName();
7627 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7630 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_file" ) ) );
7633 return QFileInfo( file ).isFile();
7638 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7641 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_directory" ) ) );
7644 return QFileInfo( file ).isDir();
7649 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7652 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_path" ) ) );
7655 return QDir::toNativeSeparators( QFileInfo( file ).path() );
7660 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7663 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_size" ) ) );
7666 return QFileInfo( file ).size();
7669static QVariant fcnHash(
const QString &str,
const QCryptographicHash::Algorithm
algorithm )
7671 return QString( QCryptographicHash::hash( str.toUtf8(),
algorithm ).toHex() );
7677 QString str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7678 QString method = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).toLower();
7680 if ( method == QLatin1String(
"md4" ) )
7682 hash = fcnHash( str, QCryptographicHash::Md4 );
7684 else if ( method == QLatin1String(
"md5" ) )
7686 hash = fcnHash( str, QCryptographicHash::Md5 );
7688 else if ( method == QLatin1String(
"sha1" ) )
7690 hash = fcnHash( str, QCryptographicHash::Sha1 );
7692 else if ( method == QLatin1String(
"sha224" ) )
7694 hash = fcnHash( str, QCryptographicHash::Sha224 );
7696 else if ( method == QLatin1String(
"sha256" ) )
7698 hash = fcnHash( str, QCryptographicHash::Sha256 );
7700 else if ( method == QLatin1String(
"sha384" ) )
7702 hash = fcnHash( str, QCryptographicHash::Sha384 );
7704 else if ( method == QLatin1String(
"sha512" ) )
7706 hash = fcnHash( str, QCryptographicHash::Sha512 );
7708 else if ( method == QLatin1String(
"sha3_224" ) )
7710 hash = fcnHash( str, QCryptographicHash::Sha3_224 );
7712 else if ( method == QLatin1String(
"sha3_256" ) )
7714 hash = fcnHash( str, QCryptographicHash::Sha3_256 );
7716 else if ( method == QLatin1String(
"sha3_384" ) )
7718 hash = fcnHash( str, QCryptographicHash::Sha3_384 );
7720 else if ( method == QLatin1String(
"sha3_512" ) )
7722 hash = fcnHash( str, QCryptographicHash::Sha3_512 );
7724 else if ( method == QLatin1String(
"keccak_224" ) )
7726 hash = fcnHash( str, QCryptographicHash::Keccak_224 );
7728 else if ( method == QLatin1String(
"keccak_256" ) )
7730 hash = fcnHash( str, QCryptographicHash::Keccak_256 );
7732 else if ( method == QLatin1String(
"keccak_384" ) )
7734 hash = fcnHash( str, QCryptographicHash::Keccak_384 );
7736 else if ( method == QLatin1String(
"keccak_512" ) )
7738 hash = fcnHash( str, QCryptographicHash::Keccak_512 );
7742 parent->
setEvalErrorString( QObject::tr(
"Hash method %1 is not available on this system." ).arg( str ) );
7749 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Md5 );
7754 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Sha256 );
7759 const QByteArray input = values.at( 0 ).toByteArray();
7760 return QVariant( QString( input.toBase64() ) );
7765 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7767 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7769 query.addQueryItem( it.key(), it.value().toString() );
7771 return query.toString( QUrl::ComponentFormattingOption::FullyEncoded );
7776 const QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7777 const QByteArray base64 = value.toLocal8Bit();
7778 const QByteArray decoded = QByteArray::fromBase64( base64 );
7779 return QVariant( decoded );
7784static 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 )
7789 parent->
setEvalErrorString( QStringLiteral(
"This function was called without an expression context." ) );
7793 const QVariant sourceLayerRef = context->
variable( QStringLiteral(
"layer" ) );
7796 QgsVectorLayer *sourceLayer = QgsExpressionUtils::getVectorLayer( sourceLayerRef, context, parent );
7805 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
7808 const bool layerCanBeCached = node->
isStatic( parent, context );
7809 QVariant targetLayerValue = node->
eval( parent, context );
7813 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
7815 QString subExpString = node->dump();
7817 bool testOnly = ( subExpString ==
"NULL" );
7820 QgsVectorLayer *targetLayer = QgsExpressionUtils::getVectorLayer( targetLayerValue, context, parent );
7824 parent->
setEvalErrorString( QObject::tr(
"Layer '%1' could not be loaded." ).arg( targetLayerValue.toString() ) );
7829 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
7831 QString filterString = node->dump();
7832 if ( filterString !=
"NULL" )
7834 request.setFilterExpression( filterString );
7838 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
7840 QVariant limitValue = node->eval( parent, context );
7842 qlonglong limit = QgsExpressionUtils::getIntValue( limitValue, parent );
7845 double max_distance = 0;
7846 if ( isNearestFunc )
7848 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
7850 QVariant distanceValue = node->eval( parent, context );
7852 max_distance = QgsExpressionUtils::getDoubleValue( distanceValue, parent );
7856 node = QgsExpressionUtils::getNode( values.at( isNearestFunc ? 5 : 4 ), parent );
7858 QVariant cacheValue = node->eval( parent, context );
7860 bool cacheEnabled = cacheValue.toBool();
7866 double minOverlap { -1 };
7867 double minInscribedCircleRadius { -1 };
7868 bool returnDetails =
false;
7869 bool sortByMeasure =
false;
7870 bool sortAscending =
false;
7871 bool requireMeasures =
false;
7872 bool overlapOrRadiusFilter =
false;
7873 if ( isIntersectsFunc )
7876 node = QgsExpressionUtils::getNode( values.at( 5 ), parent );
7878 const QVariant minOverlapValue = node->eval( parent, context );
7880 minOverlap = QgsExpressionUtils::getDoubleValue( minOverlapValue, parent );
7881 node = QgsExpressionUtils::getNode( values.at( 6 ), parent );
7883 const QVariant minInscribedCircleRadiusValue = node->eval( parent, context );
7885 minInscribedCircleRadius = QgsExpressionUtils::getDoubleValue( minInscribedCircleRadiusValue, parent );
7886 node = QgsExpressionUtils::getNode( values.at( 7 ), parent );
7888 returnDetails = !testOnly && node->eval( parent, context ).toBool();
7889 node = QgsExpressionUtils::getNode( values.at( 8 ), parent );
7891 const QString sorting { node->eval( parent, context ).toString().toLower() };
7892 sortByMeasure = !testOnly && ( sorting.startsWith(
"asc" ) || sorting.startsWith(
"des" ) );
7893 sortAscending = sorting.startsWith(
"asc" );
7894 requireMeasures = sortByMeasure || returnDetails;
7895 overlapOrRadiusFilter = minInscribedCircleRadius != -1 || minOverlap != -1;
7902 if ( sourceLayer && targetLayer->crs() != sourceLayer->crs() )
7905 request.setDestinationCrs( sourceLayer->crs(), TransformContext );
7908 bool sameLayers = ( sourceLayer && sourceLayer->id() == targetLayer->id() );
7911 if ( bboxGrow != 0 )
7913 intDomain.
grow( bboxGrow );
7916 const QString cacheBase { QStringLiteral(
"%1:%2:%3" ).arg( targetLayer->id(), subExpString, filterString ) };
7922 QList<QgsFeature> features;
7923 if ( isNearestFunc || ( layerCanBeCached && cacheEnabled ) )
7927 const QString cacheLayer { QStringLiteral(
"ovrlaylyr:%1" ).arg( cacheBase ) };
7928 const QString cacheIndex { QStringLiteral(
"ovrlayidx:%1" ).arg( cacheBase ) };
7932 cachedTarget = targetLayer->
materialize( request );
7933 if ( layerCanBeCached )
7934 context->
setCachedValue( cacheLayer, QVariant::fromValue( cachedTarget ) );
7944 if ( layerCanBeCached )
7945 context->
setCachedValue( cacheIndex, QVariant::fromValue( spatialIndex ) );
7952 QList<QgsFeatureId> fidsList;
7953 if ( isNearestFunc )
7955 fidsList = spatialIndex.
nearestNeighbor( geometry, sameLayers ? limit + 1 : limit, max_distance );
7959 fidsList = spatialIndex.
intersects( intDomain );
7962 QListIterator<QgsFeatureId> i( fidsList );
7963 while ( i.hasNext() )
7966 if ( sameLayers && feat.
id() == fId2 )
7968 features.append( cachedTarget->
getFeature( fId2 ) );
7976 request.setFilterRect( intDomain );
7981 if ( sameLayers && feat.
id() == feat2.
id() )
7983 features.append( feat2 );
7991 const QString expCacheKey { QStringLiteral(
"exp:%1" ).arg( cacheBase ) };
7992 const QString ctxCacheKey { QStringLiteral(
"ctx:%1" ).arg( cacheBase ) };
7998 subExpression.
prepare( &subContext );
8011 auto testLinestring = [ = ](
const QgsGeometry intersection,
double & overlapValue ) ->
bool
8013 bool testResult {
false };
8015 QVector<double> overlapValues;
8019 const QgsCurve *geom = qgsgeometry_cast< const QgsCurve * >( *it );
8021 if ( minOverlap != -1 || requireMeasures )
8023 overlapValue = geom->
length();
8024 overlapValues.append( overlapValue );
8025 if ( minOverlap != -1 )
8027 if ( overlapValue >= minOverlap )
8039 if ( ! overlapValues.isEmpty() )
8041 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
8048 auto testPolygon = [ = ](
const QgsGeometry intersection,
double & radiusValue,
double & overlapValue ) ->
bool
8051 bool testResult {
false };
8053 QVector<double> overlapValues;
8054 QVector<double> radiusValues;
8057 const QgsCurvePolygon *geom = qgsgeometry_cast< const QgsCurvePolygon * >( *it );
8059 if ( minOverlap != -1 || requireMeasures )
8061 overlapValue = geom->
area();
8062 overlapValues.append( geom->
area() );
8063 if ( minOverlap != - 1 )
8065 if ( overlapValue >= minOverlap )
8077 if ( minInscribedCircleRadius != -1 || requireMeasures )
8080 const double width = bbox.
width();
8081 const double height = bbox.
height();
8082 const double size = width > height ? width : height;
8083 const double tolerance = size / 100.0;
8085 testResult = radiusValue >= minInscribedCircleRadius;
8086 radiusValues.append( radiusValues );
8091 if ( !radiusValues.isEmpty() )
8093 radiusValue = *std::max_element( radiusValues.cbegin(), radiusValues.cend() );
8096 if ( ! overlapValues.isEmpty() )
8098 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
8108 QVariantList results;
8110 QListIterator<QgsFeature> i( features );
8111 while ( i.hasNext() && ( sortByMeasure || limit == -1 || foundCount < limit ) )
8117 if ( ! relationFunction || ( geometry.*relationFunction )( feat2.
geometry() ) )
8120 double overlapValue = -1;
8121 double radiusValue = -1;
8123 if ( isIntersectsFunc && ( requireMeasures || overlapOrRadiusFilter ) )
8136 for (
const auto &geom : std::as_const( geometries ) )
8138 switch ( geom.type() )
8142 poly.append( geom.asPolygon() );
8147 line.append( geom.asPolyline() );
8152 point.append( geom.asPoint() );
8163 switch ( geometry.
type() )
8191 switch ( intersection.
type() )
8198 bool testResult { testPolygon( intersection, radiusValue, overlapValue ) };
8200 if ( ! testResult && overlapOrRadiusFilter )
8213 if ( minInscribedCircleRadius != -1 )
8219 const bool testResult { testLinestring( intersection, overlapValue ) };
8221 if ( ! testResult && overlapOrRadiusFilter )
8234 if ( minInscribedCircleRadius != -1 )
8239 bool testResult {
false };
8240 if ( minOverlap != -1 || requireMeasures )
8260 testResult = testLinestring( feat2.
geometry(), overlapValue );
8265 testResult = testPolygon( feat2.
geometry(), radiusValue, overlapValue );
8271 if ( ! testResult && overlapOrRadiusFilter )
8299 const QVariant expResult = subExpression.
evaluate( &subContext );
8301 if ( requireMeasures )
8303 QVariantMap resultRecord;
8304 resultRecord.insert( QStringLiteral(
"id" ), feat2.
id() );
8305 resultRecord.insert( QStringLiteral(
"result" ), expResult );
8307 resultRecord.insert( QStringLiteral(
"overlap" ), overlapValue );
8309 if ( radiusValue != -1 )
8311 resultRecord.insert( QStringLiteral(
"radius" ), radiusValue );
8313 results.append( resultRecord );
8317 results.append( expResult );
8323 results.append( feat2.
id() );
8337 if ( requireMeasures )
8339 if ( sortByMeasure )
8341 std::sort( results.begin(), results.end(), [ sortAscending ](
const QVariant & recordA,
const QVariant & recordB ) ->
bool
8343 return sortAscending ?
8344 recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble()
8345 : recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble();
8349 if ( limit > 0 && results.size() > limit )
8351 results.erase( results.begin() + limit );
8354 if ( ! returnDetails )
8356 QVariantList expResults;
8357 for (
auto it = results.constBegin(); it != results.constEnd(); ++it )
8359 expResults.append( it->toMap().value( QStringLiteral(
"result" ) ) );
8369 QVariantList disjoint_results;
8378 if ( !results.contains( feat2.
id() ) )
8381 disjoint_results.append( subExpression.
evaluate( &subContext ) );
8384 return disjoint_results;
8427 return executeGeomOverlay( values, context, parent,
nullptr,
false, 0,
true );
8436 QMutexLocker locker( &sFunctionsMutex );
8438 QList<QgsExpressionFunction *> &functions = *sFunctions();
8440 if ( functions.isEmpty() )
8478 functions << randFunc;
8482 functions << randfFunc;
8485 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max" ), -1, fcnMax, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8486 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min" ), -1, fcnMin, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8493 <<
new QgsStaticExpressionFunction( QStringLiteral(
"pi" ), 0, fcnPi, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$pi" ) )
8498 <<
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" ) )
8499 <<
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" ) )
8500 <<
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" ) )
8505 <<
new QgsStaticExpressionFunction( QStringLiteral(
"coalesce" ), -1, fcnCoalesce, QStringLiteral(
"Conditionals" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8519 QStringLiteral(
"Aggregates" ),
8528 if ( !node->
args() )
8531 QSet<QString> referencedVars;
8543 return referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() );
8552 if ( !node->
args() )
8553 return QSet<QString>();
8555 QSet<QString> referencedCols;
8556 QSet<QString> referencedVars;
8571 if ( referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() ) )
8574 return referencedCols;
8587 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count" ), aggParams, fcnAggregateCount, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8588 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_distinct" ), aggParams, fcnAggregateCountDistinct, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8589 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_missing" ), aggParams, fcnAggregateCountMissing, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8590 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minimum" ), aggParams, fcnAggregateMin, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8591 <<
new QgsStaticExpressionFunction( QStringLiteral(
"maximum" ), aggParams, fcnAggregateMax, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8592 <<
new QgsStaticExpressionFunction( QStringLiteral(
"sum" ), aggParams, fcnAggregateSum, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8593 <<
new QgsStaticExpressionFunction( QStringLiteral(
"mean" ), aggParams, fcnAggregateMean, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8594 <<
new QgsStaticExpressionFunction( QStringLiteral(
"median" ), aggParams, fcnAggregateMedian, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8595 <<
new QgsStaticExpressionFunction( QStringLiteral(
"stdev" ), aggParams, fcnAggregateStdev, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8596 <<
new QgsStaticExpressionFunction( QStringLiteral(
"range" ), aggParams, fcnAggregateRange, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8597 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minority" ), aggParams, fcnAggregateMinority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8598 <<
new QgsStaticExpressionFunction( QStringLiteral(
"majority" ), aggParams, fcnAggregateMajority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8599 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q1" ), aggParams, fcnAggregateQ1, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8600 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q3" ), aggParams, fcnAggregateQ3, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8601 <<
new QgsStaticExpressionFunction( QStringLiteral(
"iqr" ), aggParams, fcnAggregateIQR, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8602 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min_length" ), aggParams, fcnAggregateMinLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8603 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max_length" ), aggParams, fcnAggregateMaxLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8604 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect" ), aggParams, fcnAggregateCollectGeometry, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8605 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate" ), aggParamsConcat, fcnAggregateStringConcat, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8606 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate_unique" ), aggParamsConcat, fcnAggregateStringConcatUnique, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8607 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array_agg" ), aggParamsArray, fcnAggregateArray, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8612 <<
new QgsStaticExpressionFunction( QStringLiteral(
"now" ), 0, fcnNow, QStringLiteral(
"Date and Time" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$now" ) )
8615 fcnAge, QStringLiteral(
"Date and Time" ) )
8629 fcnMakeDate, QStringLiteral(
"Date and Time" ) )
8633 fcnMakeTime, QStringLiteral(
"Date and Time" ) )
8640 fcnMakeDateTime, QStringLiteral(
"Date and Time" ) )
8648 fcnMakeInterval, QStringLiteral(
"Date and Time" ) )
8674 false, QSet< QString >(),
false, QStringList(), true )
8675 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concat" ), -1, fcnConcat, QStringLiteral(
"String" ), QString(),
false, QSet<QString>(),
false, QStringList(), true )
8693 fcnColorMixRgb, QStringLiteral(
"Color" ) )
8697 fcnColorMix, QStringLiteral(
"Color" ) )
8701 fcnColorRgb, QStringLiteral(
"Color" ) )
8706 fcnColorRgbF, QStringLiteral(
"Color" ) )
8711 fncColorRgba, QStringLiteral(
"Color" ) )
8720 fcnCreateRamp, QStringLiteral(
"Color" ) )
8724 fcnColorHsl, QStringLiteral(
"Color" ) )
8729 fncColorHsla, QStringLiteral(
"Color" ) )
8734 fcnColorHslF, QStringLiteral(
"Color" ) )
8738 fcnColorHsv, QStringLiteral(
"Color" ) )
8743 fncColorHsva, QStringLiteral(
"Color" ) )
8748 fcnColorHsvF, QStringLiteral(
"Color" ) )
8753 fcnColorCmyk, QStringLiteral(
"Color" ) )
8759 fncColorCmyka, QStringLiteral(
"Color" ) )
8765 fcnColorCmykF, QStringLiteral(
"Color" ) )
8768 fncColorPart, QStringLiteral(
"Color" ) )
8771 fncDarker, QStringLiteral(
"Color" ) )
8774 fncLighter, QStringLiteral(
"Color" ) )
8779 fcnBaseFileName, QStringLiteral(
"Files and Paths" ) )
8781 fcnFileSuffix, QStringLiteral(
"Files and Paths" ) )
8783 fcnFileExists, QStringLiteral(
"Files and Paths" ) )
8785 fcnFileName, QStringLiteral(
"Files and Paths" ) )
8787 fcnPathIsFile, QStringLiteral(
"Files and Paths" ) )
8789 fcnPathIsDir, QStringLiteral(
"Files and Paths" ) )
8791 fcnFilePath, QStringLiteral(
"Files and Paths" ) )
8793 fcnFileSize, QStringLiteral(
"Files and Paths" ) )
8796 fcnExif, QStringLiteral(
"Files and Paths" ) )
8798 fcnExifGeoTag, QStringLiteral(
"GeometryGroup" ) )
8802 fcnGenericHash, QStringLiteral(
"Conversions" ) )
8804 fcnHashMd5, QStringLiteral(
"Conversions" ) )
8806 fcnHashSha256, QStringLiteral(
"Conversions" ) )
8810 fcnToBase64, QStringLiteral(
"Conversions" ) )
8812 fcnFromBase64, QStringLiteral(
"Conversions" ) )
8818 geomFunc->setIsStatic(
false );
8819 functions << geomFunc;
8823 functions << areaFunc;
8829 functions << lengthFunc;
8833 functions << perimeterFunc;
8839 fcnRoundness, QStringLiteral(
"GeometryGroup" ) );
8853 QMap< QString, QgsExpressionFunction::FcnEval > geometry_overlay_definitions
8855 { QStringLiteral(
"overlay_intersects" ), fcnGeomOverlayIntersects },
8856 { QStringLiteral(
"overlay_contains" ), fcnGeomOverlayContains },
8857 { QStringLiteral(
"overlay_crosses" ), fcnGeomOverlayCrosses },
8858 { QStringLiteral(
"overlay_equals" ), fcnGeomOverlayEquals },
8859 { QStringLiteral(
"overlay_touches" ), fcnGeomOverlayTouches },
8860 { QStringLiteral(
"overlay_disjoint" ), fcnGeomOverlayDisjoint },
8861 { QStringLiteral(
"overlay_within" ), fcnGeomOverlayWithin },
8863 QMapIterator< QString, QgsExpressionFunction::FcnEval > i( geometry_overlay_definitions );
8864 while ( i.hasNext() )
8881 functions << fcnGeomOverlayFunc;
8894 functions << fcnGeomOverlayNearestFunc;
8907 fcnNodesToPoints, QStringLiteral(
"GeometryGroup" ) )
8909 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect_geometries" ), -1, fcnCollectGeometries, QStringLiteral(
"GeometryGroup" ) )
8914 fcnMakePointM, QStringLiteral(
"GeometryGroup" ) )
8920 fcnMakeTriangle, QStringLiteral(
"GeometryGroup" ) )
8925 fcnMakeCircle, QStringLiteral(
"GeometryGroup" ) )
8932 fcnMakeEllipse, QStringLiteral(
"GeometryGroup" ) )
8938 fcnMakeRegularPolygon, QStringLiteral(
"GeometryGroup" ) )
8942 fcnMakeSquare, QStringLiteral(
"GeometryGroup" ) )
8948 fcnMakeRectangleFrom3Points, QStringLiteral(
"GeometryGroup" ) )
8952#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
8958 }, fcnGeomMakeValid, QStringLiteral(
"GeometryGroup" ) );
8967 functions << xAtFunc;
8972 functions << yAtFunc;
8988 fcnDisjoint, QStringLiteral(
"GeometryGroup" ) )
8991 fcnIntersects, QStringLiteral(
"GeometryGroup" ) )
8994 fcnTouches, QStringLiteral(
"GeometryGroup" ) )
8997 fcnCrosses, QStringLiteral(
"GeometryGroup" ) )
9000 fcnContains, QStringLiteral(
"GeometryGroup" ) )
9003 fcnOverlaps, QStringLiteral(
"GeometryGroup" ) )
9006 fcnWithin, QStringLiteral(
"GeometryGroup" ) )
9010 fcnTranslate, QStringLiteral(
"GeometryGroup" ) )
9015 fcnRotate, QStringLiteral(
"GeometryGroup" ) )
9020 fcnScale, QStringLiteral(
"GeometryGroup" ) )
9031 fcnAffineTransform, QStringLiteral(
"GeometryGroup" ) )
9038 fcnBuffer, QStringLiteral(
"GeometryGroup" ) )
9040 fcnForceRHR, QStringLiteral(
"GeometryGroup" ) )
9042 fcnForcePolygonCW, QStringLiteral(
"GeometryGroup" ) )
9044 fcnForcePolygonCCW, QStringLiteral(
"GeometryGroup" ) )
9054 , fcnTaperedBuffer, QStringLiteral(
"GeometryGroup" ) )
9057 , fcnBufferByM, QStringLiteral(
"GeometryGroup" ) )
9063 fcnOffsetCurve, QStringLiteral(
"GeometryGroup" ) )
9069 fcnSingleSidedBuffer, QStringLiteral(
"GeometryGroup" ) )
9073 fcnExtend, QStringLiteral(
"GeometryGroup" ) )
9082 fcnInteriorRingN, QStringLiteral(
"GeometryGroup" ) )
9085 fcnGeometryN, QStringLiteral(
"GeometryGroup" ) )
9092 }, fcnSharedPaths, QStringLiteral(
"GeometryGroup" ) )
9106 }, fcnTriangularWave, QStringLiteral(
"GeometryGroup" ) )
9115 }, fcnTriangularWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9122 }, fcnSquareWave, QStringLiteral(
"GeometryGroup" ) )
9131 }, fcnSquareWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9138 }, fcnRoundWave, QStringLiteral(
"GeometryGroup" ) )
9147 }, fcnRoundWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
9156 }, fcnApplyDashPattern, QStringLiteral(
"GeometryGroup" ) )
9161 }, fcnDensifyByCount, QStringLiteral(
"GeometryGroup" ) )
9166 }, fcnDensifyByDistance, QStringLiteral(
"GeometryGroup" ) )
9178#
if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
9185 fcnOrientedBBox, QStringLiteral(
"GeometryGroup" ) )
9188 fcnMainAngle, QStringLiteral(
"GeometryGroup" ) )
9192 fcnMinimalCircle, QStringLiteral(
"GeometryGroup" ) )
9195 fcnDifference, QStringLiteral(
"GeometryGroup" ) )
9198 fcnDistance, QStringLiteral(
"GeometryGroup" ) )
9201 fcnHausdorffDistance, QStringLiteral(
"GeometryGroup" ) )
9204 fcnIntersection, QStringLiteral(
"GeometryGroup" ) )
9207 fcnSymDifference, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"symDifference" ) )
9210 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
9213 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
9216 fcnGeomToWKT, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"geomToWKT" ) )
9218 fcnGeomToWKB, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false )
9223 fcnTransformGeometry, QStringLiteral(
"GeometryGroup" ) )
9227 fcnExtrude, QStringLiteral(
"GeometryGroup" ), QString() )
9229 fcnGeomIsMultipart, QStringLiteral(
"GeometryGroup" ) )
9231 fcnZMax, QStringLiteral(
"GeometryGroup" ) )
9233 fcnZMin, QStringLiteral(
"GeometryGroup" ) )
9235 fcnMMax, QStringLiteral(
"GeometryGroup" ) )
9237 fcnMMin, QStringLiteral(
"GeometryGroup" ) )
9239 fcnSinuosity, QStringLiteral(
"GeometryGroup" ) )
9241 fcnStraightDistance2d, QStringLiteral(
"GeometryGroup" ) );
9247 fcnOrderParts, QStringLiteral(
"GeometryGroup" ), QString() );
9252 const QList< QgsExpressionNode *> argList = node->
args()->list();
9255 if ( !argNode->isStatic( parent, context ) )
9263 QString expString = argNode->
eval( parent, context ).toString();
9267 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9279 QString
expression = argNode->
eval( parent, context ).toString();
9281 e.prepare( context );
9287 functions << orderPartsFunc;
9292 fcnClosestPoint, QStringLiteral(
"GeometryGroup" ) )
9295 fcnShortestLine, QStringLiteral(
"GeometryGroup" ) )
9300 fcnLineInterpolatePointByM, QStringLiteral(
"GeometryGroup" ) )
9307 fcnLineLocateM, QStringLiteral(
"GeometryGroup" ) )
9320 functions << idFunc;
9324 functions << currentFeatureFunc;
9326 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" ) );
9328 functions << uuidFunc;
9335 fcnGetFeature, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"QgsExpressionUtils::getFeature" ) )
9338 fcnGetFeatureById, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false );
9343 functions << attributesFunc;
9347 functions << representAttributesFunc;
9355 functions << validateFeature;
9364 functions << validateAttribute;
9367 QStringLiteral(
"maptip" ),
9370 QStringLiteral(
"Record and Attributes" ),
9376 functions << maptipFunc;
9379 QStringLiteral(
"display_expression" ),
9381 fcnFeatureDisplayExpression,
9382 QStringLiteral(
"Record and Attributes" ),
9388 functions << displayFunc;
9391 QStringLiteral(
"is_selected" ),
9394 QStringLiteral(
"Record and Attributes" ),
9400 functions << isSelectedFunc;
9404 QStringLiteral(
"num_selected" ),
9407 QStringLiteral(
"Record and Attributes" ),
9415 QStringLiteral(
"sqlite_fetch_and_increment" ),
9423 fcnSqliteFetchAndIncrement,
9424 QStringLiteral(
"Record and Attributes" )
9448 parent->
setEvalErrorString( tr(
"If represent_value is called with 1 parameter, it must be an attribute." ) );
9458 parent->
setEvalErrorString( tr(
"represent_value must be called with exactly 1 or 2 parameters." ) );
9464 functions << representValueFunc;
9470 fcnGetLayerProperty, QStringLiteral(
"Map Layers" ) )
9475 fcnDecodeUri, QStringLiteral(
"Map Layers" ) )
9479 fcnMimeType, QStringLiteral(
"General" ) )
9496 QgsExpressionNode *argNode = node->args()->at( 0 );
9498 if ( !argNode->isStatic( parent, context ) )
9501 const QString varName = argNode->eval( parent, context ).toString();
9502 if ( varName == QLatin1String(
"feature" ) || varName == QLatin1String(
"id" ) || varName == QLatin1String(
"geometry" ) )
9505 const QgsExpressionContextScope *scope = context->activeScopeForVariable( varName );
9506 return scope ? scope->isStatic( varName ) : false;
9514 if ( node && node->
args()->
count() > 0 )
9519 if ( literal->value() == QLatin1String(
"geometry" ) || literal->value() == QLatin1String(
"feature" ) )
9536 QgsExpressionNode *argNode = node->args()->at( 0 );
9538 if ( argNode->isStatic( parent, context ) )
9540 QString expString = argNode->eval( parent, context ).toString();
9542 QgsExpression e( expString );
9544 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9551 functions << evalTemplateFunction;
9559 QgsExpressionNode *argNode = node->args()->at( 0 );
9561 if ( argNode->isStatic( parent, context ) )
9563 QString expString = argNode->eval( parent, context ).toString();
9565 QgsExpression e( expString );
9567 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9575 functions << evalFunc;
9581 const QList< QgsExpressionNode *> argList = node->
args()->list();
9584 if ( !argNode->
isStatic( parent, context ) )
9596 functions << attributeFunc;
9607 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array" ), -1, fcnArray, QStringLiteral(
"Arrays" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
9656 fcnMapPrefixKeys, QStringLiteral(
"Maps" ) )
9658 fcnMapToHtmlTable, QStringLiteral(
"Maps" ) )
9660 fcnMapToHtmlDefinitionList, QStringLiteral(
"Maps" ) )
9662 fcnToFormUrlEncode, QStringLiteral(
"Maps" ) )
9671 *sOwnedFunctions() << func;
9672 *sBuiltinFunctions() << func->name();
9673 sBuiltinFunctions()->append( func->aliases() );
9687 QMutexLocker locker( &sFunctionsMutex );
9688 sFunctions()->append( function );
9689 if ( transferOwnership )
9690 sOwnedFunctions()->append( function );
9705 QMutexLocker locker( &sFunctionsMutex );
9706 sFunctions()->removeAt( fnIdx );
9707 sFunctionIndexMap.clear();
9715 qDeleteAll( *sOwnedFunctions() );
9716 sOwnedFunctions()->clear();
9721 if ( sBuiltinFunctions()->isEmpty() )
9725 return *sBuiltinFunctions();
9732 QStringLiteral(
"Arrays" ) )
9743 if ( args->
count() < 2 )
9746 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9756 QVariantList result;
9758 if ( args->
count() < 2 )
9762 QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9765 std::unique_ptr< QgsExpressionContext > tempContext;
9768 tempContext = std::make_unique< QgsExpressionContext >();
9769 subContext = tempContext.get();
9776 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it, ++i )
9780 result << args->
at( 1 )->
eval( parent, subContext );
9805 if ( args->
count() < 2 )
9809 args->
at( 0 )->
prepare( parent, context );
9813 subContext = *context;
9820 args->
at( 1 )->
prepare( parent, &subContext );
9830 QStringLiteral(
"Arrays" ) )
9841 if ( args->
count() < 2 )
9844 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9854 QVariantList result;
9856 if ( args->
count() < 2 )
9860 const QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9863 std::unique_ptr< QgsExpressionContext > tempContext;
9866 tempContext = std::make_unique< QgsExpressionContext >();
9867 subContext = tempContext.get();
9874 if ( args->
count() >= 3 )
9876 const QVariant limitVar = args->
at( 2 )->
eval( parent, context );
9878 if ( QgsExpressionUtils::isIntSafe( limitVar ) )
9880 limit = limitVar.toInt();
9888 for (
const QVariant &value : array )
9891 if ( args->
at( 1 )->
eval( parent, subContext ).toBool() )
9895 if ( limit > 0 && limit == result.size() )
9895 if ( limit > 0 && limit == result.size() ) {
…}
9922 if ( args->
count() < 2 )
9926 args->
at( 0 )->
prepare( parent, context );
9930 subContext = *context;
9936 args->
at( 1 )->
prepare( parent, &subContext );
9945 QStringLiteral(
"General" ) )
9956 if ( args->
count() < 3 )
9960 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9962 QVariant
name = args->
at( 0 )->
eval( parent, context );
9963 QVariant value = args->
at( 1 )->
eval( parent, context );
9966 appendTemporaryVariable( context,
name.toString(), value );
9967 if ( args->
at( 2 )->
isStatic( parent, context ) )
9969 popTemporaryVariable( context );
9980 if ( args->
count() < 3 )
9984 QVariant
name = args->
at( 0 )->
eval( parent, context );
9985 QVariant value = args->
at( 1 )->
eval( parent, context );
9988 std::unique_ptr< QgsExpressionContext > tempContext;
9989 if ( !updatedContext )
9991 tempContext = std::make_unique< QgsExpressionContext >();
9992 updatedContext = tempContext.get();
9995 appendTemporaryVariable( updatedContext,
name.toString(), value );
9996 result = args->
at( 2 )->
eval( parent, updatedContext );
9999 popTemporaryVariable( updatedContext );
10008 Q_UNUSED( context )
10020 if ( args->
count() < 3 )
10025 QVariant value = args->
at( 1 )->
prepare( parent, context );
10028 std::unique_ptr< QgsExpressionContext > tempContext;
10029 if ( !updatedContext )
10031 tempContext = std::make_unique< QgsExpressionContext >();
10032 updatedContext = tempContext.get();
10035 appendTemporaryVariable( updatedContext,
name.toString(), value );
10036 args->
at( 2 )->
prepare( parent, updatedContext );
10039 popTemporaryVariable( updatedContext );
10044void QgsWithVariableExpressionFunction::popTemporaryVariable(
const QgsExpressionContext *context )
const
10047 delete updatedContext->
popScope();
10050void QgsWithVariableExpressionFunction::appendTemporaryVariable(
const QgsExpressionContext *context,
const QString &name,
const QVariant &value )
const
@ Left
Buffer to left of line.
DashPatternSizeAdjustment
Dash pattern size adjustment options.
@ ScaleDashOnly
Only dash lengths are adjusted.
@ ScaleBothDashAndGap
Both the dash and gap lengths are adjusted equally.
@ ScaleGapOnly
Only gap lengths are adjusted.
@ Success
Operation succeeded.
@ Visvalingam
The simplification gives each point in a line an importance weighting, so that least important points...
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
JoinStyle
Join styles for buffers.
@ Bevel
Use beveled joins.
@ Round
Use rounded joins.
@ Miter
Use mitered joins.
RasterBandStatistic
Available raster band statistics.
@ StdDev
Standard deviation.
@ NoStatistic
No statistic.
@ Group
Composite group layer. Added in QGIS 3.24.
@ Plugin
Plugin based layer.
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
EndCapStyle
End cap styles for buffers.
@ Flat
Flat cap (in line with start/end of line)
@ Square
Square cap (extends past start/end of line by buffer distance)
Aggregate
Available aggregates to calculate.
@ StringMinimumLength
Minimum length of string (string fields only)
@ FirstQuartile
First quartile (numeric fields only)
@ Mean
Mean of values (numeric fields only)
@ Median
Median of values (numeric fields only)
@ StringMaximumLength
Maximum length of string (string fields only)
@ Range
Range of values (max - min) (numeric and datetime fields only)
@ StringConcatenateUnique
Concatenate unique values with a joining string (string fields only). Specify the delimiter using set...
@ Minority
Minority of values.
@ CountMissing
Number of missing (null) values.
@ ArrayAggregate
Create an array of values.
@ Majority
Majority of values.
@ StDevSample
Sample standard deviation of values (numeric fields only)
@ ThirdQuartile
Third quartile (numeric fields only)
@ CountDistinct
Number of distinct values.
@ StringConcatenate
Concatenate values with a joining string (string fields only). Specify the delimiter using setDelimit...
@ GeometryCollect
Create a multipart geometry from aggregated geometries.
@ InterQuartileRange
Inter quartile range (IQR) (numeric fields only)
DashPatternLineEndingRule
Dash pattern line ending rules.
@ HalfDash
Start or finish the pattern with a half length dash.
@ HalfGap
Start or finish the pattern with a half length gap.
@ FullGap
Start or finish the pattern with a full gap.
@ FullDash
Start or finish the pattern with a full dash.
MakeValidMethod
Algorithms to use when repairing invalid geometries.
@ Linework
Combines all rings into a set of noded lines and then extracts valid polygons from that linework.
@ Structure
Structured method, first makes all rings valid and then merges shells and subtracts holes from shells...
@ GeometryCollection
GeometryCollection.
Abstract base class for all geometries.
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
virtual QgsAbstractGeometry * boundary() const =0
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
virtual const QgsAbstractGeometry * simplifiedTypeRef() const
Returns a reference to the simplest lossless representation of this geometry, e.g.
bool isMeasure() const
Returns true if the geometry contains m values.
virtual QgsRectangle boundingBox() const
Returns the minimal bounding box for the geometry.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
part_iterator parts_end()
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
virtual double length() const
Returns the planar, 2-dimensional length of the geometry.
virtual QgsCoordinateSequence coordinateSequence() const =0
Retrieves the sequence of geometries, rings and nodes.
virtual int partCount() const =0
Returns count of parts contained in the geometry.
part_iterator parts_begin()
Returns STL-style iterator pointing to the first part of the geometry.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
static Qgis::Aggregate stringToAggregate(const QString &string, bool *ok=nullptr)
Converts a string to a aggregate type.
static QgsFieldFormatterRegistry * fieldFormatterRegistry()
Gets the registry of available field formatters.
Handles the array_filter(array, expression) expression function.
QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Returns result of evaluating the function.
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Evaluates the function, first evaluating all required arguments before passing them to the function's...
QgsArrayFilterExpressionFunction()
Handles the array loopingarray_Foreach(array, expression) expression function.
QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Returns result of evaluating the function.
QgsArrayForeachExpressionFunction()
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Evaluates the function, first evaluating all required arguments before passing them to the function's...
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
Abstract base class for color ramps.
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
Represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QString toProj() const
Returns a Proj string representation of this CRS.
QString ellipsoidAcronym() const
Returns the ellipsoid acronym for the ellipsoid used by the CRS.
Qgis::DistanceUnit mapUnits
Contains information about the context in which a coordinate transform is executed.
Custom exception class for Coordinate Reference System related exceptions.
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
bool isEmpty() const override
Returns true if the geometry is empty.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
double area() const override
Returns the planar, 2-dimensional area of the geometry.
double roundness() const
Returns the roundness of the curve polygon.
int ringCount(int part=0) const override
Returns the number of rings of which this geometry is built.
Abstract base class for curved geometry type.
double sinuosity() const
Returns the curve sinuosity, which is the ratio of the curve length() to curve straightDistance2d().
QgsCurve * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
virtual QgsCurve * curveSubstring(double startDistance, double endDistance) const =0
Returns a new curve representing a substring of this curve.
virtual bool isClosed() const
Returns true if the curve is closed.
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
double straightDistance2d() const
Returns the straight distance of the curve, i.e.
virtual QgsCurve * reversed() const =0
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
double measureArea(const QgsGeometry &geometry) const
Measures the area of a geometry.
double convertLengthMeasurement(double length, Qgis::DistanceUnit toUnits) const
Takes a length measurement calculated by this QgsDistanceArea object and converts it to a different d...
double measurePerimeter(const QgsGeometry &geometry) const
Measures the perimeter of a polygon geometry.
double measureLength(const QgsGeometry &geometry) const
Measures the length of a geometry.
double bearing(const QgsPointXY &p1, const QgsPointXY &p2) const
Computes the bearing (in radians) between two points.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
double convertAreaMeasurement(double area, Qgis::AreaUnit toUnits) const
Takes an area measurement calculated by this QgsDistanceArea object and converts it to a different ar...
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
bool isStatic(const QString &name) const
Tests whether the variable with the specified name is static and can be cached.
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
static void registerContextFunctions()
Registers all known core functions provided by QgsExpressionContextScope objects.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
void setCachedValue(const QString &key, const QVariant &value) const
Sets a value to cache within the expression context.
QString uniqueHash(bool &ok, const QSet< QString > &variables=QSet< QString >()) const
Returns a unique hash representing the current state of the context.
QgsGeometry geometry() const
Convenience function for retrieving the geometry for the context, if set.
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
QgsExpressionContextScope * activeScopeForVariable(const QString &name)
Returns the currently active scope from the context for a specified variable name.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly by the expression to check if evaluation sh...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
bool hasGeometry() const
Returns true if the context has a geometry associated with it.
bool hasCachedValue(const QString &key) const
Returns true if the expression context contains a cached value with a matching key.
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
QVariant cachedValue(const QString &key) const
Returns the matching cached value, if set.
bool hasFeature() const
Returns true if the context has a feature associated with it.
QgsFields fields() const
Convenience function for retrieving the fields for the context, if set.
Represents a single parameter passed to a function.
An abstract base class for defining QgsExpression functions.
QList< QgsExpressionFunction::Parameter > ParameterList
List of parameters, used for function definition.
bool operator==(const QgsExpressionFunction &other) const
virtual bool isDeprecated() const
Returns true if the function is deprecated and should not be presented as a valid option to users in ...
virtual bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
Will be called during prepare to determine if the function is static.
virtual QStringList aliases() const
Returns a list of possible aliases for the function.
bool lazyEval() const
true if this function should use lazy evaluation.
static bool allParamsStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context)
This will return true if all the params for the provided function node are static within the constrai...
QString name() const
The name of the function.
virtual QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
Evaluates the function, first evaluating all required arguments before passing them to the function's...
virtual QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)=0
Returns result of evaluating the function.
virtual QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const
Returns a set of field names which are required for this function.
virtual bool handlesNull() const
Returns true if the function handles NULL values in arguments by itself, and the default NULL value h...
virtual bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
This will be called during the prepare step() of an expression if it is not static.
virtual bool usesGeometry(const QgsExpressionNodeFunction *node) const
Does this function use a geometry object.
An expression node which takes its value from a feature's field.
QString name() const
The name of the column.
An expression node for expression functions.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
An expression node for literal values.
A list of expression nodes.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
QgsExpressionNode * at(int i)
Gets the node at position i in the list.
int count() const
Returns the number of nodes in the list.
Abstract base class for all nodes that can appear in an expression.
virtual QString dump() const =0
Dump this node into a serialized (part) of an expression.
QVariant eval(QgsExpression *parent, const QgsExpressionContext *context)
Evaluate this node with the given context and parent.
virtual bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const =0
Returns true if this node can be evaluated for a static value.
bool prepare(QgsExpression *parent, const QgsExpressionContext *context)
Prepare this node for evaluation.
virtual QSet< QString > referencedColumns() const =0
Abstract virtual method which returns a list of columns required to evaluate this node.
virtual QSet< QString > referencedVariables() const =0
Returns a set of all variables which are used in this expression.
A set of expression-related functions.
Handles parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
static const QList< QgsExpressionFunction * > & Functions()
QString expression() const
Returns the original, unmodified expression string.
static void cleanRegisteredFunctions()
Deletes all registered functions whose ownership have been transferred to the expression engine.
Qgis::DistanceUnit distanceUnits() const
Returns the desired distance units for calculations involving geomCalculator(), e....
static bool registerFunction(QgsExpressionFunction *function, bool transferOwnership=false)
Registers a function to the expression engine.
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
static const QStringList & BuiltinFunctions()
static QString replaceExpressionText(const QString &action, const QgsExpressionContext *context, const QgsDistanceArea *distanceArea=nullptr)
This function replaces each expression between [% and %] in the string with the result of its evaluat...
static PRIVATE QString helpText(QString name)
Returns the help text for a specified function.
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value, QMetaType::Type fieldType=QMetaType::Type::UnknownType)
Create an expression allowing to evaluate if a field is equal to a value.
static bool unregisterFunction(const QString &name)
Unregisters a function from the expression engine.
Qgis::AreaUnit areaUnits() const
Returns the desired areal units for calculations involving geomCalculator(), e.g.,...
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions)
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QVariant evaluate()
Evaluate the feature and return the result.
QgsDistanceArea * geomCalculator()
Returns calculator used for distance and area calculations (used by $length, $area and $perimeter fun...
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
Represents a list of OrderByClauses, with the most important first and the least important last.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsFeatureRequest & setRequestMayBeNested(bool requestMayBeNested)
In case this request may be run nested within another already running iteration on the same connectio...
QgsFeatureRequest & setTimeout(int timeout)
Sets the timeout (in milliseconds) for the maximum time we should wait during feature requests before...
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
void setFeedback(QgsFeedback *feedback)
Attach a feedback object that can be queried regularly by the iterator to check if it should be cance...
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Sets the feature ID that should be fetched.
QgsVectorLayer * materialize(const QgsFeatureRequest &request, QgsFeedback *feedback=nullptr)
Materializes a request (query) made against this feature source, by running it over the source and re...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
bool isValid() const
Returns the validity of this feature.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
ConstraintStrength
Strength of constraints.
@ ConstraintStrengthNotSet
Constraint is not set.
@ ConstraintStrengthSoft
User is warned if constraint is violated but feature can still be accepted.
@ ConstraintStrengthHard
Constraint must be honored before feature can be accepted.
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Container of fields for a vector layer.
Q_INVOKABLE int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
int size() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
virtual bool removeGeometry(int nr)
Removes a geometry from the collection.
QgsGeometryCollection * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
int partCount() const override
Returns count of parts contained in the geometry.
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
static QVector< QgsLineString * > extractLineStrings(const QgsAbstractGeometry *geom)
Returns list of linestrings extracted from the passed geometry.
A geometry is the spatial representation of a feature.
double hausdorffDistanceDensify(const QgsGeometry &geom, double densifyFraction) const
Returns the Hausdorff distance between this geometry and geom.
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Returns a copy of the geometry which has been densified by adding the specified number of extra nodes...
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
double lineLocatePoint(const QgsGeometry &point) const
Returns a distance representing the location along this linestring of the closest point on this lines...
QgsGeometry difference(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing the points making up this geometry that do not make up other.
double length() const
Returns the planar, 2-dimensional length of geometry.
QgsGeometry offsetCurve(double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
QgsGeometry poleOfInaccessibility(double precision, double *distanceToBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
QgsGeometry squareWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs square waves along the boundary of the geometry, with the specified wavelength and amplitu...
QgsGeometry triangularWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs triangular waves along the boundary of the geometry, with the specified wavelength and amp...
bool vertexIdFromVertexNr(int number, QgsVertexId &id) const
Calculates the vertex ID from a vertex number.
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
bool touches(const QgsGeometry &geometry) const
Returns true if the geometry touches another geometry.
QgsGeometry applyDashPattern(const QVector< double > &pattern, Qgis::DashPatternLineEndingRule startRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternLineEndingRule endRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternSizeAdjustment adjustment=Qgis::DashPatternSizeAdjustment::ScaleBothDashAndGap, double patternOffset=0) const
Applies a dash pattern to a geometry, returning a MultiLineString geometry which is the input geometr...
QgsGeometry roundWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs rounded (sine-like) waves along the boundary of the geometry, with the specified wavelengt...
QgsGeometry nearestPoint(const QgsGeometry &other) const
Returns the nearest (closest) point on this geometry to another geometry.
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
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.
static QString build(const QVariantMap &map)
Build a hstore-formatted string from a QVariantMap.
static QVariantMap parse(const QString &string)
Returns a QVariantMap object containing the key and values from a hstore-formatted string.
A representation of the interval between two datetime values.
bool isValid() const
Returns true if the interval is valid.
double days() const
Returns the interval duration in days.
double weeks() const
Returns the interval duration in weeks.
double months() const
Returns the interval duration in months (based on a 30 day month).
double seconds() const
Returns the interval duration in seconds.
double years() const
Returns the interval duration in years (based on an average year length)
double hours() const
Returns the interval duration in hours.
double minutes() const
Returns the interval duration in minutes.
Line string geometry type, with support for z-dimension and m-values.
bool lineLocatePointByM(double m, double &x, double &y, double &z, double &distanceFromStart, bool use3DDistance=true) const
Attempts to locate a point on the linestring by m value.
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
QString dataUrl() const
Returns the DataUrl of the layer used by QGIS Server in GetCapabilities request.
QString attributionUrl() const
Returns the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Base class for all map layer types.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QString source() const
Returns the source for the layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
QgsCoordinateReferenceSystem crs
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
QgsLayerMetadata metadata
QString publicSource(bool hidePassword=false) const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
virtual bool isEditable() const
Returns true if the layer can be edited.
double minimumScale() const
Returns the minimum map scale (i.e.
virtual Q_INVOKABLE QgsDataProvider * dataProvider()
Returns the layer's data provider, it may be nullptr.
double maximumScale() const
Returns the maximum map scale (i.e.
Implementation of a geometry simplifier using the "MapToPixel" algorithm.
@ SimplifyGeometry
The geometries can be simplified using the current map2pixel context state.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
Multi line string geometry collection.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
Multi point geometry collection.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
Custom exception class which is raised when an operation is not supported.
static QgsGeometry geometryFromGML(const QString &xmlString, const QgsOgcUtils::Context &context=QgsOgcUtils::Context())
Static method that creates geometry from GML.
bool isEmpty() const
Returns true if the geometry is empty.
Point geometry type, with support for z-dimension and m-values.
double inclination(const QgsPoint &other) const
Calculates Cartesian inclination between this point and other one (starting from zenith = 0 to nadir ...
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override
Checks validity of the geometry, and returns true if the geometry is valid.
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which corresponds to this point projected by a specified distance with specified ...
QgsRelationManager * relationManager
static QgsProject * instance()
Returns the QgsProject singleton instance.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
Quadrilateral geometry type.
static QgsQuadrilateral squareFromDiagonal(const QgsPoint &p1, const QgsPoint &p2)
Construct a QgsQuadrilateral as a square from a diagonal.
QgsPolygon * toPolygon(bool force2D=false) const
Returns the quadrilateral as a new polygon.
static QgsQuadrilateral rectangleFrom3Points(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &p3, ConstructionOption mode)
Construct a QgsQuadrilateral as a Rectangle from 3 points.
ConstructionOption
A quadrilateral can be constructed from 3 points where the second distance can be determined by the t...
@ Distance
Second distance is equal to the distance between 2nd and 3rd point.
@ Projected
Second distance is equal to the distance of the perpendicular projection of the 3rd point on the segm...
The Field class represents a Raster Attribute Table field, including its name, usage and type.
The RasterBandStats struct is a container for statistics about a single raster band.
double mean
The mean cell value for the band. NO_DATA values are excluded.
double stdDev
The standard deviation of the cell values.
double minimumValue
The minimum cell value in the raster band.
double sum
The sum of all cells in the band. NO_DATA values are excluded.
double maximumValue
The maximum cell value in the raster band.
double range
The range is the distance between min & max.
A rectangle specified with double values.
void grow(double delta)
Grows the rectangle in place by the specified amount.
Regular Polygon geometry type.
ConstructionOption
A regular polygon can be constructed inscribed in a circle or circumscribed about a circle.
@ CircumscribedCircle
Circumscribed about a circle (the radius is the distance from the center to the midpoints of the side...
@ InscribedCircle
Inscribed in a circle (the radius is the distance between the center and vertices)
QgsPolygon * toPolygon() const
Returns as a polygon.
QList< QgsRelation > relationsByName(const QString &name) const
Returns a list of relations with matching names.
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id.
Represents a relationship between two vector layers.
QgsVectorLayer * referencedLayer
QgsVectorLayer * referencingLayer
QString getRelatedFeaturesFilter(const QgsFeature &feature) const
Returns a filter expression which returns all the features on the referencing (child) layer which hav...
A spatial index for QgsFeature objects.
@ FlagStoreFeatureGeometries
Indicates that the spatial index should also store feature geometries. This requires more memory,...
QList< QgsFeatureId > nearestNeighbor(const QgsPointXY &point, int neighbors=1, double maxDistance=0) const
Returns nearest neighbors to a point.
QList< QgsFeatureId > intersects(const QgsRectangle &rectangle) const
Returns a list of features with a bounding box which intersects the specified rectangle.
static QString quotedIdentifier(const QString &identifier)
Returns a properly quoted version of identifier.
static QString quotedValue(const QVariant &value)
Returns a properly quoted and escaped version of value for use in SQL strings.
Helper class for defining QgsExpression functions.
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
void setIsStaticFunction(const std::function< bool(const QgsExpressionNodeFunction *, QgsExpression *, const QgsExpressionContext *) > &isStatic)
Set a function that will be called in the prepare step to determine if the function is static or not.
QStringList aliases() const override
Returns a list of possible aliases for the function.
void setPrepareFunction(const std::function< bool(const QgsExpressionNodeFunction *, QgsExpression *, const QgsExpressionContext *)> &prepareFunc)
Set a function that will be called in the prepare step to determine if the function is static or not.
void setUsesGeometryFunction(const std::function< bool(const QgsExpressionNodeFunction *node)> &usesGeometry)
Set a function that will be called when determining if the function requires feature geometry or not.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
void setIsStatic(bool isStatic)
Tag this function as either static or not static.
QgsStaticExpressionFunction(const QString &fnname, int params, FcnEval fcn, const QString &group, const QString &helpText=QString(), bool usesGeometry=false, const QSet< QString > &referencedColumns=QSet< QString >(), bool lazyEval=false, const QStringList &aliases=QStringList(), bool handlesNull=false)
Static function for evaluation against a QgsExpressionContext, using an unnamed list of parameter val...
QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const override
Returns a set of field names which are required for this function.
bool usesGeometry(const QgsExpressionNodeFunction *node) const override
Does this function use a geometry object.
Utility functions for working with strings.
static int hammingDistance(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the Hamming distance between two strings.
static QString soundex(const QString &string)
Returns the Soundex representation of a string.
static int levenshteinDistance(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the Levenshtein edit distance between two strings.
static QString longestCommonSubstring(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the longest common substring between two strings.
static QString wordWrap(const QString &string, int length, bool useMaxLineLength=true, const QString &customDelimiter=QString())
Automatically wraps a string by inserting new line characters at appropriate locations in the string.
const QgsColorRamp * colorRampRef(const QString &name) const
Returns a const pointer to a symbol (doesn't create new instance)
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Contains utility functions for working with symbols and symbol layers.
static QColor decodeColor(const QString &str)
static QString encodeColor(const QColor &color)
static bool runOnMainThread(const Func &func, QgsFeedback *feedback=nullptr)
Guarantees that func is executed on the main thread.
Allows creation of a multi-layer database-side transaction.
virtual bool executeSql(const QString &sql, QString &error, bool isDirty=false, const QString &name=QString())=0
Execute the sql string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
virtual QgsTransaction * transaction() const
Returns the transaction this data provider is included in, if any.
static bool validateAttribute(const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors, QgsFieldConstraints::ConstraintStrength strength=QgsFieldConstraints::ConstraintStrengthNotSet, QgsFieldConstraints::ConstraintOrigin origin=QgsFieldConstraints::ConstraintOriginNotSet)
Tests a feature attribute value to check whether it passes all constraints which are present on the c...
Represents a vector layer which manages a vector based dataset.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QVariant aggregate(Qgis::Aggregate aggregate, const QString &fieldOrExpression, const QgsAggregateCalculator::AggregateParameters ¶meters=QgsAggregateCalculator::AggregateParameters(), QgsExpressionContext *context=nullptr, bool *ok=nullptr, QgsFeatureIds *fids=nullptr, QgsFeedback *feedback=nullptr, QString *error=nullptr) const
Calculates an aggregated value from the layer's features.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QString displayExpression
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
QgsEditorWidgetSetup editorWidgetSetup(int index) const
Returns the editor widget setup for the field at the specified index.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
Q_INVOKABLE QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.
Handles the with_variable(name, value, node) expression function.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
QgsWithVariableExpressionFunction()
QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Evaluates the function, first evaluating all required arguments before passing them to the function's...
QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Returns result of evaluating the function.
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
static 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)
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.