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 bool isStatic =
true;
718 if ( filterExp.referencedVariables().contains( QStringLiteral(
"parent" ) )
719 || filterExp.referencedVariables().contains( QString() )
720 || subExp.referencedVariables().contains( QStringLiteral(
"parent" ) )
721 || subExp.referencedVariables().contains( QString() ) )
728 const QSet<QString> refVars = filterExp.referencedVariables() + subExp.referencedVariables();
729 for (
const QString &varName : refVars )
732 if ( scope && !scope->
isStatic( varName ) )
740 if ( isStatic && ! parameters.
orderBy.isEmpty() )
742 for (
const auto &orderByClause : std::as_const( parameters.orderBy ) )
745 if ( orderByExpression.referencedVariables().contains( QStringLiteral(
"parent" ) ) || orderByExpression.referencedVariables().contains( QString() ) )
755 cacheKey = QStringLiteral(
"aggfcn:%1:%2:%3:%4:%5%6:%7" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter,
756 QString::number( context->
feature().
id() ), QString::number(
qHash( context->
feature() ) ), orderBy );
760 cacheKey = QStringLiteral(
"aggfcn:%1:%2:%3:%4:%5" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter, orderBy );
771 subContext.appendScope( subScope );
772 result = vl->aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &aggregateError );
784 result = vl->aggregate( aggregate, subExpression, parameters,
nullptr, &ok,
nullptr,
nullptr, &aggregateError );
788 if ( !aggregateError.isEmpty() )
789 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, aggregateError ) );
791 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
802 parent->
setEvalErrorString( QObject::tr(
"Cannot use relation aggregate function in this context" ) );
810 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
814 parent->
setEvalErrorString( QObject::tr(
"Cannot use relation aggregate function in this context" ) );
823 QVariant value = node->
eval( parent, context );
825 QString relationId = value.toString();
832 if ( relations.isEmpty() || relations.at( 0 ).referencedLayer() != vl )
834 parent->
setEvalErrorString( QObject::tr(
"Cannot find relation with id '%1'" ).arg( relationId ) );
839 relation = relations.at( 0 );
846 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
848 value = node->
eval( parent, context );
854 parent->
setEvalErrorString( QObject::tr(
"No such aggregate '%1'" ).arg( value.toString() ) );
859 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
861 QString subExpression = node->
dump();
865 if ( values.count() > 3 )
867 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
869 value = node->
eval( parent, context );
876 if ( values.count() > 4 )
878 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
881 if ( !nl || nl->value().isValid() )
883 orderBy = node->
dump();
894 QString cacheKey = QStringLiteral(
"relagg:%1:%2:%3:%4:%5" ).arg( vl->id(),
895 QString::number(
static_cast< int >( aggregate ) ),
908 result = childLayer->
aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &error );
912 if ( !error.isEmpty() )
913 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, error ) );
915 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
929 parent->
setEvalErrorString( QObject::tr(
"Cannot use aggregate function in this context" ) );
937 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
941 parent->
setEvalErrorString( QObject::tr(
"Cannot use aggregate function in this context" ) );
950 QString subExpression = node->
dump();
954 if ( values.count() > 1 )
956 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
959 if ( !nl || nl->value().isValid() )
960 groupBy = node->
dump();
964 if ( values.count() > 2 )
966 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
969 if ( !nl || nl->value().isValid() )
975 if ( orderByPos >= 0 && values.count() > orderByPos )
977 node = QgsExpressionUtils::getNode( values.at( orderByPos ), parent );
980 if ( !nl || nl->value().isValid() )
982 orderBy = node->
dump();
990 if ( !groupBy.isEmpty() )
993 QVariant groupByValue = groupByExp.evaluate( context );
994 QString groupByClause = QStringLiteral(
"%1 %2 %3" ).arg( groupBy,
997 if ( !parameters.
filter.isEmpty() )
998 parameters.
filter = QStringLiteral(
"(%1) AND (%2)" ).arg( parameters.
filter, groupByClause );
1000 parameters.
filter = groupByClause;
1006 bool isStatic =
true;
1007 const QSet<QString> refVars = filterExp.referencedVariables() + subExp.referencedVariables();
1008 for (
const QString &varName : refVars )
1011 if ( scope && !scope->
isStatic( varName ) )
1021 cacheKey = QStringLiteral(
"agg:%1:%2:%3:%4:%5%6:%7" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter,
1022 QString::number( context->
feature().
id() ), QString::number(
qHash( context->
feature() ) ), orderBy );
1026 cacheKey = QStringLiteral(
"agg:%1:%2:%3:%4:%5" ).arg( vl->id(), QString::number(
static_cast< int >( aggregate ) ), subExpression, parameters.
filter, orderBy );
1038 subContext.appendScope( subScope );
1040 result = vl->aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &error );
1044 if ( !error.isEmpty() )
1045 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, error ) );
1047 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
1152 if ( values.count() > 3 )
1154 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
1156 QVariant value = node->
eval( parent, context );
1158 parameters.
delimiter = value.toString();
1169 if ( values.count() > 3 )
1171 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
1173 QVariant value = node->
eval( parent, context );
1175 parameters.
delimiter = value.toString();
1191 QVariant scale = context->
variable( QStringLiteral(
"map_scale" ) );
1196 const double v = scale.toDouble( &ok );
1204 double minValue = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1205 double testValue = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1206 double maxValue = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1209 if ( testValue <= minValue )
1211 return QVariant( minValue );
1213 else if ( testValue >= maxValue )
1215 return QVariant( maxValue );
1219 return QVariant( testValue );
1225 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1226 return QVariant( std::floor( x ) );
1231 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1232 return QVariant( std::ceil( x ) );
1237 return QVariant( QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) );
1241 return QVariant( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) );
1245 return QVariant( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ) );
1250 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1251 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1252 if ( format.isEmpty() && !language.isEmpty() )
1254 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to DateTime when the language is specified" ) );
1255 return QVariant( QDateTime() );
1258 if ( format.isEmpty() && language.isEmpty() )
1259 return QVariant( QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent ) );
1261 QString datetimestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1262 QLocale locale = QLocale();
1263 if ( !language.isEmpty() )
1265 locale = QLocale( language );
1268 QDateTime datetime = locale.toDateTime( datetimestring, format );
1269 if ( !datetime.isValid() )
1271 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to DateTime" ).arg( datetimestring ) );
1272 datetime = QDateTime();
1274 return QVariant( datetime );
1279 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1280 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1281 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1283 const QDate date( year, month, day );
1284 if ( !date.isValid() )
1286 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1289 return QVariant( date );
1294 const int hours = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1295 const int minutes = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1296 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1298 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1299 if ( !time.isValid() )
1301 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1304 return QVariant( time );
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 );
1312 const int hours = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
1313 const int minutes = QgsExpressionUtils::getIntValue( values.at( 4 ), parent );
1314 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1316 const QDate date( year, month, day );
1317 if ( !date.isValid() )
1319 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1322 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1323 if ( !time.isValid() )
1325 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1328 return QVariant( QDateTime( date, time ) );
1333 const double years = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1334 const double months = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1335 const double weeks = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1336 const double days = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
1337 const double hours = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
1338 const double minutes = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1339 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
1341 return QVariant::fromValue(
QgsInterval( years, months, weeks, days, hours, minutes, seconds ) );
1346 for (
const QVariant &value : values )
1357 const QVariant val1 = values.at( 0 );
1358 const QVariant val2 = values.at( 1 );
1368 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1369 return QVariant(
str.toLower() );
1373 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1374 return QVariant(
str.toUpper() );
1378 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1379 QStringList elems =
str.split(
' ' );
1380 for (
int i = 0; i < elems.size(); i++ )
1382 if ( elems[i].size() > 1 )
1383 elems[i] = elems[i].at( 0 ).toUpper() + elems[i].mid( 1 ).toLower();
1385 return QVariant( elems.join( QLatin1Char(
' ' ) ) );
1390 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1391 return QVariant(
str.trimmed() );
1396 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1398 const QString characters = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1400 const QRegularExpression re( QStringLiteral(
"^([%1]*)" ).arg( QRegularExpression::escape( characters ) ) );
1401 str.replace( re, QString() );
1402 return QVariant(
str );
1407 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1409 const QString characters = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1411 const QRegularExpression re( QStringLiteral(
"([%1]*)$" ).arg( QRegularExpression::escape( characters ) ) );
1412 str.replace( re, QString() );
1413 return QVariant(
str );
1418 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1419 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1425 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1426 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1432 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1433 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1435 return ( dist < 0 ? QVariant() : QVariant(
QgsStringUtils::hammingDistance( string1, string2, true ) ) );
1440 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1446 QChar character = QChar( QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent ) );
1447 return QVariant( QString( character ) );
1452 QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1454 if ( value.isEmpty() )
1459 int res = value.at( 0 ).unicode();
1460 return QVariant( res );
1465 if ( values.length() == 2 || values.length() == 3 )
1467 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1468 qlonglong wrap = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1470 QString customdelimiter = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1481 if ( values.at( 0 ).userType() == qMetaTypeId< QgsGeometry>() )
1484 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
1488 return QVariant( geom.
length() );
1492 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1493 return QVariant(
str.length() );
1498 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
1503 double totalLength = 0;
1506 if (
const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( *it ) )
1508 totalLength += line->length3D();
1512 std::unique_ptr< QgsLineString > segmentized( qgsgeometry_cast< const QgsCurve * >( *it )->curveToLine() );
1513 totalLength += segmentized->length3D();
1522 if ( values.count() == 2 && values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
1524 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1525 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
1526 QVector< QPair< QString, QString > > mapItems;
1528 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
1530 mapItems.append( qMakePair( it.key(), it.value().toString() ) );
1534 std::sort( mapItems.begin(),
1536 [](
const QPair< QString, QString > &pair1,
1537 const QPair< QString, QString > &pair2 )
1539 return ( pair1.first.length() > pair2.first.length() );
1542 for (
auto it = mapItems.constBegin(); it != mapItems.constEnd(); ++it )
1544 str =
str.replace( it->first, it->second );
1547 return QVariant(
str );
1549 else if ( values.count() == 3 )
1551 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1552 QVariantList before;
1554 bool isSingleReplacement =
false;
1556 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).userType() != QMetaType::Type::QStringList )
1558 before = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1562 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
1565 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
1567 after = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1568 isSingleReplacement =
true;
1572 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
1575 if ( !isSingleReplacement && before.length() != after.length() )
1577 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
1581 for (
int i = 0; i < before.length(); i++ )
1583 str =
str.replace( before.at( i ).toString(), after.at( isSingleReplacement ? 0 : i ).toString() );
1586 return QVariant(
str );
1590 parent->
setEvalErrorString( QObject::tr(
"Function replace requires 2 or 3 arguments" ) );
1597 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1598 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1599 QString after = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1601 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1602 if ( !re.isValid() )
1604 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1607 return QVariant(
str.replace( re, after ) );
1612 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1613 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1615 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1616 if ( !re.isValid() )
1618 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1621 return QVariant( (
str.indexOf( re ) + 1 ) );
1626 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1627 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1628 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1630 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1631 if ( !re.isValid() )
1633 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1637 QRegularExpressionMatch matches = re.match(
str );
1638 if ( matches.hasMatch() )
1641 QStringList list = matches.capturedTexts();
1644 for ( QStringList::const_iterator it = ++list.constBegin(); it != list.constEnd(); ++it )
1646 array += ( !( *it ).isEmpty() ) ? *it : empty;
1649 return QVariant( array );
1659 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1660 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1662 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1663 if ( !re.isValid() )
1665 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1670 QRegularExpressionMatch match = re.match(
str );
1671 if ( match.hasMatch() )
1674 if ( match.lastCapturedIndex() > 0 )
1677 return QVariant( match.captured( 1 ) );
1682 return QVariant( match.captured( 0 ) );
1687 return QVariant(
"" );
1693 QString uuid = QUuid::createUuid().toString();
1694 if ( values.at( 0 ).toString().compare( QStringLiteral(
"WithoutBraces" ), Qt::CaseInsensitive ) == 0 )
1695 uuid = QUuid::createUuid().toString( QUuid::StringFormat::WithoutBraces );
1696 else if ( values.at( 0 ).toString().compare( QStringLiteral(
"Id128" ), Qt::CaseInsensitive ) == 0 )
1697 uuid = QUuid::createUuid().toString( QUuid::StringFormat::Id128 );
1703 if ( !values.at( 0 ).isValid() || !values.at( 1 ).isValid() )
1706 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1707 int from = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1710 if ( values.at( 2 ).isValid() )
1711 len = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
1717 from =
str.size() + from;
1723 else if ( from > 0 )
1731 len =
str.size() + len - from;
1738 return QVariant(
str.mid( from, len ) );
1744 return QVariant(
static_cast< int >( f.
id() ) );
1749 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1750 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
1751 bool foundLayer =
false;
1752 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, geom](
QgsMapLayer * mapLayer )
1754 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer * >( mapLayer );
1755 if ( !layer || !layer->dataProvider() )
1757 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1761 if ( bandNb < 1 || bandNb > layer->bandCount() )
1763 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster band number." ) );
1769 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid point geometry." ) );
1777 if ( multiPoint.count() == 1 )
1779 point = multiPoint[0];
1788 double value = layer->dataProvider()->sample( point, bandNb );
1789 return std::isnan( value ) ? QVariant() : value;
1795 parent->
setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1806 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1807 const double value = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1809 bool foundLayer =
false;
1810 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, value](
QgsMapLayer * mapLayer )-> QVariant
1812 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer *>( mapLayer );
1813 if ( !layer || !layer->dataProvider() )
1815 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1819 if ( bandNb < 1 || bandNb > layer->bandCount() )
1821 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster band number." ) );
1825 if ( std::isnan( value ) )
1827 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster value." ) );
1831 if ( ! layer->dataProvider()->attributeTable( bandNb ) )
1836 const QVariantList data = layer->dataProvider()->attributeTable( bandNb )->row( value );
1837 if ( data.isEmpty() )
1843 const QList<QgsRasterAttributeTable::Field> fields { layer->dataProvider()->attributeTable( bandNb )->fields() };
1844 for (
int idx = 0; idx < static_cast<int>( fields.count( ) ) && idx < static_cast<int>( data.count() ); ++idx )
1847 if ( field.isColor() || field.isRamp() )
1851 result.insert( fields.at( idx ).name, data.at( idx ) );
1859 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1880 if ( values.size() == 1 )
1882 attr = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1885 else if ( values.size() == 2 )
1887 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
1888 attr = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1892 parent->
setEvalErrorString( QObject::tr(
"Function `attribute` requires one or two parameters. %n given.",
nullptr, values.length() ) );
1901 QString table { R
"html(
1904 <tr><th>%1</th></tr>
1907 <tr><td>%2</td></tr>
1911 if ( values.size() == 1 )
1913 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1917 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_table` requires one parameter. %n given.",
nullptr, values.length() ) );
1921 if ( dict.isEmpty() )
1926 QStringList headers;
1929 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
1931 headers.push_back( it.key().toHtmlEscaped() );
1932 cells.push_back( it.value().toString( ).toHtmlEscaped() );
1935 return table.arg( headers.join( QLatin1String(
"</th><th>" ) ), cells.join( QLatin1String(
"</td><td>" ) ) );
1940 QString table { R
"html(
1945 if ( values.size() == 1 )
1947 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1951 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_dl` requires one parameter. %n given.",
nullptr, values.length() ) );
1955 if ( dict.isEmpty() )
1962 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
1964 rows.append( QStringLiteral(
"<dt>%1</dt><dd>%2</dd>" ).arg( it.key().toHtmlEscaped(), it.value().toString().toHtmlEscaped() ) );
1967 return table.arg( rows );
1975 layer = context->
variable( QStringLiteral(
"layer" ) );
1980 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
1982 layer = node->
eval( parent, context );
1993 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
1997 const QString strength = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).toLower();
1998 if ( strength == QLatin1String(
"hard" ) )
2002 else if ( strength == QLatin1String(
"soft" ) )
2007 bool foundLayer =
false;
2008 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
2010 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2013 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2019 for (
int i = 0; i < fields.
size(); i++ )
2034 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2046 layer = context->
variable( QStringLiteral(
"layer" ) );
2051 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
2053 layer = node->
eval( parent, context );
2064 feature = QgsExpressionUtils::getFeature( values.at( 2 ), parent );
2068 const QString strength = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).toLower();
2069 if ( strength == QLatin1String(
"hard" ) )
2073 else if ( strength == QLatin1String(
"soft" ) )
2078 const QString attributeName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2080 bool foundLayer =
false;
2081 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, attributeName, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
2083 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2090 if ( fieldIndex == -1 )
2092 parent->
setEvalErrorString( QObject::tr(
"The attribute name did not match any field for the given feature" ) );
2103 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2119 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2124 for (
int i = 0; i < fields.
count(); ++i )
2138 if ( values.isEmpty() )
2141 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2143 else if ( values.size() == 1 )
2145 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2146 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2148 else if ( values.size() == 2 )
2150 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2151 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2155 parent->
setEvalErrorString( QObject::tr(
"Function `represent_attributes` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2162 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: layer could not be resolved." ) );
2168 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: feature could not be resolved." ) );
2174 for (
int fieldIndex = 0; fieldIndex < fields.
count(); ++fieldIndex )
2176 const QString fieldName { fields.
at( fieldIndex ).
name() };
2177 const QVariant attributeVal = feature.
attribute( fieldIndex );
2178 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer->
id(), fieldName, attributeVal.toString() );
2181 result.insert( fieldName, context->
cachedValue( cacheValueKey ) );
2190 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer->
id(), fieldName );
2202 QString value( fieldFormatter->
representValue( layer, fieldIndex, setup.
config(), cache, attributeVal ) );
2204 result.insert( fields.
at( fieldIndex ).
name(), value );
2220 bool evaluate =
true;
2224 if ( values.isEmpty() )
2227 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2229 else if ( values.size() == 1 )
2231 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2232 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2234 else if ( values.size() == 2 )
2236 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2237 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2239 else if ( values.size() == 3 )
2241 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2242 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2243 evaluate = values.value( 2 ).toBool();
2249 parent->
setEvalErrorString( QObject::tr(
"Function `maptip` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2253 parent->
setEvalErrorString( QObject::tr(
"Function `display` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2285 subContext.setFeature( feature );
2294 exp.prepare( &subContext );
2295 return exp.evaluate( &subContext ).toString();
2301 return fcnCoreFeatureMaptipDisplay( values, context, parent,
false );
2306 return fcnCoreFeatureMaptipDisplay( values, context, parent,
true );
2313 if ( values.isEmpty() )
2316 layer = context->
variable( QStringLiteral(
"layer" ) );
2318 else if ( values.size() == 1 )
2320 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2321 layer = context->
variable( QStringLiteral(
"layer" ) );
2323 else if ( values.size() == 2 )
2325 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2326 layer = values.at( 0 );
2330 parent->
setEvalErrorString( QObject::tr(
"Function `is_selected` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2334 bool foundLayer =
false;
2335 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [feature](
QgsMapLayer * mapLayer ) -> QVariant
2337 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2338 if ( !layer || !feature.
isValid() )
2355 if ( values.isEmpty() )
2356 layer = context->
variable( QStringLiteral(
"layer" ) );
2357 else if ( values.count() == 1 )
2358 layer = values.at( 0 );
2361 parent->
setEvalErrorString( QObject::tr(
"Function `num_selected` requires no more than one parameter. %n given.",
nullptr, values.length() ) );
2365 bool foundLayer =
false;
2366 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [](
QgsMapLayer * mapLayer ) -> QVariant
2368 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2384 static QMap<QString, qlonglong> counterCache;
2385 QVariant functionResult;
2387 auto fetchAndIncrementFunc = [ values, parent, &functionResult ](
QgsMapLayer * mapLayer,
const QString & databaseArgument )
2391 const QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( mapLayer );
2396 database = decodedUri.value( QStringLiteral(
"path" ) ).toString();
2397 if ( database.isEmpty() )
2399 parent->
setEvalErrorString( QObject::tr(
"Could not extract file path from layer `%1`." ).arg( layer->
name() ) );
2404 database = databaseArgument;
2407 const QString table = values.at( 1 ).toString();
2408 const QString idColumn = values.at( 2 ).toString();
2409 const QString filterAttribute = values.at( 3 ).toString();
2410 const QVariant filterValue = values.at( 4 ).toString();
2411 const QVariantMap defaultValues = values.at( 5 ).toMap();
2417 if ( sqliteDb.
open_v2( database, SQLITE_OPEN_READWRITE,
nullptr ) != SQLITE_OK )
2420 functionResult = QVariant();
2424 QString errorMessage;
2425 QString currentValSql;
2427 qlonglong nextId = 0;
2428 bool cachedMode =
false;
2429 bool valueRetrieved =
false;
2431 QString cacheString = QStringLiteral(
"%1:%2:%3:%4:%5" ).arg( database, table, idColumn, filterAttribute, filterValue.toString() );
2438 auto cachedCounter = counterCache.find( cacheString );
2440 if ( cachedCounter != counterCache.end() )
2442 qlonglong &cachedValue = cachedCounter.value();
2443 nextId = cachedValue;
2445 cachedValue = nextId;
2446 valueRetrieved =
true;
2451 if ( !cachedMode || !valueRetrieved )
2453 int result = SQLITE_ERROR;
2456 if ( !filterAttribute.isNull() )
2461 sqliteStatement = sqliteDb.
prepare( currentValSql, result );
2463 if ( result == SQLITE_OK )
2466 if ( sqliteStatement.
step() == SQLITE_ROW )
2472 if ( cachedMode && result == SQLITE_OK )
2474 counterCache.insert( cacheString, nextId );
2478 counterCache.remove( cacheString );
2481 valueRetrieved =
true;
2485 if ( valueRetrieved )
2494 if ( !filterAttribute.isNull() )
2500 for ( QVariantMap::const_iterator iter = defaultValues.constBegin(); iter != defaultValues.constEnd(); ++iter )
2503 vals << iter.value().toString();
2506 upsertSql += QLatin1String(
" (" ) + cols.join(
',' ) +
')';
2507 upsertSql += QLatin1String(
" VALUES " );
2508 upsertSql +=
'(' + vals.join(
',' ) +
')';
2510 int result = SQLITE_ERROR;
2514 if ( transaction->
executeSql( upsertSql, errorMessage ) )
2521 result = sqliteDb.
exec( upsertSql, errorMessage );
2523 if ( result == SQLITE_OK )
2525 functionResult = QVariant( nextId );
2530 parent->
setEvalErrorString( QStringLiteral(
"Could not increment value: SQLite error: \"%1\" (%2)." ).arg( errorMessage, QString::number( result ) ) );
2531 functionResult = QVariant();
2536 functionResult = QVariant();
2539 bool foundLayer =
false;
2540 QgsExpressionUtils::executeLambdaForMapLayer( values.at( 0 ), context, parent, [&fetchAndIncrementFunc](
QgsMapLayer * layer )
2542 fetchAndIncrementFunc( layer, QString() );
2546 const QString databasePath = values.at( 0 ).toString();
2549 fetchAndIncrementFunc(
nullptr, databasePath );
2553 return functionResult;
2559 for (
const QVariant &value : values )
2562 concat += QgsExpressionUtils::getStringValue( value, parent );
2569 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2570 return string.indexOf( QgsExpressionUtils::getStringValue( values.at( 1 ), parent ) ) + 1;
2575 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2576 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2577 return string.right( pos );
2582 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2583 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2584 return string.left( pos );
2589 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2590 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2591 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2592 return string.leftJustified( length, fill.at( 0 ),
true );
2597 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2598 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2599 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2600 return string.rightJustified( length, fill.at( 0 ),
true );
2605 if ( values.size() < 1 )
2607 parent->
setEvalErrorString( QObject::tr(
"Function format requires at least 1 argument" ) );
2611 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2612 for (
int n = 1; n < values.length(); n++ )
2614 string =
string.arg( QgsExpressionUtils::getStringValue( values.at( n ), parent ) );
2622 return QVariant( QDateTime::currentDateTime() );
2627 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2628 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2629 if ( format.isEmpty() && !language.isEmpty() )
2631 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Date when the language is specified" ) );
2632 return QVariant( QDate() );
2635 if ( format.isEmpty() && language.isEmpty() )
2636 return QVariant( QgsExpressionUtils::getDateValue( values.at( 0 ), parent ) );
2638 QString datestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2639 QLocale locale = QLocale();
2640 if ( !language.isEmpty() )
2642 locale = QLocale( language );
2645 QDate date = locale.toDate( datestring, format );
2646 if ( !date.isValid() )
2648 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Date" ).arg( datestring ) );
2651 return QVariant( date );
2656 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2657 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2658 if ( format.isEmpty() && !language.isEmpty() )
2660 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Time when the language is specified" ) );
2661 return QVariant( QTime() );
2664 if ( format.isEmpty() && language.isEmpty() )
2665 return QVariant( QgsExpressionUtils::getTimeValue( values.at( 0 ), parent ) );
2667 QString timestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2668 QLocale locale = QLocale();
2669 if ( !language.isEmpty() )
2671 locale = QLocale( language );
2674 QTime time = locale.toTime( timestring, format );
2675 if ( !time.isValid() )
2677 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Time" ).arg( timestring ) );
2680 return QVariant( time );
2685 return QVariant::fromValue( QgsExpressionUtils::getInterval( values.at( 0 ), parent ) );
2694 double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
2695 QString axis = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2696 int precision = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
2698 QString formatString;
2699 if ( values.count() > 3 )
2700 formatString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
2703 if ( formatString.compare( QLatin1String(
"suffix" ), Qt::CaseInsensitive ) == 0 )
2707 else if ( formatString.compare( QLatin1String(
"aligned" ), Qt::CaseInsensitive ) == 0 )
2711 else if ( ! formatString.isEmpty() )
2713 parent->
setEvalErrorString( QObject::tr(
"Invalid formatting parameter: '%1'. It must be empty, or 'suffix' or 'aligned'." ).arg( formatString ) );
2717 if ( axis.compare( QLatin1String(
"x" ), Qt::CaseInsensitive ) == 0 )
2721 else if ( axis.compare( QLatin1String(
"y" ), Qt::CaseInsensitive ) == 0 )
2727 parent->
setEvalErrorString( QObject::tr(
"Invalid axis name: '%1'. It must be either 'x' or 'y'." ).arg( axis ) );
2735 return floatToDegreeFormat( format, values, context, parent, node );
2742 value = QgsCoordinateUtils::dmsToDecimal( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), &ok );
2744 return ok ? QVariant( value ) : QVariant();
2750 return floatToDegreeFormat( format, values, context, parent, node );
2755 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2756 QDateTime d2 = QgsExpressionUtils::getDateTimeValue( values.at( 1 ), parent );
2757 qint64 seconds = d2.secsTo( d1 );
2758 return QVariant::fromValue(
QgsInterval( seconds ) );
2763 if ( !values.at( 0 ).canConvert<QDate>() )
2766 QDate date = QgsExpressionUtils::getDateValue( values.at( 0 ), parent );
2767 if ( !date.isValid() )
2772 return date.dayOfWeek() % 7;
2777 QVariant value = values.at( 0 );
2778 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2781 return QVariant( inter.
days() );
2785 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2786 return QVariant( d1.date().day() );
2792 QVariant value = values.at( 0 );
2793 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2796 return QVariant( inter.
years() );
2800 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2801 return QVariant( d1.date().year() );
2807 QVariant value = values.at( 0 );
2808 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2811 return QVariant( inter.
months() );
2815 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2816 return QVariant( d1.date().month() );
2822 QVariant value = values.at( 0 );
2823 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2826 return QVariant( inter.
weeks() );
2830 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2831 return QVariant( d1.date().weekNumber() );
2837 QVariant value = values.at( 0 );
2838 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2841 return QVariant( inter.
hours() );
2845 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2846 return QVariant( t1.hour() );
2852 QVariant value = values.at( 0 );
2853 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2856 return QVariant( inter.
minutes() );
2860 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2861 return QVariant( t1.minute() );
2867 QVariant value = values.at( 0 );
2868 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2871 return QVariant( inter.
seconds() );
2875 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2876 return QVariant( t1.second() );
2882 QDateTime dt = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2885 return QVariant( dt.toMSecsSinceEpoch() );
2895 long long millisecs_since_epoch = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
2897 return QVariant( QDateTime::fromMSecsSinceEpoch( millisecs_since_epoch ) );
2902 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2905 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif" ) ) );
2908 QString tag = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2914 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2917 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif_geotag" ) ) );
2924#define ENSURE_GEOM_TYPE(f, g, geomtype) \
2925 if ( !(f).hasGeometry() ) \
2926 return QVariant(); \
2927 QgsGeometry g = (f).geometry(); \
2928 if ( (g).type() != (geomtype) ) \
2935 if ( g.isMultipart() )
2937 return g.asMultiPoint().at( 0 ).x();
2941 return g.asPoint().x();
2949 if ( g.isMultipart() )
2951 return g.asMultiPoint().at( 0 ).y();
2955 return g.asPoint().y();
2969 if ( g.isEmpty() || !abGeom->
is3D() )
2974 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( g.constGet() );
2980 if (
const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( g.constGet() ) )
2982 if ( collection->numGeometries() > 0 )
2984 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
2995 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3001 return QVariant( isValid );
3006 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3010 const QString methodString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).trimmed();
3011#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
3016 if ( methodString.compare( QLatin1String(
"linework" ), Qt::CaseInsensitive ) == 0 )
3018 else if ( methodString.compare( QLatin1String(
"structure" ), Qt::CaseInsensitive ) == 0 )
3021 const bool keepCollapsed = values.value( 2 ).toBool();
3026 valid = geom.
makeValid( method, keepCollapsed );
3030 parent->
setEvalErrorString( QObject::tr(
"The make_valid parameters require a newer GEOS library version" ) );
3034 return QVariant::fromValue( valid );
3039 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3045 for (
int i = 0; i < multiGeom.size(); ++i )
3047 array += QVariant::fromValue( multiGeom.at( i ) );
3055 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3067 QVariant result( centroid.asPoint().
x() );
3073 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3085 QVariant result( centroid.asPoint().
y() );
3091 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3101 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3109 if ( collection->numGeometries() == 1 )
3111 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3122 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3132 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3140 if ( collection->numGeometries() == 1 )
3142 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3153 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3158 int idx = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
3185 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3202 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3219 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3224 bool ignoreClosing =
false;
3225 if ( values.length() > 1 )
3227 ignoreClosing = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3237 bool skipLast =
false;
3238 if ( ignoreClosing && ring.count() > 2 && ring.first() == ring.last() )
3243 for (
int i = 0; i < ( skipLast ? ring.count() - 1 : ring.count() ); ++ i )
3255 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3266 for (
int i = 0; i < line->numPoints() - 1; ++i )
3270 << line->pointN( i )
3271 << line->pointN( i + 1 ) );
3282 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3292 if ( collection->numGeometries() == 1 )
3294 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->geometryN( 0 ) );
3299 if ( !curvePolygon )
3303 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3309 QVariant result = curve ? QVariant::fromValue(
QgsGeometry( curve ) ) : QVariant();
3315 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3325 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3331 QVariant result = part ? QVariant::fromValue(
QgsGeometry( part ) ) : QVariant();
3337 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3346 return QVariant::fromValue(
QgsGeometry( boundary ) );
3351 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3360 return QVariant::fromValue( merged );
3365 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3369 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3374 if ( sharedPaths.
isNull() )
3377 return QVariant::fromValue( sharedPaths );
3383 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3388 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3391 if ( simplified.
isNull() )
3399 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3404 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3409 if ( simplified.
isNull() )
3417 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3422 int iterations = std::min( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), 10 );
3423 double offset = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0.0, 0.5 );
3424 double minLength = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3425 double maxAngle = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ), 0.0, 180.0 );
3427 QgsGeometry smoothed = geom.
smooth(
static_cast<unsigned int>( iterations ), offset, minLength, maxAngle );
3436 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3441 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3442 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3443 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3454 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3459 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3460 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3461 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3462 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3463 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3466 minAmplitude, maxAmplitude, seed );
3475 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3480 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3481 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3482 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3493 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3498 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3499 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3500 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3501 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3502 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3505 minAmplitude, maxAmplitude, seed );
3514 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3519 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3520 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3521 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3532 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3537 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3538 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3539 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3540 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3541 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3544 minAmplitude, maxAmplitude, seed );
3553 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3558 const QVariantList pattern = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
3559 QVector< double > dashPattern;
3560 dashPattern.reserve( pattern.size() );
3561 for (
const QVariant &value : std::as_const( pattern ) )
3564 double v = value.toDouble( &ok );
3571 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must be an array of numbers" ) );
3576 if ( dashPattern.size() % 2 != 0 )
3578 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must contain an even number of elements" ) );
3582 const QString startRuleString = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).trimmed();
3584 if ( startRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3586 else if ( startRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3588 else if ( startRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3590 else if ( startRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3592 else if ( startRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3596 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( startRuleString ) );
3600 const QString endRuleString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
3602 if ( endRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3604 else if ( endRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3606 else if ( endRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3608 else if ( endRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3610 else if ( endRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3614 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( endRuleString ) );
3618 const QString adjustString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
3620 if ( adjustString.compare( QLatin1String(
"both" ), Qt::CaseInsensitive ) == 0 )
3622 else if ( adjustString.compare( QLatin1String(
"dash" ), Qt::CaseInsensitive ) == 0 )
3624 else if ( adjustString.compare( QLatin1String(
"gap" ), Qt::CaseInsensitive ) == 0 )
3628 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern size adjustment" ).arg( adjustString ) );
3632 const double patternOffset = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
3643 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3648 const long long count = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3650 if ( densified.
isNull() )
3658 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3663 const double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3665 if ( densified.
isNull() )
3674 if ( values.size() == 1 && QgsExpressionUtils::isList( values.at( 0 ) ) )
3676 list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
3683 QVector< QgsGeometry > parts;
3684 parts.reserve( list.size() );
3685 for (
const QVariant &value : std::as_const( list ) )
3687 if ( value.userType() == qMetaTypeId< QgsGeometry>() )
3703 if ( values.count() < 2 || values.count() > 4 )
3705 parent->
setEvalErrorString( QObject::tr(
"Function make_point requires 2-4 arguments" ) );
3709 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3710 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3711 double z = values.count() >= 3 ? QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) : 0.0;
3712 double m = values.count() >= 4 ? QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) : 0.0;
3713 switch ( values.count() )
3727 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3728 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3729 double m = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3735 if ( values.empty() )
3740 QVector<QgsPoint> points;
3741 points.reserve( values.count() );
3743 auto addPoint = [&points](
const QgsGeometry & geom )
3751 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3758 for (
const QVariant &value : values )
3760 if ( value.userType() == QMetaType::Type::QVariantList )
3762 const QVariantList list = value.toList();
3763 for (
const QVariant &v : list )
3765 addPoint( QgsExpressionUtils::getGeometry( v, parent ) );
3770 addPoint( QgsExpressionUtils::getGeometry( value, parent ) );
3774 if ( points.count() < 2 )
3782 if ( values.count() < 1 )
3784 parent->
setEvalErrorString( QObject::tr(
"Function make_polygon requires an argument" ) );
3788 QgsGeometry outerRing = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3796 std::unique_ptr< QgsPolygon > polygon = std::make_unique< QgsPolygon >();
3798 const QgsCurve *exteriorRing = qgsgeometry_cast< QgsCurve * >( outerRing.
constGet() );
3805 exteriorRing = qgsgeometry_cast< QgsCurve * >( collection->
geometryN( 0 ) );
3810 if ( !exteriorRing )
3813 polygon->setExteriorRing( exteriorRing->
segmentize() );
3816 for (
int i = 1; i < values.count(); ++i )
3818 QgsGeometry ringGeom = QgsExpressionUtils::getGeometry( values.at( i ), parent );
3825 const QgsCurve *ring = qgsgeometry_cast< QgsCurve * >( ringGeom.
constGet() );
3832 ring = qgsgeometry_cast< QgsCurve * >( collection->
geometryN( 0 ) );
3840 polygon->addInteriorRing( ring->
segmentize() );
3843 return QVariant::fromValue(
QgsGeometry( std::move( polygon ) ) );
3848 std::unique_ptr<QgsTriangle> tr(
new QgsTriangle() );
3849 std::unique_ptr<QgsLineString> lineString(
new QgsLineString() );
3850 lineString->clear();
3852 for (
const QVariant &value : values )
3854 QgsGeometry geom = QgsExpressionUtils::getGeometry( value, parent );
3861 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3868 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3876 lineString->addVertex( *point );
3879 tr->setExteriorRing( lineString.release() );
3881 return QVariant::fromValue(
QgsGeometry( tr.release() ) );
3886 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3893 double radius = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3894 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
3901 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3908 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3916 return QVariant::fromValue(
QgsGeometry( circ.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
3921 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3928 double majorAxis = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3929 double minorAxis = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3930 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3931 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 4 ), parent );
3937 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3944 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3951 QgsEllipse elp( *point, majorAxis, minorAxis, azimuth );
3952 return QVariant::fromValue(
QgsGeometry( elp.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
3958 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3965 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3972 unsigned int nbEdges =
static_cast<unsigned int>( QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) );
3975 parent->
setEvalErrorString( QObject::tr(
"Number of edges/sides must be greater than 2" ) );
3982 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (inscribed) or 1 (circumscribed)" ) );
3986 const QgsPoint *center = qgsgeometry_cast< const QgsPoint * >( pt1.
constGet() );
3993 center = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4000 const QgsPoint *corner = qgsgeometry_cast< const QgsPoint * >( pt2.
constGet() );
4007 corner = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4022 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4028 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4034 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
4035 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
4043 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4049 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4055 QgsGeometry pt3 = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
4064 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (distance) or 1 (projected)" ) );
4067 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
4068 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
4069 const QgsPoint *point3 = qgsgeometry_cast< const QgsPoint *>( pt3.
constGet() );
4088 return QVariant::fromValue( geom.
vertexAt( idx ) );
4096 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4098 const QVariant v = pointAt( geom, idx, parent );
4101 return QVariant( v.value<
QgsPoint>().
x() );
4107 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4109 return fcnOldXat( values, f, parent, node );
4111 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4113 return fcnOldXat( QVariantList() << values[1], f, parent, node );
4116 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4122 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4124 const QVariant v = pointAt( geom, vertexNumber, parent );
4126 return QVariant( v.value<
QgsPoint>().
x() );
4136 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4138 const QVariant v = pointAt( geom, idx, parent );
4141 return QVariant( v.value<
QgsPoint>().
y() );
4147 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4149 return fcnOldYat( values, f, parent, node );
4151 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4153 return fcnOldYat( QVariantList() << values[1], f, parent, node );
4156 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4162 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4164 const QVariant v = pointAt( geom, vertexNumber, parent );
4166 return QVariant( v.value<
QgsPoint>().
y() );
4173 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4179 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4181 const QVariant v = pointAt( geom, vertexNumber, parent );
4183 return QVariant( v.value<
QgsPoint>().
z() );
4190 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4196 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4198 const QVariant v = pointAt( geom, vertexNumber, parent );
4200 return QVariant( v.value<
QgsPoint>().
m() );
4219 return QVariant::fromValue( geom );
4227 QString wkt = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4229 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4235 const QByteArray wkb = QgsExpressionUtils::getBinaryValue( values.at( 0 ), parent );
4241 return !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4246 QString gml = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4253 ogcContext.
layer = mapLayerPtr.data();
4254 ogcContext.
transformContext = context->
variable( QStringLiteral(
"_project_transform_context" ) ).value<QgsCoordinateTransformContext>();
4258 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4271 return QVariant( area );
4281 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4286 return QVariant( geom.
area() );
4298 return QVariant( len );
4315 return QVariant( len );
4319 return f.
geometry().
isNull() ? QVariant( 0 ) : QVariant( f.geometry().constGet()->perimeter() );
4325 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4331 return QVariant( geom.
length() );
4336 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4337 return QVariant( geom.
isNull() ? 0 : geom.constGet()->nCoordinates() );
4342 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4351 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4360 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4375 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon *>( collection->
geometryN( i ) );
4376 if ( !curvePolygon )
4379 return QVariant( curvePolygon->
isEmpty() ? 0 : curvePolygon->numInteriorRings() );
4388 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4395 return QVariant( curvePolygon->
ringCount() );
4397 bool foundPoly =
false;
4405 curvePolygon = qgsgeometry_cast< QgsCurvePolygon *>( collection->
geometryN( i ) );
4406 if ( !curvePolygon )
4417 return QVariant( ringCount );
4422 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4424 QVariant result = !geomBounds.
isNull() ? QVariant::fromValue( geomBounds ) : QVariant();
4430 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4436 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4442 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4451 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4457 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4463 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4469 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4475 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4483 double max = std::numeric_limits< double >::lowest();
4487 double z = ( *it ).z();
4493 if ( max == std::numeric_limits< double >::lowest() )
4496 return QVariant( max );
4501 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4509 double min = std::numeric_limits< double >::max();
4513 double z = ( *it ).z();
4519 if ( min == std::numeric_limits< double >::max() )
4522 return QVariant( min );
4527 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4535 double min = std::numeric_limits< double >::max();
4539 double m = ( *it ).m();
4545 if ( min == std::numeric_limits< double >::max() )
4548 return QVariant( min );
4553 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4561 double max = std::numeric_limits< double >::lowest();
4565 double m = ( *it ).m();
4571 if ( max == std::numeric_limits< double >::lowest() )
4574 return QVariant( max );
4579 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4580 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom.
constGet() );
4583 parent->
setEvalErrorString( QObject::tr(
"Function `sinuosity` requires a line geometry." ) );
4592 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4596 parent->
setEvalErrorString( QObject::tr(
"Function `straight_distance_2d` requires a line geometry or a multi line geometry with a single part." ) );
4605 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4610 parent->
setEvalErrorString( QObject::tr(
"Function `roundness` requires a polygon geometry or a multi polygon geometry with a single part." ) );
4621 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4625 std::unique_ptr< QgsAbstractGeometry > flipped( geom.
constGet()->
clone() );
4627 return QVariant::fromValue(
QgsGeometry( std::move( flipped ) ) );
4632 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4636 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( fGeom.
constGet() );
4643 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
4651 return QVariant::fromValue( curve->
isClosed() );
4656 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4669 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4670 closedLine->close();
4672 result = QVariant::fromValue(
QgsGeometry( std::move( closedLine ) ) );
4682 if (
const QgsLineString *line = qgsgeometry_cast<const QgsLineString * >( collection->
geometryN( i ) ) )
4684 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4685 closedLine->close();
4687 closed->addGeometry( closedLine.release() );
4690 result = QVariant::fromValue(
QgsGeometry( std::move( closed ) ) );
4698 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4702 return QVariant::fromValue( fGeom.
isEmpty() );
4708 return QVariant::fromValue(
true );
4710 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4711 return QVariant::fromValue( fGeom.
isNull() || fGeom.
isEmpty() );
4716 if ( values.length() < 2 || values.length() > 3 )
4719 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4720 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4727 if ( values.length() == 2 )
4730 QString result = engine->relate( sGeom.
constGet() );
4731 return QVariant::fromValue( result );
4736 QString pattern = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
4737 bool result = engine->relatePattern( sGeom.
constGet(), pattern );
4738 return QVariant::fromValue( result );
4744 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4745 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4750 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4751 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4752 return fGeom.
disjoint( sGeom ) ? TVL_True : TVL_False;
4756 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4757 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4758 return fGeom.
intersects( sGeom ) ? TVL_True : TVL_False;
4762 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4763 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4764 return fGeom.
touches( sGeom ) ? TVL_True : TVL_False;
4768 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4769 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4770 return fGeom.
crosses( sGeom ) ? TVL_True : TVL_False;
4774 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4775 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4776 return fGeom.
contains( sGeom ) ? TVL_True : TVL_False;
4780 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4781 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4782 return fGeom.
overlaps( sGeom ) ? TVL_True : TVL_False;
4786 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4787 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4788 return fGeom.
within( sGeom ) ? TVL_True : TVL_False;
4793 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4794 const double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4795 const int seg = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4796 const QString endCapString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
4797 const QString joinString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
4798 const double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
4801 if ( endCapString.compare( QLatin1String(
"flat" ), Qt::CaseInsensitive ) == 0 )
4803 else if ( endCapString.compare( QLatin1String(
"square" ), Qt::CaseInsensitive ) == 0 )
4807 if ( joinString.compare( QLatin1String(
"miter" ), Qt::CaseInsensitive ) == 0 )
4809 else if ( joinString.compare( QLatin1String(
"bevel" ), Qt::CaseInsensitive ) == 0 )
4813 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4819 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4821 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4826 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4828 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4833 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4835 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4840 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4841 const QgsPoint *pt = qgsgeometry_cast<const QgsPoint *>( fGeom.
constGet() );
4848 pt = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4855 parent->
setEvalErrorString( QObject::tr(
"Function `wedge_buffer` requires a point value for the center." ) );
4859 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4860 double width = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4861 double outerRadius = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4862 double innerRadius = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
4865 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4871 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4874 parent->
setEvalErrorString( QObject::tr(
"Function `tapered_buffer` requires a line geometry." ) );
4878 double startWidth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4879 double endWidth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4880 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) );
4883 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4889 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4892 parent->
setEvalErrorString( QObject::tr(
"Function `buffer_by_m` requires a line geometry." ) );
4896 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) );
4899 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4905 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4906 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4907 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4908 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4909 if ( joinInt < 1 || joinInt > 3 )
4913 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4916 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4922 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4923 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4924 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4926 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4927 if ( joinInt < 1 || joinInt > 3 )
4931 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4934 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4940 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4941 double distStart = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4942 double distEnd = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4945 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4951 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4952 double dx = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4953 double dy = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4955 return QVariant::fromValue( fGeom );
4960 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4961 const double rotation = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4962 const QgsGeometry center = values.at( 2 ).
isValid() ? QgsExpressionUtils::getGeometry( values.at( 2 ), parent )
4964 const bool perPart = values.value( 3 ).toBool();
4971 std::unique_ptr< QgsGeometryCollection > collection( qgsgeometry_cast< QgsGeometryCollection * >( fGeom.
constGet()->
clone() ) );
4974 const QgsPointXY partCenter = ( *it )->boundingBox().center();
4975 QTransform t = QTransform::fromTranslate( partCenter.
x(), partCenter.
y() );
4976 t.rotate( -rotation );
4977 t.translate( -partCenter.
x(), -partCenter.
y() );
4978 ( *it )->transform( t );
4980 return QVariant::fromValue(
QgsGeometry( std::move( collection ) ) );
4992 parent->
setEvalErrorString( QObject::tr(
"Function 'rotate' requires a point value for the center" ) );
5000 fGeom.
rotate( rotation, pt );
5001 return QVariant::fromValue( fGeom );
5007 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5008 const double xScale = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5009 const double yScale = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5010 const QgsGeometry center = values.at( 3 ).isValid() ? QgsExpressionUtils::getGeometry( values.at( 3 ), parent )
5021 parent->
setEvalErrorString( QObject::tr(
"Function 'scale' requires a point value for the center" ) );
5029 QTransform t = QTransform::fromTranslate( pt.
x(), pt.
y() );
5030 t.scale( xScale, yScale );
5031 t.translate( -pt.
x(), -pt.
y() );
5033 return QVariant::fromValue( fGeom );
5038 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5044 const double deltaX = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5045 const double deltaY = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5047 const double rotationZ = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5049 const double scaleX = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
5050 const double scaleY = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
5052 const double deltaZ = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
5053 const double deltaM = QgsExpressionUtils::getDoubleValue( values.at( 7 ), parent );
5054 const double scaleZ = QgsExpressionUtils::getDoubleValue( values.at( 8 ), parent );
5055 const double scaleM = QgsExpressionUtils::getDoubleValue( values.at( 9 ), parent );
5066 QTransform transform;
5067 transform.translate( deltaX, deltaY );
5068 transform.rotate( rotationZ );
5069 transform.scale( scaleX, scaleY );
5070 fGeom.
transform( transform, deltaZ, scaleZ, deltaM, scaleM );
5072 return QVariant::fromValue( fGeom );
5078 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5080 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5085 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5087 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5093 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5094 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5096 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5102 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5104 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5108#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
5113 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5114 const double targetPercent = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5115 const bool allowHoles = values.value( 2 ).toBool();
5117 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5130 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5132 if ( values.length() == 2 )
5133 segments = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5141 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5147 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5149 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5155 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5161 double area,
angle, width, height;
5174 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5175 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5177 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5183 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5190 const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( fGeom.
constGet() );
5195 result = reversed ? QVariant::fromValue(
QgsGeometry( reversed ) ) : QVariant();
5203 if (
const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( collection->
geometryN( i ) ) )
5205 reversed->addGeometry( curve->
reversed() );
5212 result = reversed ? QVariant::fromValue(
QgsGeometry( std::move( reversed ) ) ) : QVariant();
5219 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5230 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->
geometryN( 0 ) );
5239 QVariant result = exterior ? QVariant::fromValue(
QgsGeometry( exterior ) ) : QVariant();
5245 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5246 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5247 return QVariant( fGeom.
distance( sGeom ) );
5252 QgsGeometry g1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5253 QgsGeometry g2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5256 if ( values.length() == 3 && values.at( 2 ).isValid() )
5258 double densify = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5259 densify = std::clamp( densify, 0.0, 1.0 );
5267 return res > -1 ? QVariant( res ) : QVariant();
5272 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5273 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5275 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5280 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5281 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5283 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5288 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5289 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5291 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5297 if ( values.length() < 1 || values.length() > 2 )
5300 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5302 if ( values.length() == 2 )
5303 prec = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5304 QString wkt = fGeom.
asWkt( prec );
5305 return QVariant( wkt );
5310 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5311 return fGeom.
isNull() ? QVariant() : QVariant( fGeom.asWkb() );
5316 if ( values.length() != 2 )
5318 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires exactly two parameters. %n given.",
nullptr, values.length() ) );
5322 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5323 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5325 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5332 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5337 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5344 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5351 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires two points as arguments." ) );
5358 if ( pt1->
y() < pt2->
y() )
5360 else if ( pt1->
y() > pt2->
y() )
5368 if ( pt1->
x() < pt2->
x() )
5370 else if ( pt1->
x() > pt2->
x() )
5371 return M_PI + ( M_PI_2 );
5376 if ( pt1->
x() < pt2->
x() )
5378 if ( pt1->
y() < pt2->
y() )
5380 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) );
5384 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5391 if ( pt1->
y() > pt2->
y() )
5393 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) )
5398 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5399 + ( M_PI + ( M_PI_2 ) );
5406 const QgsGeometry geom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5407 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5408 QString sourceCrs = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5409 QString ellipsoid = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
5413 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires two valid point geometries." ) );
5421 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires point geometries or multi point geometries with a single part." ) );
5430 if ( sourceCrs.isEmpty() )
5432 sourceCrs = context->
variable( QStringLiteral(
"layer_crs" ) ).toString();
5435 if ( ellipsoid.isEmpty() )
5437 ellipsoid = context->
variable( QStringLiteral(
"project_ellipsoid" ) ).toString();
5444 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires a valid source CRS." ) );
5452 parent->
setEvalErrorString( QObject::tr(
"Function `bearing` requires a valid ellipsoid acronym or ellipsoid authority ID." ) );
5458 const double bearing = da.
bearing( point1, point2 );
5459 if ( std::isfinite( bearing ) )
5461 return std::fmod( bearing + 2 * M_PI, 2 * M_PI );
5474 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5478 parent->
setEvalErrorString( QStringLiteral(
"'project' requires a point geometry" ) );
5482 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5483 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5484 double inclination = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5487 QgsPoint newPoint = p->
project( distance, 180.0 * azimuth / M_PI, 180.0 * inclination / M_PI );
5494 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5495 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5497 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5504 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5508 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5515 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5523 parent->
setEvalErrorString( QStringLiteral(
"Function 'inclination' requires two points as arguments." ) );
5533 if ( values.length() != 3 )
5536 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5537 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5538 double y = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5542 QVariant result = geom.
constGet() ? QVariant::fromValue( geom ) : QVariant();
5548 if ( values.length() < 2 )
5551 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5554 return values.at( 0 );
5556 QString expString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5557 QVariant cachedExpression;
5562 if ( cachedExpression.isValid() )
5569 bool asc = values.value( 2 ).toBool();
5587 Q_ASSERT( collection );
5591 QgsExpressionSorter sorter( orderBy );
5593 QList<QgsFeature> partFeatures;
5594 partFeatures.reserve( collection->
partCount() );
5595 for (
int i = 0; i < collection->
partCount(); ++i )
5601 sorter.sortFeatures( partFeatures, unconstedContext );
5605 Q_ASSERT( orderedGeom );
5610 for (
const QgsFeature &feature : std::as_const( partFeatures ) )
5615 QVariant result = QVariant::fromValue(
QgsGeometry( orderedGeom ) );
5618 delete unconstedContext;
5625 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5626 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5630 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5636 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5637 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5641 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5647 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5648 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5652 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5658 const QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5659 const double m = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5660 const bool use3DDistance = values.at( 2 ).toBool();
5662 double x, y, z, distance;
5685 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5688 parent->
setEvalErrorString( QObject::tr(
"line_substring requires a curve geometry input" ) );
5694 curve = qgsgeometry_cast< const QgsCurve * >( lineGeom.
constGet() );
5701 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
5708 double startDistance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5709 double endDistance = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5711 std::unique_ptr< QgsCurve > substring( curve->
curveSubstring( startDistance, endDistance ) );
5713 return !result.isNull() ? QVariant::fromValue( result ) : QVariant();
5718 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5719 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5726 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5727 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5732 vertex = count + vertex;
5740 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5741 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5746 vertex = count + vertex;
5754 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5755 QgsGeometry pointGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5759 return distance >= 0 ? distance : QVariant();
5764 const QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5765 const double m = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5766 const bool use3DDistance = values.at( 2 ).toBool();
5768 double x, y, z, distance;
5777 return found ? distance : QVariant();
5782 if ( values.length() == 2 && values.at( 1 ).toInt() != 0 )
5784 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5785 return qgsRound( number, QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
5788 if ( values.length() >= 1 )
5790 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5791 return QVariant( qlonglong( std::round( number ) ) );
5806 const double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5807 const int places = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5808 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5815 const bool omitGroupSeparator = values.value( 3 ).toBool();
5816 const bool trimTrailingZeros = values.value( 4 ).toBool();
5818 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5819 if ( !omitGroupSeparator )
5820 locale.setNumberOptions( locale.numberOptions() & ~QLocale::NumberOption::OmitGroupSeparator );
5822 locale.setNumberOptions( locale.numberOptions() | QLocale::NumberOption::OmitGroupSeparator );
5824 QString res = locale.toString( value,
'f', places );
5826 if ( trimTrailingZeros )
5828#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
5829 const QChar decimal = locale.decimalPoint();
5830 const QChar zeroDigit = locale.zeroDigit();
5832 const QChar decimal = locale.decimalPoint().at( 0 );
5833 const QChar zeroDigit = locale.zeroDigit().at( 0 );
5836 if ( res.contains( decimal ) )
5838 int trimPoint = res.length() - 1;
5840 while ( res.at( trimPoint ) == zeroDigit )
5843 if ( res.at( trimPoint ) == decimal )
5846 res.truncate( trimPoint + 1 );
5855 QDateTime datetime = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
5856 const QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5857 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5860 if ( format.indexOf(
"Z" ) > 0 )
5861 datetime = datetime.toUTC();
5863 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5864 return locale.toString( datetime, format );
5869 const QVariant variant = values.at( 0 );
5871 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
5872 if ( !color.isValid() )
5875 const float alpha = color.alphaF();
5876 if ( color.spec() == QColor::Spec::Cmyk )
5878 const float avg = ( color.cyanF() + color.magentaF() + color.yellowF() ) / 3;
5879 color = QColor::fromCmykF( avg, avg, avg, color.blackF(), alpha );
5883 const float avg = ( color.redF() + color.greenF() + color.blueF() ) / 3;
5884 color.setRgbF( avg, avg, avg, alpha );
5887 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
5894 double ratio = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5899 else if ( ratio < 0 )
5904 int red =
static_cast<int>( color1.red() * ( 1 - ratio ) + color2.red() * ratio );
5905 int green =
static_cast<int>( color1.green() * ( 1 - ratio ) + color2.green() * ratio );
5906 int blue =
static_cast<int>( color1.blue() * ( 1 - ratio ) + color2.blue() * ratio );
5907 int alpha =
static_cast<int>( color1.alpha() * ( 1 - ratio ) + color2.alpha() * ratio );
5909 QColor newColor( red, green, blue, alpha );
5916 const QVariant variant1 = values.at( 0 );
5917 const QVariant variant2 = values.at( 1 );
5919 if ( variant1.userType() != variant2.userType() )
5921 parent->
setEvalErrorString( QObject::tr(
"Both color arguments must have the same type (string or color object)" ) );
5926 const QColor color1 = QgsExpressionUtils::getColorValue( variant1, parent, isQColor );
5927 if ( !color1.isValid() )
5930 const QColor color2 = QgsExpressionUtils::getColorValue( variant2, parent, isQColor );
5931 if ( !color2.isValid() )
5934 if ( ( color1.spec() == QColor::Cmyk ) != ( color2.spec() == QColor::Cmyk ) )
5936 parent->
setEvalErrorString( QObject::tr(
"Both color arguments must have compatible color type (CMYK or RGB/HSV/HSL)" ) );
5940 const float ratio =
static_cast<float>( std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0., 1. ) );
5946 const float alpha = color1.alphaF() * ( 1 - ratio ) + color2.alphaF() * ratio;
5947 if ( color1.spec() == QColor::Spec::Cmyk )
5949 float cyan = color1.cyanF() * ( 1 - ratio ) + color2.cyanF() * ratio;
5950 float magenta = color1.magentaF() * ( 1 - ratio ) + color2.magentaF() * ratio;
5951 float yellow = color1.yellowF() * ( 1 - ratio ) + color2.yellowF() * ratio;
5952 float black = color1.blackF() * ( 1 - ratio ) + color2.blackF() * ratio;
5953 newColor = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
5957 float red = color1.redF() * ( 1 - ratio ) + color2.redF() * ratio;
5958 float green = color1.greenF() * ( 1 - ratio ) + color2.greenF() * ratio;
5959 float blue = color1.blueF() * ( 1 - ratio ) + color2.blueF() * ratio;
5960 newColor = QColor::fromRgbF( red, green, blue, alpha );
5965 return isQColor ? QVariant( newColor ) : QVariant(
QgsSymbolLayerUtils::encodeColor( newColor ) );
5970 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
5971 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5972 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
5973 QColor color = QColor( red, green, blue );
5974 if ( ! color.isValid() )
5976 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( red ).arg( green ).arg( blue ) );
5977 color = QColor( 0, 0, 0 );
5980 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
5985 const float red = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
5986 const float green = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
5987 const float blue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
5988 const float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
5989 QColor color = QColor::fromRgbF( red, green, blue, alpha );
5990 if ( ! color.isValid() )
5992 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
6001 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
6002 QVariant value = node->
eval( parent, context );
6006 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
6008 value = node->
eval( parent, context );
6016 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
6018 QVariant value = node->
eval( parent, context );
6020 if ( value.toBool() )
6022 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
6024 value = node->
eval( parent, context );
6029 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
6031 value = node->
eval( parent, context );
6039 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
6040 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6041 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6042 int alpha = QgsExpressionUtils::getNativeIntValue( values.at( 3 ), parent );
6043 QColor color = QColor( red, green, blue, alpha );
6044 if ( ! color.isValid() )
6046 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
6047 color = QColor( 0, 0, 0 );
6056 if ( values.at( 0 ).userType() == qMetaTypeId< QgsGradientColorRamp>() )
6058 expRamp = QgsExpressionUtils::getRamp( values.at( 0 ), parent );
6063 QString rampName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
6067 parent->
setEvalErrorString( QObject::tr(
"\"%1\" is not a valid color ramp" ).arg( rampName ) );
6072 double value = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
6073 QColor color = ramp->
color( value );
6080 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6082 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6084 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6086 QColor color = QColor::fromHslF( hue, saturation, lightness );
6088 if ( ! color.isValid() )
6090 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( lightness ) );
6091 color = QColor( 0, 0, 0 );
6094 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6100 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6102 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6104 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6106 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
6108 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
6109 if ( ! color.isValid() )
6111 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
6112 color = QColor( 0, 0, 0 );
6119 float hue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6120 float saturation = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6121 float lightness = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6122 float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6124 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
6125 if ( ! color.isValid() )
6127 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
6137 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6139 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6141 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6143 QColor color = QColor::fromHsvF( hue, saturation, value );
6145 if ( ! color.isValid() )
6147 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( value ) );
6148 color = QColor( 0, 0, 0 );
6151 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6157 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
6159 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6161 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6163 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
6165 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
6166 if ( ! color.isValid() )
6168 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
6169 color = QColor( 0, 0, 0 );
6176 float hue = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6177 float saturation = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6178 float value = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6179 float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6180 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
6182 if ( ! color.isValid() )
6184 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
6193 const float cyan = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) ), 0.f, 1.f );
6194 const float magenta = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) ), 0.f, 1.f );
6195 const float yellow = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) ), 0.f, 1.f );
6196 const float black = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) ), 0.f, 1.f );
6197 const float alpha = std::clamp(
static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ) ), 0.f, 1.f );
6199 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6200 if ( ! color.isValid() )
6202 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
6212 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
6214 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6216 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6218 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
6220 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black );
6222 if ( ! color.isValid() )
6224 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ) );
6225 color = QColor( 0, 0, 0 );
6228 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
6234 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
6236 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
6238 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
6240 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
6242 double alpha = QgsExpressionUtils::getIntValue( values.at( 4 ), parent ) / 255.0;
6244 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
6245 if ( ! color.isValid() )
6247 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
6248 color = QColor( 0, 0, 0 );
6255 const QVariant variant = values.at( 0 );
6257 const QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6258 if ( !color.isValid() )
6261 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6262 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6264 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6265 return color.green();
6266 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6267 return color.blue();
6268 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6269 return color.alpha();
6270 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6271 return static_cast< double >( color.hsvHueF() * 360 );
6272 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6273 return static_cast< double >( color.hsvSaturationF() * 100 );
6274 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6275 return static_cast< double >( color.valueF() * 100 );
6276 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6277 return static_cast< double >( color.hslHueF() * 360 );
6278 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6279 return static_cast< double >( color.hslSaturationF() * 100 );
6280 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6281 return static_cast< double >( color.lightnessF() * 100 );
6282 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6283 return static_cast< double >( color.cyanF() * 100 );
6284 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6285 return static_cast< double >( color.magentaF() * 100 );
6286 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6287 return static_cast< double >( color.yellowF() * 100 );
6288 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6289 return static_cast< double >( color.blackF() * 100 );
6291 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6297 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
6300 parent->
setEvalErrorString( QObject::tr(
"A minimum of two colors is required to create a ramp" ) );
6304 QList< QColor > colors;
6306 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
6309 if ( !colors.last().isValid() )
6311 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( it.value().toString() ) );
6315 double step = it.key().toDouble();
6316 if ( it == map.constBegin() )
6321 else if ( it == map.constEnd() )
6331 bool discrete = values.at( 1 ).toBool();
6333 if ( colors.empty() )
6336 return QVariant::fromValue(
QgsGradientColorRamp( colors.first(), colors.last(), discrete, stops ) );
6341 const QVariant variant = values.at( 0 );
6343 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6344 if ( !color.isValid() )
6347 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6348 int value = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6349 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6350 color.setRed( std::clamp( value, 0, 255 ) );
6351 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6352 color.setGreen( std::clamp( value, 0, 255 ) );
6353 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6354 color.setBlue( std::clamp( value, 0, 255 ) );
6355 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6356 color.setAlpha( std::clamp( value, 0, 255 ) );
6357 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6358 color.setHsv( std::clamp( value, 0, 359 ), color.hsvSaturation(), color.value(), color.alpha() );
6359 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6360 color.setHsvF( color.hsvHueF(), std::clamp( value, 0, 100 ) / 100.0, color.valueF(), color.alphaF() );
6361 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6362 color.setHsvF( color.hsvHueF(), color.hsvSaturationF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6363 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6364 color.setHsl( std::clamp( value, 0, 359 ), color.hslSaturation(), color.lightness(), color.alpha() );
6365 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6366 color.setHslF( color.hslHueF(), std::clamp( value, 0, 100 ) / 100.0, color.lightnessF(), color.alphaF() );
6367 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6368 color.setHslF( color.hslHueF(), color.hslSaturationF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6369 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6370 color.setCmykF( std::clamp( value, 0, 100 ) / 100.0, color.magentaF(), color.yellowF(), color.blackF(), color.alphaF() );
6371 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6372 color.setCmykF( color.cyanF(), std::clamp( value, 0, 100 ) / 100.0, color.yellowF(), color.blackF(), color.alphaF() );
6373 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6374 color.setCmykF( color.cyanF(), color.magentaF(), std::clamp( value, 0, 100 ) / 100.0, color.blackF(), color.alphaF() );
6375 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6376 color.setCmykF( color.cyanF(), color.magentaF(), color.yellowF(), std::clamp( value, 0, 100 ) / 100.0, color.alphaF() );
6379 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6382 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6387 const QVariant variant = values.at( 0 );
6389 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6390 if ( !color.isValid() )
6393 color = color.darker( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6395 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6400 const QVariant variant = values.at( 0 );
6402 QColor color = QgsExpressionUtils::getColorValue( variant, parent, isQColor );
6403 if ( !color.isValid() )
6406 color = color.lighter( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6408 return isQColor ? QVariant( color ) : QVariant(
QgsSymbolLayerUtils::encodeColor( color ) );
6413 QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6416 return QVariant::fromValue( geom );
6422 const QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6430 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
6431 QString sAuthId = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6432 QString dAuthId = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6436 return QVariant::fromValue( fGeom );
6439 return QVariant::fromValue( fGeom );
6448 return QVariant::fromValue( fGeom );
6461 bool foundLayer =
false;
6462 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6465 if ( !featureSource || !foundLayer )
6470 const QgsFeatureId fid = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
6483 result = QVariant::fromValue( fet );
6491 bool foundLayer =
false;
6492 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6495 if ( !featureSource || !foundLayer )
6500 QString cacheValueKey;
6501 if ( values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
6503 QVariantMap attributeMap = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
6505 QMap <QString, QVariant>::const_iterator i = attributeMap.constBegin();
6506 QString filterString;
6507 for ( ; i != attributeMap.constEnd(); ++i )
6509 if ( !filterString.isEmpty() )
6511 filterString.append(
" AND " );
6515 cacheValueKey = QStringLiteral(
"getfeature:%1:%2" ).arg( featureSource->id(), filterString );
6524 QString attribute = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6525 int attributeId = featureSource->fields().lookupField( attribute );
6526 if ( attributeId == -1 )
6531 const QVariant &attVal = values.at( 2 );
6533 cacheValueKey = QStringLiteral(
"getfeature:%1:%2:%3" ).arg( featureSource->id(), QString::number( attributeId ), attVal.toString() );
6556 res = QVariant::fromValue( fet );
6571 if ( !values.isEmpty() )
6574 if ( col && ( values.size() == 1 || !values.at( 1 ).isValid() ) )
6575 fieldName = col->
name();
6576 else if ( values.size() == 2 )
6577 fieldName = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6580 QVariant value = values.at( 0 );
6585 if ( fieldIndex == -1 )
6587 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: Field not found %2" ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6593 QgsVectorLayer *layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
6596 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName, value.toString() );
6605 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName );
6616 result =
formatter->representValue( layer, fieldIndex, setup.
config(), cache, value );
6623 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: function cannot be evaluated without a context." ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6631 const QVariant data = values.at( 0 );
6632 const QMimeDatabase db;
6633 return db.mimeTypeForData( data.toByteArray() ).name();
6638 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6640 bool foundLayer =
false;
6641 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [layerProperty](
QgsMapLayer * layer )-> QVariant
6647 if ( QString::compare( layerProperty, QStringLiteral(
"name" ), Qt::CaseInsensitive ) == 0 )
6648 return layer->name();
6649 else if ( QString::compare( layerProperty, QStringLiteral(
"id" ), Qt::CaseInsensitive ) == 0 )
6651 else if ( QString::compare( layerProperty, QStringLiteral(
"title" ), Qt::CaseInsensitive ) == 0 )
6652 return !layer->metadata().title().isEmpty() ? layer->metadata().title() : layer->serverProperties()->title();
6653 else if ( QString::compare( layerProperty, QStringLiteral(
"abstract" ), Qt::CaseInsensitive ) == 0 )
6654 return !layer->metadata().abstract().isEmpty() ? layer->metadata().abstract() : layer->serverProperties()->abstract();
6655 else if ( QString::compare( layerProperty, QStringLiteral(
"keywords" ), Qt::CaseInsensitive ) == 0 )
6657 QStringList keywords;
6658 const QgsAbstractMetadataBase::KeywordMap keywordMap = layer->metadata().keywords();
6659 for ( auto it = keywordMap.constBegin(); it != keywordMap.constEnd(); ++it )
6661 keywords.append( it.value() );
6663 if ( !keywords.isEmpty() )
6665 return layer->serverProperties()->keywordList();
6667 else if ( QString::compare( layerProperty, QStringLiteral(
"data_url" ), Qt::CaseInsensitive ) == 0 )
6669 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution" ), Qt::CaseInsensitive ) == 0 )
6671 return !layer->
metadata().
rights().isEmpty() ? QVariant( layer->
metadata().
rights() ) : QVariant( layer->serverProperties()->attribution() );
6673 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution_url" ), Qt::CaseInsensitive ) == 0 )
6675 else if ( QString::compare( layerProperty, QStringLiteral(
"source" ), Qt::CaseInsensitive ) == 0 )
6677 else if ( QString::compare( layerProperty, QStringLiteral(
"min_scale" ), Qt::CaseInsensitive ) == 0 )
6679 else if ( QString::compare( layerProperty, QStringLiteral(
"max_scale" ), Qt::CaseInsensitive ) == 0 )
6681 else if ( QString::compare( layerProperty, QStringLiteral(
"is_editable" ), Qt::CaseInsensitive ) == 0 )
6683 else if ( QString::compare( layerProperty, QStringLiteral(
"crs" ), Qt::CaseInsensitive ) == 0 )
6685 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_definition" ), Qt::CaseInsensitive ) == 0 )
6687 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_description" ), Qt::CaseInsensitive ) == 0 )
6689 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_ellipsoid" ), Qt::CaseInsensitive ) == 0 )
6691 else if ( QString::compare( layerProperty, QStringLiteral(
"extent" ), Qt::CaseInsensitive ) == 0 )
6694 QVariant result = QVariant::fromValue( extentGeom );
6697 else if ( QString::compare( layerProperty, QStringLiteral(
"distance_units" ), Qt::CaseInsensitive ) == 0 )
6699 else if ( QString::compare( layerProperty, QStringLiteral(
"path" ), Qt::CaseInsensitive ) == 0 )
6702 return decodedUri.value( QStringLiteral(
"path" ) );
6704 else if ( QString::compare( layerProperty, QStringLiteral(
"type" ), Qt::CaseInsensitive ) == 0 )
6706 switch ( layer->
type() )
6709 return QCoreApplication::translate(
"expressions",
"Vector" );
6711 return QCoreApplication::translate(
"expressions",
"Raster" );
6713 return QCoreApplication::translate(
"expressions",
"Mesh" );
6715 return QCoreApplication::translate(
"expressions",
"Vector Tile" );
6717 return QCoreApplication::translate(
"expressions",
"Plugin" );
6719 return QCoreApplication::translate(
"expressions",
"Annotation" );
6721 return QCoreApplication::translate(
"expressions",
"Point Cloud" );
6723 return QCoreApplication::translate(
"expressions",
"Group" );
6725 return QCoreApplication::translate(
"expressions",
"Tiled Scene" );
6731 QgsVectorLayer *vLayer = qobject_cast< QgsVectorLayer * >( layer );
6734 if ( QString::compare( layerProperty, QStringLiteral(
"storage_type" ), Qt::CaseInsensitive ) == 0 )
6736 else if ( QString::compare( layerProperty, QStringLiteral(
"geometry_type" ), Qt::CaseInsensitive ) == 0 )
6738 else if ( QString::compare( layerProperty, QStringLiteral(
"feature_count" ), Qt::CaseInsensitive ) == 0 )
6754 const QString uriPart = values.at( 1 ).toString();
6756 bool foundLayer =
false;
6758 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, uriPart](
QgsMapLayer * layer )-> QVariant
6760 if ( !layer->dataProvider() )
6762 parent->setEvalErrorString( QObject::tr(
"Layer %1 has invalid data provider" ).arg( layer->name() ) );
6768 if ( !uriPart.isNull() )
6770 return decodedUri.value( uriPart );
6780 parent->
setEvalErrorString( QObject::tr(
"Function `decode_uri` requires a valid layer." ) );
6791 const int band = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6792 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6794 bool foundLayer =
false;
6795 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, band, layerProperty](
QgsMapLayer * layer )-> QVariant
6797 QgsRasterLayer *rl = qobject_cast< QgsRasterLayer * >( layer );
6801 if ( band < 1 || band > rl->bandCount() )
6803 parent->setEvalErrorString( QObject::tr(
"Invalid band number %1 for layer" ).arg( band ) );
6809 if ( QString::compare( layerProperty, QStringLiteral(
"avg" ), Qt::CaseInsensitive ) == 0 )
6811 else if ( QString::compare( layerProperty, QStringLiteral(
"stdev" ), Qt::CaseInsensitive ) == 0 )
6813 else if ( QString::compare( layerProperty, QStringLiteral(
"min" ), Qt::CaseInsensitive ) == 0 )
6815 else if ( QString::compare( layerProperty, QStringLiteral(
"max" ), Qt::CaseInsensitive ) == 0 )
6817 else if ( QString::compare( layerProperty, QStringLiteral(
"range" ), Qt::CaseInsensitive ) == 0 )
6819 else if ( QString::compare( layerProperty, QStringLiteral(
"sum" ), Qt::CaseInsensitive ) == 0 )
6823 parent->
setEvalErrorString( QObject::tr(
"Invalid raster statistic: '%1'" ).arg( layerProperty ) );
6851 parent->
setEvalErrorString( QObject::tr(
"Function `raster_statistic` requires a valid raster layer." ) );
6868 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6869 bool ascending = values.value( 1 ).toBool();
6870 std::sort( list.begin(), list.end(), [ascending]( QVariant a, QVariant b ) ->
bool { return ( !ascending ? qgsVariantLessThan( b, a ) : qgsVariantLessThan( a, b ) ); } );
6876 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).length();
6881 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).contains( values.at( 1 ) ) );
6886 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).count( values.at( 1 ) ) );
6891 QVariantList listA = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6892 QVariantList listB = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
6894 for (
const auto &item : listB )
6896 if ( listA.contains( item ) )
6900 return QVariant( match == listB.count() );
6905 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).indexOf( values.at( 1 ) );
6910 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6911 const int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6912 if ( pos < list.length() && pos >= 0 )
return list.at( pos );
6913 else if ( pos < 0 && ( list.length() + pos ) >= 0 )
6914 return list.at( list.length() + pos );
6920 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6921 return list.value( 0 );
6926 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6927 return list.value( list.size() - 1 );
6932 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6933 return list.isEmpty() ? QVariant() : *std::min_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
6938 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6939 return list.isEmpty() ? QVariant() : *std::max_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
6944 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6947 for (
const QVariant &item : list )
6949 switch ( item.userType() )
6951 case QMetaType::Int:
6952 case QMetaType::UInt:
6953 case QMetaType::LongLong:
6954 case QMetaType::ULongLong:
6955 case QMetaType::Float:
6956 case QMetaType::Double:
6957 total += item.toDouble();
6962 return i == 0 ? QVariant() : total / i;
6967 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6968 QVariantList numbers;
6969 for (
const auto &item : list )
6971 switch ( item.userType() )
6973 case QMetaType::Int:
6974 case QMetaType::UInt:
6975 case QMetaType::LongLong:
6976 case QMetaType::ULongLong:
6977 case QMetaType::Float:
6978 case QMetaType::Double:
6979 numbers.append( item );
6983 std::sort( numbers.begin(), numbers.end(), []( QVariant a, QVariant b ) ->
bool { return ( qgsVariantLessThan( a, b ) ); } );
6984 const int count = numbers.count();
6989 else if ( count % 2 )
6991 return numbers.at( count / 2 );
6995 return ( numbers.at( count / 2 - 1 ).toDouble() + numbers.at( count / 2 ).toDouble() ) / 2;
7001 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7004 for (
const QVariant &item : list )
7006 switch ( item.userType() )
7008 case QMetaType::Int:
7009 case QMetaType::UInt:
7010 case QMetaType::LongLong:
7011 case QMetaType::ULongLong:
7012 case QMetaType::Float:
7013 case QMetaType::Double:
7014 total += item.toDouble();
7019 return i == 0 ? QVariant() : total;
7022static QVariant convertToSameType(
const QVariant &value, QMetaType::Type type )
7024 QVariant result = value;
7025 result.convert(
static_cast<int>( type ) );
7031 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7032 QHash< QVariant, int > hash;
7033 for (
const auto &item : list )
7037 const QList< int > occurrences = hash.values();
7038 if ( occurrences.empty() )
7039 return QVariantList();
7041 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
7043 const QString option = values.at( 1 ).toString();
7044 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
7046 return convertToSameType( hash.keys( maxValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7048 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
7050 if ( hash.isEmpty() )
7053 return QVariant( hash.key( maxValue ) );
7055 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
7057 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( maxValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) ), context, parent, node );
7059 else if ( option.compare( QLatin1String(
"real_majority" ), Qt::CaseInsensitive ) == 0 )
7061 if ( maxValue * 2 <= list.size() )
7064 return QVariant( hash.key( maxValue ) );
7075 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7076 QHash< QVariant, int > hash;
7077 for (
const auto &item : list )
7081 const QList< int > occurrences = hash.values();
7082 if ( occurrences.empty() )
7083 return QVariantList();
7085 const int minValue = *std::min_element( occurrences.constBegin(), occurrences.constEnd() );
7087 const QString option = values.at( 1 ).toString();
7088 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
7090 return convertToSameType( hash.keys( minValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7092 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
7094 if ( hash.isEmpty() )
7097 return QVariant( hash.key( minValue ) );
7099 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
7101 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( minValue ),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) ), context, parent, node );
7103 else if ( option.compare( QLatin1String(
"real_minority" ), Qt::CaseInsensitive ) == 0 )
7105 if ( hash.isEmpty() )
7109 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
7110 if ( maxValue * 2 > list.size() )
7111 hash.remove( hash.key( maxValue ) );
7113 return convertToSameType( hash.keys(),
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7124 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7125 list.append( values.at( 1 ) );
7126 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7131 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7132 list.prepend( values.at( 1 ) );
7133 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7138 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7139 list.insert( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), values.at( 2 ) );
7140 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7145 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7146 int position = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7148 position = position + list.length();
7149 if ( position >= 0 && position < list.length() )
7150 list.removeAt( position );
7151 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7159 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7161 const QVariant toRemove = values.at( 1 );
7164 list.erase( std::remove_if( list.begin(), list.end(), [](
const QVariant & element )
7166 return QgsVariantUtils::isNull( element );
7171 list.removeAll( toRemove );
7173 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7178 if ( values.count() == 2 && values.at( 1 ).userType() == QMetaType::Type::QVariantMap )
7180 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
7182 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7183 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
7185 int index = list.indexOf( it.key() );
7186 while ( index >= 0 )
7188 list.replace( index, it.value() );
7189 index = list.indexOf( it.key() );
7193 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7195 else if ( values.count() == 3 )
7197 QVariantList before;
7199 bool isSingleReplacement =
false;
7201 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).userType() != QMetaType::Type::QStringList )
7203 before = QVariantList() << values.at( 1 );
7207 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
7210 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
7212 after = QVariantList() << values.at( 2 );
7213 isSingleReplacement =
true;
7217 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
7220 if ( !isSingleReplacement && before.length() != after.length() )
7222 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
7226 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7227 for (
int i = 0; i < before.length(); i++ )
7229 int index = list.indexOf( before.at( i ) );
7230 while ( index >= 0 )
7232 list.replace( index, after.at( isSingleReplacement ? 0 : i ) );
7233 index = list.indexOf( before.at( i ) );
7237 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7241 parent->
setEvalErrorString( QObject::tr(
"Function array_replace requires 2 or 3 arguments" ) );
7248 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7249 QVariantList list_new;
7251 for (
const QVariant &cur :
QgsExpressionUtils::getListValue( values.at( 1 ), parent ) )
7253 while ( list.removeOne( cur ) )
7255 list_new.append( cur );
7259 list_new.append( list );
7261 return convertToSameType( list_new,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7267 for (
const QVariant &cur : values )
7269 list += QgsExpressionUtils::getListValue( cur, parent );
7271 return convertToSameType( list,
static_cast<QMetaType::Type
>( values.at( 0 ).userType() ) );
7276 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7277 int start_pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7278 const int end_pos = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
7279 int slice_length = 0;
7281 if ( start_pos < 0 )
7283 start_pos = list.length() + start_pos;
7287 slice_length = end_pos - start_pos + 1;
7291 slice_length = list.length() + end_pos - start_pos + 1;
7294 if ( slice_length < 0 )
7298 list = list.mid( start_pos, slice_length );
7304 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7305 std::reverse( list.begin(), list.end() );
7311 const QVariantList array1 = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7312 const QVariantList array2 = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
7313 for (
const QVariant &cur : array2 )
7315 if ( array1.contains( cur ) )
7316 return QVariant(
true );
7318 return QVariant(
false );
7323 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7325 QVariantList distinct;
7327 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7329 if ( !distinct.contains( *it ) )
7331 distinct += ( *it );
7340 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7341 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7342 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7346 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7348 str += ( !( *it ).toString().isEmpty() ) ? ( *it ).toString() : empty;
7349 if ( it != ( array.constEnd() - 1 ) )
7355 return QVariant(
str );
7360 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7361 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7362 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7364 QStringList list =
str.split( delimiter );
7367 for ( QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
7369 array += ( !( *it ).isEmpty() ) ? *it : empty;
7377 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7378 QJsonDocument document = QJsonDocument::fromJson(
str.toUtf8() );
7379 if ( document.isNull() )
7382 return document.toVariant();
7388 QJsonDocument document = QJsonDocument::fromVariant( values.at( 0 ) );
7389 return QString( document.toJson( QJsonDocument::Compact ) );
7394 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7395 if (
str.isEmpty() )
7396 return QVariantMap();
7404 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7411 for (
int i = 0; i + 1 < values.length(); i += 2 )
7413 result.insert( QgsExpressionUtils::getStringValue( values.at( i ), parent ), values.at( i + 1 ) );
7420 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7421 const QString prefix = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7422 QVariantMap resultMap;
7424 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7426 resultMap.insert( QString( it.key() ).prepend( prefix ), it.value() );
7434 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).value( values.at( 1 ).toString() );
7439 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).contains( values.at( 1 ).toString() );
7444 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7445 map.remove( values.at( 1 ).toString() );
7451 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7452 map.insert( values.at( 1 ).toString(), values.at( 2 ) );
7459 for (
const QVariant &cur : values )
7461 const QVariantMap curMap = QgsExpressionUtils::getMapValue( cur, parent );
7462 for ( QVariantMap::const_iterator it = curMap.constBegin(); it != curMap.constEnd(); ++it )
7463 result.insert( it.key(), it.value() );
7470 return QStringList( QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).keys() );
7475 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).values();
7480 const QString envVarName = values.at( 0 ).toString();
7481 if ( !QProcessEnvironment::systemEnvironment().contains( envVarName ) )
7484 return QProcessEnvironment::systemEnvironment().value( envVarName );
7489 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7492 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"base_file_name" ) ) );
7495 return QFileInfo( file ).completeBaseName();
7500 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7503 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_suffix" ) ) );
7506 return QFileInfo( file ).completeSuffix();
7511 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7514 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_exists" ) ) );
7517 return QFileInfo::exists( file );
7522 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7525 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_name" ) ) );
7528 return QFileInfo( file ).fileName();
7533 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7536 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_file" ) ) );
7539 return QFileInfo( file ).isFile();
7544 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7547 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_directory" ) ) );
7550 return QFileInfo( file ).isDir();
7555 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7558 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_path" ) ) );
7561 return QDir::toNativeSeparators( QFileInfo( file ).path() );
7566 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7569 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_size" ) ) );
7572 return QFileInfo( file ).size();
7575static QVariant fcnHash(
const QString &
str,
const QCryptographicHash::Algorithm
algorithm )
7577 return QString( QCryptographicHash::hash(
str.toUtf8(),
algorithm ).toHex() );
7583 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7584 QString method = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).toLower();
7586 if ( method == QLatin1String(
"md4" ) )
7588 hash = fcnHash(
str, QCryptographicHash::Md4 );
7590 else if ( method == QLatin1String(
"md5" ) )
7592 hash = fcnHash(
str, QCryptographicHash::Md5 );
7594 else if ( method == QLatin1String(
"sha1" ) )
7596 hash = fcnHash(
str, QCryptographicHash::Sha1 );
7598 else if ( method == QLatin1String(
"sha224" ) )
7600 hash = fcnHash(
str, QCryptographicHash::Sha224 );
7602 else if ( method == QLatin1String(
"sha256" ) )
7604 hash = fcnHash(
str, QCryptographicHash::Sha256 );
7606 else if ( method == QLatin1String(
"sha384" ) )
7608 hash = fcnHash(
str, QCryptographicHash::Sha384 );
7610 else if ( method == QLatin1String(
"sha512" ) )
7612 hash = fcnHash(
str, QCryptographicHash::Sha512 );
7614 else if ( method == QLatin1String(
"sha3_224" ) )
7616 hash = fcnHash(
str, QCryptographicHash::Sha3_224 );
7618 else if ( method == QLatin1String(
"sha3_256" ) )
7620 hash = fcnHash(
str, QCryptographicHash::Sha3_256 );
7622 else if ( method == QLatin1String(
"sha3_384" ) )
7624 hash = fcnHash(
str, QCryptographicHash::Sha3_384 );
7626 else if ( method == QLatin1String(
"sha3_512" ) )
7628 hash = fcnHash(
str, QCryptographicHash::Sha3_512 );
7630 else if ( method == QLatin1String(
"keccak_224" ) )
7632 hash = fcnHash(
str, QCryptographicHash::Keccak_224 );
7634 else if ( method == QLatin1String(
"keccak_256" ) )
7636 hash = fcnHash(
str, QCryptographicHash::Keccak_256 );
7638 else if ( method == QLatin1String(
"keccak_384" ) )
7640 hash = fcnHash(
str, QCryptographicHash::Keccak_384 );
7642 else if ( method == QLatin1String(
"keccak_512" ) )
7644 hash = fcnHash(
str, QCryptographicHash::Keccak_512 );
7648 parent->
setEvalErrorString( QObject::tr(
"Hash method %1 is not available on this system." ).arg(
str ) );
7655 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Md5 );
7660 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Sha256 );
7665 const QByteArray input = values.at( 0 ).toByteArray();
7666 return QVariant( QString( input.toBase64() ) );
7671 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7673 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7675 query.addQueryItem( it.key(), it.value().toString() );
7677 return query.toString( QUrl::ComponentFormattingOption::FullyEncoded );
7682 const QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7683 const QByteArray base64 = value.toLocal8Bit();
7684 const QByteArray decoded = QByteArray::fromBase64( base64 );
7685 return QVariant( decoded );
7690static 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 )
7693 const QVariant sourceLayerRef = context->
variable( QStringLiteral(
"layer" ) );
7696 QgsVectorLayer *sourceLayer = QgsExpressionUtils::getVectorLayer( sourceLayerRef, context, parent );
7705 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
7708 const bool layerCanBeCached = node->
isStatic( parent, context );
7709 QVariant targetLayerValue = node->
eval( parent, context );
7713 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
7715 QString subExpString = node->dump();
7717 bool testOnly = ( subExpString ==
"NULL" );
7720 QgsVectorLayer *targetLayer = QgsExpressionUtils::getVectorLayer( targetLayerValue, context, parent );
7724 parent->
setEvalErrorString( QObject::tr(
"Layer '%1' could not be loaded." ).arg( targetLayerValue.toString() ) );
7729 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
7731 QString filterString = node->dump();
7732 if ( filterString !=
"NULL" )
7734 request.setFilterExpression( filterString );
7738 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
7740 QVariant limitValue = node->eval( parent, context );
7742 qlonglong limit = QgsExpressionUtils::getIntValue( limitValue, parent );
7745 double max_distance = 0;
7746 if ( isNearestFunc )
7748 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
7750 QVariant distanceValue = node->eval( parent, context );
7752 max_distance = QgsExpressionUtils::getDoubleValue( distanceValue, parent );
7756 node = QgsExpressionUtils::getNode( values.at( isNearestFunc ? 5 : 4 ), parent );
7758 QVariant cacheValue = node->eval( parent, context );
7760 bool cacheEnabled = cacheValue.toBool();
7766 double minOverlap { -1 };
7767 double minInscribedCircleRadius { -1 };
7768 bool returnDetails =
false;
7769 bool sortByMeasure =
false;
7770 bool sortAscending =
false;
7771 bool requireMeasures =
false;
7772 bool overlapOrRadiusFilter =
false;
7773 if ( isIntersectsFunc )
7776 node = QgsExpressionUtils::getNode( values.at( 5 ), parent );
7778 const QVariant minOverlapValue = node->eval( parent, context );
7780 minOverlap = QgsExpressionUtils::getDoubleValue( minOverlapValue, parent );
7781 node = QgsExpressionUtils::getNode( values.at( 6 ), parent );
7783 const QVariant minInscribedCircleRadiusValue = node->eval( parent, context );
7785 minInscribedCircleRadius = QgsExpressionUtils::getDoubleValue( minInscribedCircleRadiusValue, parent );
7786 node = QgsExpressionUtils::getNode( values.at( 7 ), parent );
7788 returnDetails = !testOnly && node->eval( parent, context ).toBool();
7789 node = QgsExpressionUtils::getNode( values.at( 8 ), parent );
7791 const QString sorting { node->eval( parent, context ).toString().toLower() };
7792 sortByMeasure = !testOnly && ( sorting.startsWith(
"asc" ) || sorting.startsWith(
"des" ) );
7793 sortAscending = sorting.startsWith(
"asc" );
7794 requireMeasures = sortByMeasure || returnDetails;
7795 overlapOrRadiusFilter = minInscribedCircleRadius != -1 || minOverlap != -1;
7802 if ( sourceLayer && targetLayer->crs() != sourceLayer->crs() )
7805 request.setDestinationCrs( sourceLayer->crs(), TransformContext );
7808 bool sameLayers = ( sourceLayer && sourceLayer->id() == targetLayer->id() );
7811 if ( bboxGrow != 0 )
7813 intDomain.
grow( bboxGrow );
7816 const QString cacheBase { QStringLiteral(
"%1:%2:%3" ).arg( targetLayer->id(), subExpString, filterString ) };
7822 QList<QgsFeature> features;
7823 if ( isNearestFunc || ( layerCanBeCached && cacheEnabled ) )
7827 const QString cacheLayer { QStringLiteral(
"ovrlaylyr:%1" ).arg( cacheBase ) };
7828 const QString cacheIndex { QStringLiteral(
"ovrlayidx:%1" ).arg( cacheBase ) };
7832 cachedTarget = targetLayer->
materialize( request );
7833 if ( layerCanBeCached )
7834 context->
setCachedValue( cacheLayer, QVariant::fromValue( cachedTarget ) );
7844 if ( layerCanBeCached )
7845 context->
setCachedValue( cacheIndex, QVariant::fromValue( spatialIndex ) );
7852 QList<QgsFeatureId> fidsList;
7853 if ( isNearestFunc )
7855 fidsList = spatialIndex.
nearestNeighbor( geometry, sameLayers ? limit + 1 : limit, max_distance );
7859 fidsList = spatialIndex.
intersects( intDomain );
7862 QListIterator<QgsFeatureId> i( fidsList );
7863 while ( i.hasNext() )
7866 if ( sameLayers && feat.
id() == fId2 )
7868 features.append( cachedTarget->
getFeature( fId2 ) );
7876 request.setFilterRect( intDomain );
7881 if ( sameLayers && feat.
id() == feat2.
id() )
7883 features.append( feat2 );
7891 const QString expCacheKey { QStringLiteral(
"exp:%1" ).arg( cacheBase ) };
7892 const QString ctxCacheKey { QStringLiteral(
"ctx:%1" ).arg( cacheBase ) };
7898 subExpression.
prepare( &subContext );
7911 auto testLinestring = [ = ](
const QgsGeometry intersection,
double & overlapValue ) ->
bool
7913 bool testResult {
false };
7915 QVector<double> overlapValues;
7918 const QgsCurve *geom = qgsgeometry_cast< const QgsCurve * >( *it );
7920 if ( minOverlap != -1 || requireMeasures )
7922 overlapValue = geom->
length();
7923 overlapValues.append( overlapValue );
7924 if ( minOverlap != -1 )
7926 if ( overlapValue >= minOverlap )
7938 if ( ! overlapValues.isEmpty() )
7940 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
7947 auto testPolygon = [ = ](
const QgsGeometry intersection,
double & radiusValue,
double & overlapValue ) ->
bool
7950 bool testResult {
false };
7952 QVector<double> overlapValues;
7953 QVector<double> radiusValues;
7956 const QgsCurvePolygon *geom = qgsgeometry_cast< const QgsCurvePolygon * >( *it );
7958 if ( minOverlap != -1 || requireMeasures )
7960 overlapValue = geom->
area();
7961 overlapValues.append( geom->
area() );
7962 if ( minOverlap != - 1 )
7964 if ( overlapValue >= minOverlap )
7976 if ( minInscribedCircleRadius != -1 || requireMeasures )
7979 const double width = bbox.
width();
7980 const double height = bbox.
height();
7981 const double size = width > height ? width : height;
7982 const double tolerance = size / 100.0;
7984 testResult = radiusValue >= minInscribedCircleRadius;
7985 radiusValues.append( radiusValues );
7990 if ( !radiusValues.isEmpty() )
7992 radiusValue = *std::max_element( radiusValues.cbegin(), radiusValues.cend() );
7995 if ( ! overlapValues.isEmpty() )
7997 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
8007 QVariantList results;
8009 QListIterator<QgsFeature> i( features );
8010 while ( i.hasNext() && ( sortByMeasure || limit == -1 || foundCount < limit ) )
8016 if ( ! relationFunction || ( geometry.*relationFunction )( feat2.
geometry() ) )
8019 double overlapValue = -1;
8020 double radiusValue = -1;
8022 if ( isIntersectsFunc && ( requireMeasures || overlapOrRadiusFilter ) )
8029 switch ( intersection.
type() )
8036 bool testResult { testPolygon( intersection, radiusValue, overlapValue ) };
8038 if ( ! testResult && overlapOrRadiusFilter )
8051 if ( minInscribedCircleRadius != -1 )
8057 const bool testResult { testLinestring( intersection, overlapValue ) };
8059 if ( ! testResult && overlapOrRadiusFilter )
8072 if ( minInscribedCircleRadius != -1 )
8077 bool testResult {
false };
8078 if ( minOverlap != -1 || requireMeasures )
8098 testResult = testLinestring( feat2.
geometry(), overlapValue );
8103 testResult = testPolygon( feat2.
geometry(), radiusValue, overlapValue );
8109 if ( ! testResult && overlapOrRadiusFilter )
8137 const QVariant expResult = subExpression.
evaluate( &subContext );
8139 if ( requireMeasures )
8141 QVariantMap resultRecord;
8142 resultRecord.insert( QStringLiteral(
"id" ), feat2.
id() );
8143 resultRecord.insert( QStringLiteral(
"result" ), expResult );
8145 resultRecord.insert( QStringLiteral(
"overlap" ), overlapValue );
8147 if ( radiusValue != -1 )
8149 resultRecord.insert( QStringLiteral(
"radius" ), radiusValue );
8151 results.append( resultRecord );
8155 results.append( expResult );
8161 results.append( feat2.
id() );
8175 if ( requireMeasures )
8177 if ( sortByMeasure )
8179 std::sort( results.begin(), results.end(), [ sortAscending ](
const QVariant & recordA,
const QVariant & recordB ) ->
bool
8181 return sortAscending ?
8182 recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble()
8183 : recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble();
8187 if ( limit > 0 && results.size() > limit )
8189 results.erase( results.begin() + limit );
8192 if ( ! returnDetails )
8194 QVariantList expResults;
8195 for (
auto it = results.constBegin(); it != results.constEnd(); ++it )
8197 expResults.append( it->toMap().value( QStringLiteral(
"result" ) ) );
8207 QVariantList disjoint_results;
8216 if ( !results.contains( feat2.
id() ) )
8219 disjoint_results.append( subExpression.
evaluate( &subContext ) );
8222 return disjoint_results;
8265 return executeGeomOverlay( values, context, parent,
nullptr,
false, 0,
true );
8274 QMutexLocker locker( &sFunctionsMutex );
8276 QList<QgsExpressionFunction *> &functions = *sFunctions();
8278 if ( functions.isEmpty() )
8316 functions << randFunc;
8320 functions << randfFunc;
8323 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max" ), -1, fcnMax, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8324 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min" ), -1, fcnMin, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8331 <<
new QgsStaticExpressionFunction( QStringLiteral(
"pi" ), 0, fcnPi, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$pi" ) )
8335 <<
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" ) )
8336 <<
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" ) )
8337 <<
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" ) )
8342 <<
new QgsStaticExpressionFunction( QStringLiteral(
"coalesce" ), -1, fcnCoalesce, QStringLiteral(
"Conditionals" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8356 QStringLiteral(
"Aggregates" ),
8365 if ( !node->
args() )
8368 QSet<QString> referencedVars;
8380 return referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() );
8389 if ( !node->
args() )
8390 return QSet<QString>();
8392 QSet<QString> referencedCols;
8393 QSet<QString> referencedVars;
8408 if ( referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() ) )
8411 return referencedCols;
8424 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count" ), aggParams, fcnAggregateCount, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8425 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_distinct" ), aggParams, fcnAggregateCountDistinct, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8426 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_missing" ), aggParams, fcnAggregateCountMissing, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8427 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minimum" ), aggParams, fcnAggregateMin, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8428 <<
new QgsStaticExpressionFunction( QStringLiteral(
"maximum" ), aggParams, fcnAggregateMax, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8429 <<
new QgsStaticExpressionFunction( QStringLiteral(
"sum" ), aggParams, fcnAggregateSum, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8430 <<
new QgsStaticExpressionFunction( QStringLiteral(
"mean" ), aggParams, fcnAggregateMean, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8431 <<
new QgsStaticExpressionFunction( QStringLiteral(
"median" ), aggParams, fcnAggregateMedian, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8432 <<
new QgsStaticExpressionFunction( QStringLiteral(
"stdev" ), aggParams, fcnAggregateStdev, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8433 <<
new QgsStaticExpressionFunction( QStringLiteral(
"range" ), aggParams, fcnAggregateRange, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8434 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minority" ), aggParams, fcnAggregateMinority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8435 <<
new QgsStaticExpressionFunction( QStringLiteral(
"majority" ), aggParams, fcnAggregateMajority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8436 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q1" ), aggParams, fcnAggregateQ1, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8437 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q3" ), aggParams, fcnAggregateQ3, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8438 <<
new QgsStaticExpressionFunction( QStringLiteral(
"iqr" ), aggParams, fcnAggregateIQR, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8439 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min_length" ), aggParams, fcnAggregateMinLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8440 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max_length" ), aggParams, fcnAggregateMaxLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8441 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect" ), aggParams, fcnAggregateCollectGeometry, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8442 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate" ), aggParamsConcat, fcnAggregateStringConcat, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8443 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate_unique" ), aggParamsConcat, fcnAggregateStringConcatUnique, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8444 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array_agg" ), aggParamsArray, fcnAggregateArray, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8449 <<
new QgsStaticExpressionFunction( QStringLiteral(
"now" ), 0, fcnNow, QStringLiteral(
"Date and Time" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$now" ) )
8452 fcnAge, QStringLiteral(
"Date and Time" ) )
8466 fcnMakeDate, QStringLiteral(
"Date and Time" ) )
8470 fcnMakeTime, QStringLiteral(
"Date and Time" ) )
8477 fcnMakeDateTime, QStringLiteral(
"Date and Time" ) )
8485 fcnMakeInterval, QStringLiteral(
"Date and Time" ) )
8510 false, QSet< QString >(),
false, QStringList(), true )
8511 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concat" ), -1, fcnConcat, QStringLiteral(
"String" ), QString(),
false, QSet<QString>(),
false, QStringList(), true )
8529 fcnColorMixRgb, QStringLiteral(
"Color" ) )
8533 fcnColorMix, QStringLiteral(
"Color" ) )
8537 fcnColorRgb, QStringLiteral(
"Color" ) )
8542 fcnColorRgbF, QStringLiteral(
"Color" ) )
8547 fncColorRgba, QStringLiteral(
"Color" ) )
8553 fcnCreateRamp, QStringLiteral(
"Color" ) )
8557 fcnColorHsl, QStringLiteral(
"Color" ) )
8562 fncColorHsla, QStringLiteral(
"Color" ) )
8567 fcnColorHslF, QStringLiteral(
"Color" ) )
8571 fcnColorHsv, QStringLiteral(
"Color" ) )
8576 fncColorHsva, QStringLiteral(
"Color" ) )
8581 fcnColorHsvF, QStringLiteral(
"Color" ) )
8586 fcnColorCmyk, QStringLiteral(
"Color" ) )
8592 fncColorCmyka, QStringLiteral(
"Color" ) )
8598 fcnColorCmykF, QStringLiteral(
"Color" ) )
8601 fncColorPart, QStringLiteral(
"Color" ) )
8604 fncDarker, QStringLiteral(
"Color" ) )
8607 fncLighter, QStringLiteral(
"Color" ) )
8612 fcnBaseFileName, QStringLiteral(
"Files and Paths" ) )
8614 fcnFileSuffix, QStringLiteral(
"Files and Paths" ) )
8616 fcnFileExists, QStringLiteral(
"Files and Paths" ) )
8618 fcnFileName, QStringLiteral(
"Files and Paths" ) )
8620 fcnPathIsFile, QStringLiteral(
"Files and Paths" ) )
8622 fcnPathIsDir, QStringLiteral(
"Files and Paths" ) )
8624 fcnFilePath, QStringLiteral(
"Files and Paths" ) )
8626 fcnFileSize, QStringLiteral(
"Files and Paths" ) )
8629 fcnExif, QStringLiteral(
"Files and Paths" ) )
8631 fcnExifGeoTag, QStringLiteral(
"GeometryGroup" ) )
8635 fcnGenericHash, QStringLiteral(
"Conversions" ) )
8637 fcnHashMd5, QStringLiteral(
"Conversions" ) )
8639 fcnHashSha256, QStringLiteral(
"Conversions" ) )
8643 fcnToBase64, QStringLiteral(
"Conversions" ) )
8645 fcnFromBase64, QStringLiteral(
"Conversions" ) )
8651 geomFunc->setIsStatic(
false );
8652 functions << geomFunc;
8656 functions << areaFunc;
8662 functions << lengthFunc;
8666 functions << perimeterFunc;
8672 fcnRoundness, QStringLiteral(
"GeometryGroup" ) );
8686 QMap< QString, QgsExpressionFunction::FcnEval > geometry_overlay_definitions
8688 { QStringLiteral(
"overlay_intersects" ), fcnGeomOverlayIntersects },
8689 { QStringLiteral(
"overlay_contains" ), fcnGeomOverlayContains },
8690 { QStringLiteral(
"overlay_crosses" ), fcnGeomOverlayCrosses },
8691 { QStringLiteral(
"overlay_equals" ), fcnGeomOverlayEquals },
8692 { QStringLiteral(
"overlay_touches" ), fcnGeomOverlayTouches },
8693 { QStringLiteral(
"overlay_disjoint" ), fcnGeomOverlayDisjoint },
8694 { QStringLiteral(
"overlay_within" ), fcnGeomOverlayWithin },
8696 QMapIterator< QString, QgsExpressionFunction::FcnEval > i( geometry_overlay_definitions );
8697 while ( i.hasNext() )
8714 functions << fcnGeomOverlayFunc;
8727 functions << fcnGeomOverlayNearestFunc;
8740 fcnNodesToPoints, QStringLiteral(
"GeometryGroup" ) )
8742 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect_geometries" ), -1, fcnCollectGeometries, QStringLiteral(
"GeometryGroup" ) )
8747 fcnMakePointM, QStringLiteral(
"GeometryGroup" ) )
8753 fcnMakeTriangle, QStringLiteral(
"GeometryGroup" ) )
8758 fcnMakeCircle, QStringLiteral(
"GeometryGroup" ) )
8765 fcnMakeEllipse, QStringLiteral(
"GeometryGroup" ) )
8771 fcnMakeRegularPolygon, QStringLiteral(
"GeometryGroup" ) )
8775 fcnMakeSquare, QStringLiteral(
"GeometryGroup" ) )
8781 fcnMakeRectangleFrom3Points, QStringLiteral(
"GeometryGroup" ) )
8785#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
8791 }, fcnGeomMakeValid, QStringLiteral(
"GeometryGroup" ) );
8800 functions << xAtFunc;
8805 functions << yAtFunc;
8821 fcnDisjoint, QStringLiteral(
"GeometryGroup" ) )
8824 fcnIntersects, QStringLiteral(
"GeometryGroup" ) )
8827 fcnTouches, QStringLiteral(
"GeometryGroup" ) )
8830 fcnCrosses, QStringLiteral(
"GeometryGroup" ) )
8833 fcnContains, QStringLiteral(
"GeometryGroup" ) )
8836 fcnOverlaps, QStringLiteral(
"GeometryGroup" ) )
8839 fcnWithin, QStringLiteral(
"GeometryGroup" ) )
8843 fcnTranslate, QStringLiteral(
"GeometryGroup" ) )
8848 fcnRotate, QStringLiteral(
"GeometryGroup" ) )
8853 fcnScale, QStringLiteral(
"GeometryGroup" ) )
8864 fcnAffineTransform, QStringLiteral(
"GeometryGroup" ) )
8871 fcnBuffer, QStringLiteral(
"GeometryGroup" ) )
8873 fcnForceRHR, QStringLiteral(
"GeometryGroup" ) )
8875 fcnForcePolygonCW, QStringLiteral(
"GeometryGroup" ) )
8877 fcnForcePolygonCCW, QStringLiteral(
"GeometryGroup" ) )
8887 , fcnTaperedBuffer, QStringLiteral(
"GeometryGroup" ) )
8890 , fcnBufferByM, QStringLiteral(
"GeometryGroup" ) )
8896 fcnOffsetCurve, QStringLiteral(
"GeometryGroup" ) )
8902 fcnSingleSidedBuffer, QStringLiteral(
"GeometryGroup" ) )
8906 fcnExtend, QStringLiteral(
"GeometryGroup" ) )
8915 fcnInteriorRingN, QStringLiteral(
"GeometryGroup" ) )
8918 fcnGeometryN, QStringLiteral(
"GeometryGroup" ) )
8925 }, fcnSharedPaths, QStringLiteral(
"GeometryGroup" ) )
8939 }, fcnTriangularWave, QStringLiteral(
"GeometryGroup" ) )
8948 }, fcnTriangularWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
8955 }, fcnSquareWave, QStringLiteral(
"GeometryGroup" ) )
8964 }, fcnSquareWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
8971 }, fcnRoundWave, QStringLiteral(
"GeometryGroup" ) )
8980 }, fcnRoundWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
8989 }, fcnApplyDashPattern, QStringLiteral(
"GeometryGroup" ) )
8994 }, fcnDensifyByCount, QStringLiteral(
"GeometryGroup" ) )
8999 }, fcnDensifyByDistance, QStringLiteral(
"GeometryGroup" ) )
9011#
if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
9018 fcnOrientedBBox, QStringLiteral(
"GeometryGroup" ) )
9021 fcnMainAngle, QStringLiteral(
"GeometryGroup" ) )
9025 fcnMinimalCircle, QStringLiteral(
"GeometryGroup" ) )
9028 fcnDifference, QStringLiteral(
"GeometryGroup" ) )
9031 fcnDistance, QStringLiteral(
"GeometryGroup" ) )
9034 fcnHausdorffDistance, QStringLiteral(
"GeometryGroup" ) )
9037 fcnIntersection, QStringLiteral(
"GeometryGroup" ) )
9040 fcnSymDifference, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"symDifference" ) )
9043 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
9046 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
9049 fcnGeomToWKT, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"geomToWKT" ) )
9051 fcnGeomToWKB, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false )
9056 fcnTransformGeometry, QStringLiteral(
"GeometryGroup" ) )
9060 fcnExtrude, QStringLiteral(
"GeometryGroup" ), QString() )
9062 fcnGeomIsMultipart, QStringLiteral(
"GeometryGroup" ) )
9064 fcnZMax, QStringLiteral(
"GeometryGroup" ) )
9066 fcnZMin, QStringLiteral(
"GeometryGroup" ) )
9068 fcnMMax, QStringLiteral(
"GeometryGroup" ) )
9070 fcnMMin, QStringLiteral(
"GeometryGroup" ) )
9072 fcnSinuosity, QStringLiteral(
"GeometryGroup" ) )
9074 fcnStraightDistance2d, QStringLiteral(
"GeometryGroup" ) );
9080 fcnOrderParts, QStringLiteral(
"GeometryGroup" ), QString() );
9085 const QList< QgsExpressionNode *> argList = node->
args()->list();
9088 if ( !argNode->isStatic( parent, context ) )
9096 QString expString = argNode->
eval( parent, context ).toString();
9100 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9112 QString
expression = argNode->
eval( parent, context ).toString();
9114 e.prepare( context );
9120 functions << orderPartsFunc;
9125 fcnClosestPoint, QStringLiteral(
"GeometryGroup" ) )
9128 fcnShortestLine, QStringLiteral(
"GeometryGroup" ) )
9133 fcnLineInterpolatePointByM, QStringLiteral(
"GeometryGroup" ) )
9140 fcnLineLocateM, QStringLiteral(
"GeometryGroup" ) )
9153 functions << idFunc;
9157 functions << currentFeatureFunc;
9159 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" ) );
9161 functions << uuidFunc;
9168 fcnGetFeature, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"QgsExpressionUtils::getFeature" ) )
9171 fcnGetFeatureById, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false );
9176 functions << attributesFunc;
9180 functions << representAttributesFunc;
9188 functions << validateFeature;
9197 functions << validateAttribute;
9200 QStringLiteral(
"maptip" ),
9203 QStringLiteral(
"Record and Attributes" ),
9209 functions << maptipFunc;
9212 QStringLiteral(
"display_expression" ),
9214 fcnFeatureDisplayExpression,
9215 QStringLiteral(
"Record and Attributes" ),
9221 functions << displayFunc;
9224 QStringLiteral(
"is_selected" ),
9227 QStringLiteral(
"Record and Attributes" ),
9233 functions << isSelectedFunc;
9237 QStringLiteral(
"num_selected" ),
9240 QStringLiteral(
"Record and Attributes" ),
9248 QStringLiteral(
"sqlite_fetch_and_increment" ),
9256 fcnSqliteFetchAndIncrement,
9257 QStringLiteral(
"Record and Attributes" )
9275 parent->
setEvalErrorString( tr(
"If represent_value is called with 1 parameter, it must be an attribute." ) );
9285 parent->
setEvalErrorString( tr(
"represent_value must be called with exactly 1 or 2 parameters." ) );
9291 functions << representValueFunc;
9297 fcnGetLayerProperty, QStringLiteral(
"Map Layers" ) )
9302 fcnDecodeUri, QStringLiteral(
"Map Layers" ) )
9306 fcnMimeType, QStringLiteral(
"General" ) )
9323 QgsExpressionNode *argNode = node->args()->at( 0 );
9325 if ( !argNode->isStatic( parent, context ) )
9328 const QString varName = argNode->eval( parent, context ).toString();
9329 if ( varName == QLatin1String(
"feature" ) || varName == QLatin1String(
"id" ) || varName == QLatin1String(
"geometry" ) )
9332 const QgsExpressionContextScope *scope = context->activeScopeForVariable( varName );
9333 return scope ? scope->isStatic( varName ) : false;
9341 if ( node && node->
args()->
count() > 0 )
9346 if ( literal->value() == QLatin1String(
"geometry" ) || literal->value() == QLatin1String(
"feature" ) )
9363 QgsExpressionNode *argNode = node->args()->at( 0 );
9365 if ( argNode->isStatic( parent, context ) )
9367 QString expString = argNode->eval( parent, context ).toString();
9369 QgsExpression e( expString );
9371 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9378 functions << evalTemplateFunction;
9386 QgsExpressionNode *argNode = node->args()->at( 0 );
9388 if ( argNode->isStatic( parent, context ) )
9390 QString expString = argNode->eval( parent, context ).toString();
9392 QgsExpression e( expString );
9394 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9402 functions << evalFunc;
9408 const QList< QgsExpressionNode *> argList = node->
args()->list();
9411 if ( !argNode->
isStatic( parent, context ) )
9423 functions << attributeFunc;
9434 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array" ), -1, fcnArray, QStringLiteral(
"Arrays" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
9483 fcnMapPrefixKeys, QStringLiteral(
"Maps" ) )
9485 fcnMapToHtmlTable, QStringLiteral(
"Maps" ) )
9487 fcnMapToHtmlDefinitionList, QStringLiteral(
"Maps" ) )
9489 fcnToFormUrlEncode, QStringLiteral(
"Maps" ) )
9498 *sOwnedFunctions() << func;
9499 *sBuiltinFunctions() << func->name();
9500 sBuiltinFunctions()->append( func->aliases() );
9514 QMutexLocker locker( &sFunctionsMutex );
9515 sFunctions()->append( function );
9516 if ( transferOwnership )
9517 sOwnedFunctions()->append( function );
9532 QMutexLocker locker( &sFunctionsMutex );
9533 sFunctions()->removeAt( fnIdx );
9534 sFunctionIndexMap.clear();
9542 qDeleteAll( *sOwnedFunctions() );
9543 sOwnedFunctions()->clear();
9548 if ( sBuiltinFunctions()->isEmpty() )
9552 return *sBuiltinFunctions();
9559 QStringLiteral(
"Arrays" ) )
9570 if ( args->
count() < 2 )
9573 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9583 QVariantList result;
9585 if ( args->
count() < 2 )
9589 QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9592 std::unique_ptr< QgsExpressionContext > tempContext;
9595 tempContext = std::make_unique< QgsExpressionContext >();
9596 subContext = tempContext.get();
9603 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it, ++i )
9607 result << args->
at( 1 )->
eval( parent, subContext );
9632 if ( args->
count() < 2 )
9636 args->
at( 0 )->
prepare( parent, context );
9640 subContext = *context;
9647 args->
at( 1 )->
prepare( parent, &subContext );
9657 QStringLiteral(
"Arrays" ) )
9668 if ( args->
count() < 2 )
9671 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9681 QVariantList result;
9683 if ( args->
count() < 2 )
9687 const QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9690 std::unique_ptr< QgsExpressionContext > tempContext;
9693 tempContext = std::make_unique< QgsExpressionContext >();
9694 subContext = tempContext.get();
9701 if ( args->
count() >= 3 )
9703 const QVariant limitVar = args->
at( 2 )->
eval( parent, context );
9705 if ( QgsExpressionUtils::isIntSafe( limitVar ) )
9707 limit = limitVar.toInt();
9715 for (
const QVariant &value : array )
9718 if ( args->
at( 1 )->
eval( parent, subContext ).toBool() )
9722 if ( limit > 0 && limit == result.size() )
9749 if ( args->
count() < 2 )
9753 args->
at( 0 )->
prepare( parent, context );
9757 subContext = *context;
9763 args->
at( 1 )->
prepare( parent, &subContext );
9772 QStringLiteral(
"General" ) )
9783 if ( args->
count() < 3 )
9787 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9789 QVariant
name = args->
at( 0 )->
eval( parent, context );
9790 QVariant value = args->
at( 1 )->
eval( parent, context );
9793 appendTemporaryVariable( context,
name.toString(), value );
9794 if ( args->
at( 2 )->
isStatic( parent, context ) )
9796 popTemporaryVariable( context );
9807 if ( args->
count() < 3 )
9811 QVariant
name = args->
at( 0 )->
eval( parent, context );
9812 QVariant value = args->
at( 1 )->
eval( parent, context );
9815 std::unique_ptr< QgsExpressionContext > tempContext;
9816 if ( !updatedContext )
9818 tempContext = std::make_unique< QgsExpressionContext >();
9819 updatedContext = tempContext.get();
9822 appendTemporaryVariable( updatedContext,
name.toString(), value );
9823 result = args->
at( 2 )->
eval( parent, updatedContext );
9826 popTemporaryVariable( updatedContext );
9847 if ( args->
count() < 3 )
9852 QVariant value = args->
at( 1 )->
prepare( parent, context );
9855 std::unique_ptr< QgsExpressionContext > tempContext;
9856 if ( !updatedContext )
9858 tempContext = std::make_unique< QgsExpressionContext >();
9859 updatedContext = tempContext.get();
9862 appendTemporaryVariable( updatedContext,
name.toString(), value );
9863 args->
at( 2 )->
prepare( parent, updatedContext );
9866 popTemporaryVariable( updatedContext );
9871void QgsWithVariableExpressionFunction::popTemporaryVariable(
const QgsExpressionContext *context )
const
9877void 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...
Abstract base class for all geometries.
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
virtual QgsAbstractGeometry * boundary() const =0
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
virtual const QgsAbstractGeometry * simplifiedTypeRef() const
Returns a reference to the simplest lossless representation of this geometry, e.g.
bool isMeasure() const
Returns true if the geometry contains m values.
virtual QgsRectangle boundingBox() const
Returns the minimal bounding box for the geometry.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
part_iterator parts_end()
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
virtual double length() const
Returns the planar, 2-dimensional length of the geometry.
virtual QgsCoordinateSequence coordinateSequence() const =0
Retrieves the sequence of geometries, rings and nodes.
virtual int partCount() const =0
Returns count of parts contained in the geometry.
part_iterator parts_begin()
Returns STL-style iterator pointing to the first part of the geometry.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
static Qgis::Aggregate stringToAggregate(const QString &string, bool *ok=nullptr)
Converts a string to a aggregate type.
static QgsFieldFormatterRegistry * fieldFormatterRegistry()
Gets the registry of available field formatters.
Handles the array_filter(array, expression) expression function.
QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Returns result of evaluating the function.
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Evaluates the function, first evaluating all required arguments before passing them to the function's...
QgsArrayFilterExpressionFunction()
Handles the array loopingarray_Foreach(array, expression) expression function.
QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Returns result of evaluating the function.
QgsArrayForeachExpressionFunction()
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Evaluates the function, first evaluating all required arguments before passing them to the function's...
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
Abstract base class for color ramps.
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QString toProj() const
Returns a Proj string representation of this CRS.
QString ellipsoidAcronym() const
Returns the ellipsoid acronym for the ellipsoid used by the CRS.
Qgis::DistanceUnit mapUnits
Contains information about the context in which a coordinate transform is executed.
Custom exception class for Coordinate Reference System related exceptions.
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
bool isEmpty() const override
Returns true if the geometry is empty.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
double area() const override
Returns the planar, 2-dimensional area of the geometry.
double roundness() const
Returns the roundness of the curve polygon.
int ringCount(int part=0) const override
Returns the number of rings of which this geometry is built.
Abstract base class for curved geometry type.
double sinuosity() const
Returns the curve sinuosity, which is the ratio of the curve length() to curve straightDistance2d().
QgsCurve * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
virtual QgsCurve * curveSubstring(double startDistance, double endDistance) const =0
Returns a new curve representing a substring of this curve.
virtual bool isClosed() const
Returns true if the curve is closed.
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
double straightDistance2d() const
Returns the straight distance of the curve, i.e.
virtual QgsCurve * reversed() const =0
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
double measureArea(const QgsGeometry &geometry) const
Measures the area of a geometry.
double convertLengthMeasurement(double length, Qgis::DistanceUnit toUnits) const
Takes a length measurement calculated by this QgsDistanceArea object and converts it to a different d...
double measurePerimeter(const QgsGeometry &geometry) const
Measures the perimeter of a polygon geometry.
double measureLength(const QgsGeometry &geometry) const
Measures the length of a geometry.
double bearing(const QgsPointXY &p1, const QgsPointXY &p2) const
Computes the bearing (in radians) between two points.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
double convertAreaMeasurement(double area, Qgis::AreaUnit toUnits) const
Takes an area measurement calculated by this QgsDistanceArea object and converts it to a different ar...
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
bool isStatic(const QString &name) const
Tests whether the variable with the specified name is static and can be cached.
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
static void registerContextFunctions()
Registers all known core functions provided by QgsExpressionContextScope objects.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
void setCachedValue(const QString &key, const QVariant &value) const
Sets a value to cache within the expression context.
QgsGeometry geometry() const
Convenience function for retrieving the geometry for the context, if set.
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
QgsExpressionContextScope * activeScopeForVariable(const QString &name)
Returns the currently active scope from the context for a specified variable name.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly by the expression to check if evaluation sh...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
bool hasGeometry() const
Returns true if the context has a geometry associated with it.
bool hasCachedValue(const QString &key) const
Returns true if the expression context contains a cached value with a matching key.
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
QVariant cachedValue(const QString &key) const
Returns the matching cached value, if set.
bool hasFeature() const
Returns true if the context has a feature associated with it.
QgsFields fields() const
Convenience function for retrieving the fields for the context, if set.
Represents a single parameter passed to a function.
A abstract base class for defining QgsExpression functions.
QList< QgsExpressionFunction::Parameter > ParameterList
List of parameters, used for function definition.
bool operator==(const QgsExpressionFunction &other) const
virtual bool isDeprecated() const
Returns true if the function is deprecated and should not be presented as a valid option to users in ...
virtual bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
Will be called during prepare to determine if the function is static.
virtual QStringList aliases() const
Returns a list of possible aliases for the function.
bool lazyEval() const
true if this function should use lazy evaluation.
static bool allParamsStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context)
This will return true if all the params for the provided function node are static within the constrai...
QString name() const
The name of the function.
virtual QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
Evaluates the function, first evaluating all required arguments before passing them to the function's...
virtual QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)=0
Returns result of evaluating the function.
virtual QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const
Returns a set of field names which are required for this function.
virtual bool handlesNull() const
Returns true if the function handles NULL values in arguments by itself, and the default NULL value h...
virtual bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
This will be called during the prepare step() of an expression if it is not static.
virtual bool usesGeometry(const QgsExpressionNodeFunction *node) const
Does this function use a geometry object.
An expression node which takes it value from a feature's field.
QString name() const
The name of the column.
An expression node for expression functions.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
An expression node for literal values.
A list of expression nodes.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
QgsExpressionNode * at(int i)
Gets the node at position i in the list.
int count() const
Returns the number of nodes in the list.
Abstract base class for all nodes that can appear in an expression.
virtual QString dump() const =0
Dump this node into a serialized (part) of an expression.
QVariant eval(QgsExpression *parent, const QgsExpressionContext *context)
Evaluate this node with the given context and parent.
virtual bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const =0
Returns true if this node can be evaluated for a static value.
bool prepare(QgsExpression *parent, const QgsExpressionContext *context)
Prepare this node for evaluation.
virtual QSet< QString > referencedColumns() const =0
Abstract virtual method which returns a list of columns required to evaluate this node.
virtual QSet< QString > referencedVariables() const =0
Returns a set of all variables which are used in this expression.
A set of expression-related functions.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
static const QList< QgsExpressionFunction * > & Functions()
QString expression() const
Returns the original, unmodified expression string.
static void cleanRegisteredFunctions()
Deletes all registered functions whose ownership have been transferred to the expression engine.
Qgis::DistanceUnit distanceUnits() const
Returns the desired distance units for calculations involving geomCalculator(), e....
static bool registerFunction(QgsExpressionFunction *function, bool transferOwnership=false)
Registers a function to the expression engine.
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
static const QStringList & BuiltinFunctions()
static QString replaceExpressionText(const QString &action, const QgsExpressionContext *context, const QgsDistanceArea *distanceArea=nullptr)
This function replaces each expression between [% and %] in the string with the result of its evaluat...
static PRIVATE QString helpText(QString name)
Returns the help text for a specified function.
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value, QMetaType::Type fieldType=QMetaType::Type::UnknownType)
Create an expression allowing to evaluate if a field is equal to a value.
static bool unregisterFunction(const QString &name)
Unregisters a function from the expression engine.
Qgis::AreaUnit areaUnits() const
Returns the desired areal units for calculations involving geomCalculator(), e.g.,...
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions)
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QVariant evaluate()
Evaluate the feature and return the result.
QgsDistanceArea * geomCalculator()
Returns calculator used for distance and area calculations (used by $length, $area and $perimeter fun...
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
Represents a list of OrderByClauses, with the most important first and the least important last.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsFeatureRequest & setRequestMayBeNested(bool requestMayBeNested)
In case this request may be run nested within another already running iteration on the same connectio...
QgsFeatureRequest & setTimeout(int timeout)
Sets the timeout (in milliseconds) for the maximum time we should wait during feature requests before...
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
void setFeedback(QgsFeedback *feedback)
Attach a feedback object that can be queried regularly by the iterator to check if it should be cance...
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Sets the feature ID that should be fetched.
QgsVectorLayer * materialize(const QgsFeatureRequest &request, QgsFeedback *feedback=nullptr)
Materializes a request (query) made against this feature source, by running it over the source and re...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
bool isValid() const
Returns the validity of this feature.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
ConstraintStrength
Strength of constraints.
@ ConstraintStrengthNotSet
Constraint is not set.
@ ConstraintStrengthSoft
User is warned if constraint is violated but feature can still be accepted.
@ ConstraintStrengthHard
Constraint must be honored before feature can be accepted.
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Container of fields for a vector layer.
Q_INVOKABLE int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
int size() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
virtual bool removeGeometry(int nr)
Removes a geometry from the collection.
QgsGeometryCollection * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
int partCount() const override
Returns count of parts contained in the geometry.
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
static QVector< QgsLineString * > extractLineStrings(const QgsAbstractGeometry *geom)
Returns list of linestrings extracted from the passed geometry.
A geometry is the spatial representation of a feature.
double hausdorffDistanceDensify(const QgsGeometry &geom, double densifyFraction) const
Returns the Hausdorff distance between this geometry and geom.
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Returns a copy of the geometry which has been densified by adding the specified number of extra nodes...
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
double lineLocatePoint(const QgsGeometry &point) const
Returns a distance representing the location along this linestring of the closest point on this lines...
QgsGeometry difference(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing the points making up this geometry that do not make up other.
double length() const
Returns the planar, 2-dimensional length of geometry.
QgsGeometry offsetCurve(double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
QgsGeometry poleOfInaccessibility(double precision, double *distanceToBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
QgsGeometry squareWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs square waves along the boundary of the geometry, with the specified wavelength and amplitu...
QgsGeometry triangularWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs triangular waves along the boundary of the geometry, with the specified wavelength and amp...
bool vertexIdFromVertexNr(int number, QgsVertexId &id) const
Calculates the vertex ID from a vertex number.
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
bool touches(const QgsGeometry &geometry) const
Returns true if the geometry touches another geometry.
QgsGeometry applyDashPattern(const QVector< double > &pattern, Qgis::DashPatternLineEndingRule startRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternLineEndingRule endRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternSizeAdjustment adjustment=Qgis::DashPatternSizeAdjustment::ScaleBothDashAndGap, double patternOffset=0) const
Applies a dash pattern to a geometry, returning a MultiLineString geometry which is the input geometr...
QgsGeometry roundWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs rounded (sine-like) waves along the boundary of the geometry, with the specified wavelengt...
QgsGeometry nearestPoint(const QgsGeometry &other) const
Returns the nearest (closest) point on this geometry to another geometry.
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
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.
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 ...
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.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
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, exception handling*.
std::unique_ptr< QgsAbstractGeometry > maximumInscribedCircle(double tolerance, QString *errorMsg=nullptr) const
Returns the maximum inscribed circle.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
Represents a color stop within a QgsGradientColorRamp color ramp.
A representation of the interval between two datetime values.
bool isValid() const
Returns true if the interval is valid.
double days() const
Returns the interval duration in days.
double weeks() const
Returns the interval duration in weeks.
double months() const
Returns the interval duration in months (based on a 30 day month).
double seconds() const
Returns the interval duration in seconds.
double years() const
Returns the interval duration in years (based on an average year length)
double hours() const
Returns the interval duration in hours.
double minutes() const
Returns the interval duration in minutes.
Line string geometry type, with support for z-dimension and m-values.
bool lineLocatePointByM(double m, double &x, double &y, double &z, double &distanceFromStart, bool use3DDistance=true) const
Attempts to locate a point on the linestring by m value.
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
QString dataUrl() const
Returns the DataUrl of the layer used by QGIS Server in GetCapabilities request.
QString attributionUrl() const
Returns the attribution URL of the layer used by QGIS Server in GetCapabilities request.
Base class for all map layer types.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QString source() const
Returns the source for the layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
QgsCoordinateReferenceSystem crs
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
QgsLayerMetadata metadata
QString publicSource(bool hidePassword=false) const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
virtual bool isEditable() const
Returns true if the layer can be edited.
double minimumScale() const
Returns the minimum map scale (i.e.
virtual Q_INVOKABLE QgsDataProvider * dataProvider()
Returns the layer's data provider, it may be nullptr.
double maximumScale() const
Returns the maximum map scale (i.e.
Implementation of GeometrySimplifier using the "MapToPixel" algorithm.
@ SimplifyGeometry
The geometries can be simplified using the current map2pixel context state.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Multi line string geometry collection.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
Multi point geometry collection.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
Custom exception class which is raised when an operation is not supported.
static QgsGeometry geometryFromGML(const QString &xmlString, const QgsOgcUtils::Context &context=QgsOgcUtils::Context())
Static method that creates geometry from GML.
A class to represent a 2D point.
bool isEmpty() const
Returns true if the geometry is empty.
Point geometry type, with support for z-dimension and m-values.
double inclination(const QgsPoint &other) const
Calculates Cartesian inclination between this point and other one (starting from zenith = 0 to nadir ...
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override
Checks validity of the geometry, and returns true if the geometry is valid.
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which corresponds to this point projected by a specified distance with specified ...
QgsRelationManager * relationManager
static QgsProject * instance()
Returns the QgsProject singleton instance.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
Quadrilateral geometry type.
static QgsQuadrilateral squareFromDiagonal(const QgsPoint &p1, const QgsPoint &p2)
Construct a QgsQuadrilateral as a square from a diagonal.
QgsPolygon * toPolygon(bool force2D=false) const
Returns the quadrilateral as a new polygon.
static QgsQuadrilateral rectangleFrom3Points(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &p3, ConstructionOption mode)
Construct a QgsQuadrilateral as a Rectangle from 3 points.
ConstructionOption
A quadrilateral can be constructed from 3 points where the second distance can be determined by the t...
@ Distance
Second distance is equal to the distance between 2nd and 3rd point.
@ Projected
Second distance is equal to the distance of the perpendicular projection of the 3rd point on the segm...
The Field class represents a Raster Attribute Table field, including its name, usage and type.
The RasterBandStats struct is a container for statistics about a single raster band.
double mean
The mean cell value for the band. NO_DATA values are excluded.
double stdDev
The standard deviation of the cell values.
double minimumValue
The minimum cell value in the raster band.
double sum
The sum of all cells in the band. NO_DATA values are excluded.
double maximumValue
The maximum cell value in the raster band.
double range
The range is the distance between min & max.
A rectangle specified with double values.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double width() const
Returns the width of the rectangle.
double xMaximum() const
Returns the x maximum value (right side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
QgsPointXY center() const
Returns the center point of the rectangle.
void grow(double delta)
Grows the rectangle in place by the specified amount.
double height() const
Returns the height of the rectangle.
Regular Polygon geometry type.
ConstructionOption
A regular polygon can be constructed inscribed in a circle or circumscribed about a circle.
@ CircumscribedCircle
Circumscribed about a circle (the radius is the distance from the center to the midpoints of the side...
@ InscribedCircle
Inscribed in a circle (the radius is the distance between the center and vertices)
QgsPolygon * toPolygon() const
Returns as a polygon.
QList< QgsRelation > relationsByName(const QString &name) const
Returns a list of relations with matching names.
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id.
Represents a relationship between two vector layers.
QgsVectorLayer * referencedLayer
QgsVectorLayer * referencingLayer
QString getRelatedFeaturesFilter(const QgsFeature &feature) const
Returns a filter expression which returns all the features on the referencing (child) layer which hav...
A spatial index for QgsFeature objects.
@ FlagStoreFeatureGeometries
Indicates that the spatial index should also store feature geometries. This requires more memory,...
QList< QgsFeatureId > nearestNeighbor(const QgsPointXY &point, int neighbors=1, double maxDistance=0) const
Returns nearest neighbors to a point.
QList< QgsFeatureId > intersects(const QgsRectangle &rectangle) const
Returns a list of features with a bounding box which intersects the specified rectangle.
static QString quotedIdentifier(const QString &identifier)
Returns a properly quoted version of identifier.
static QString quotedValue(const QVariant &value)
Returns a properly quoted and escaped version of value for use in SQL strings.
c++ helper class for defining QgsExpression functions.
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
void setIsStaticFunction(const std::function< bool(const QgsExpressionNodeFunction *, QgsExpression *, const QgsExpressionContext *) > &isStatic)
Set a function that will be called in the prepare step to determine if the function is static or not.
QStringList aliases() const override
Returns a list of possible aliases for the function.
void setPrepareFunction(const std::function< bool(const QgsExpressionNodeFunction *, QgsExpression *, const QgsExpressionContext *)> &prepareFunc)
Set a function that will be called in the prepare step to determine if the function is static or not.
void setUsesGeometryFunction(const std::function< bool(const QgsExpressionNodeFunction *node)> &usesGeometry)
Set a function that will be called when determining if the function requires feature geometry or not.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
void setIsStatic(bool isStatic)
Tag this function as either static or not static.
QgsStaticExpressionFunction(const QString &fnname, int params, FcnEval fcn, const QString &group, const QString &helpText=QString(), bool usesGeometry=false, const QSet< QString > &referencedColumns=QSet< QString >(), bool lazyEval=false, const QStringList &aliases=QStringList(), bool handlesNull=false)
Static function for evaluation against a QgsExpressionContext, using an unnamed list of parameter val...
QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const override
Returns a set of field names which are required for this function.
bool usesGeometry(const QgsExpressionNodeFunction *node) const override
Does this function use a geometry object.
Utility functions for working with strings.
static int hammingDistance(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the Hamming distance between two strings.
static QString soundex(const QString &string)
Returns the Soundex representation of a string.
static int levenshteinDistance(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the Levenshtein edit distance between two strings.
static QString longestCommonSubstring(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the longest common substring between two strings.
static QString wordWrap(const QString &string, int length, bool useMaxLineLength=true, const QString &customDelimiter=QString())
Automatically wraps a string by inserting new line characters at appropriate locations in the string.
const QgsColorRamp * colorRampRef(const QString &name) const
Returns a const pointer to a symbol (doesn't create new instance)
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Contains utility functions for working with symbols and symbol layers.
static QColor decodeColor(const QString &str)
static QString encodeColor(const QColor &color)
static bool runOnMainThread(const Func &func, QgsFeedback *feedback=nullptr)
Guarantees that func is executed on the main thread.
This class allows including a set of layers in a database-side transaction, provided the layer data p...
virtual bool executeSql(const QString &sql, QString &error, bool isDirty=false, const QString &name=QString())=0
Execute the sql string.
static Q_INVOKABLE QString encodeUnit(Qgis::DistanceUnit unit)
Encodes a distance unit to a string.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
virtual QgsTransaction * transaction() const
Returns the transaction this data provider is included in, if any.
static bool validateAttribute(const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors, QgsFieldConstraints::ConstraintStrength strength=QgsFieldConstraints::ConstraintStrengthNotSet, QgsFieldConstraints::ConstraintOrigin origin=QgsFieldConstraints::ConstraintOriginNotSet)
Tests a feature attribute value to check whether it passes all constraints which are present on the c...
Represents a vector layer which manages a vector based data sets.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QVariant aggregate(Qgis::Aggregate aggregate, const QString &fieldOrExpression, const QgsAggregateCalculator::AggregateParameters ¶meters=QgsAggregateCalculator::AggregateParameters(), QgsExpressionContext *context=nullptr, bool *ok=nullptr, QgsFeatureIds *fids=nullptr, QgsFeedback *feedback=nullptr, QString *error=nullptr) const
Calculates an aggregated value from the layer's features.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QString displayExpression
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
QgsEditorWidgetSetup editorWidgetSetup(int index) const
Returns the editor widget setup for the field at the specified index.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
Q_INVOKABLE QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.
Handles the with_variable(name, value, node) expression function.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
QgsWithVariableExpressionFunction()
QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Evaluates the function, first evaluating all required arguments before passing them to the function's...
QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node) override
Returns result of evaluating the function.
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
static QString geometryDisplayString(Qgis::GeometryType type)
Returns a display string for a geometry type.
static bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
Unique pointer for sqlite3 databases, which automatically closes the database when the pointer goes o...
sqlite3_statement_unique_ptr prepare(const QString &sql, int &resultCode) const
Prepares a sql statement, returning the result.
QString errorMessage() const
Returns the most recent error message encountered by the database.
int open_v2(const QString &path, int flags, const char *zVfs)
Opens the database at the specified file path.
int exec(const QString &sql, QString &errorMessage) const
Executes the sql command in the database.
Unique pointer for sqlite3 prepared statements, which automatically finalizes the statement when the ...
int step()
Steps to the next record in the statement, returning the sqlite3 result code.
qlonglong columnAsInt64(int column) const
Gets column value from the current statement row as a long long integer (64 bits).
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
CORE_EXPORT QString build(const QVariantMap &map)
Build a hstore-formatted string from a QVariantMap.
CORE_EXPORT QVariantMap parse(const QString &string)
Returns a QVariantMap object containing the key and values from a hstore-formatted string.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
uint qHash(const QVariant &variant)
Hash for QVariant.
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
#define ENSURE_GEOM_TYPE(f, g, geomtype)
QVariant fcnRampColor(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< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
QLineF segment(int index, QRectF rect, double radius)
A bundle of parameters controlling aggregate calculation.
QString filter
Optional filter for calculating aggregate over a subset of features, or an empty string to use all fe...
QString delimiter
Delimiter to use for joining values with the StringConcatenate aggregate.
QgsFeatureRequest::OrderBy orderBy
Optional order by clauses.
Single variable definition for use within a QgsExpressionContextScope.
The Context struct stores the current layer and coordinate transform context.
const QgsMapLayer * layer
QgsCoordinateTransformContext transformContext
Utility class for identifying a unique vertex within a geometry.