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 );
590 QVariant result( QVariant::Double );
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 );
614 QVariant result( QVariant::Double );
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() ) )
727 const QSet<QString> refVars = filterExp.referencedVariables() + subExp.referencedVariables();
728 for (
const QString &varName : refVars )
731 if ( scope && !scope->
isStatic( varName ) )
741 cacheKey = QStringLiteral(
"aggfcn:%1:%2:%3:%4:%5%6:%7" ).arg( vl->id(), QString::number( aggregate ), subExpression, parameters.
filter,
742 QString::number( context->
feature().
id() ), QString::number(
qHash( context->
feature() ) ), orderBy );
746 cacheKey = QStringLiteral(
"aggfcn:%1:%2:%3:%4:%5" ).arg( vl->id(), QString::number( aggregate ), subExpression, parameters.
filter, orderBy );
757 subContext.appendScope( subScope );
758 result = vl->aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &aggregateError );
770 result = vl->aggregate( aggregate, subExpression, parameters,
nullptr, &ok,
nullptr,
nullptr, &aggregateError );
774 if ( !aggregateError.isEmpty() )
775 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, aggregateError ) );
777 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
788 parent->
setEvalErrorString( QObject::tr(
"Cannot use relation aggregate function in this context" ) );
796 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
800 parent->
setEvalErrorString( QObject::tr(
"Cannot use relation aggregate function in this context" ) );
809 QVariant value = node->
eval( parent, context );
811 QString relationId = value.toString();
818 if ( relations.isEmpty() || relations.at( 0 ).referencedLayer() != vl )
820 parent->
setEvalErrorString( QObject::tr(
"Cannot find relation with id '%1'" ).arg( relationId ) );
825 relation = relations.at( 0 );
832 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
834 value = node->
eval( parent, context );
840 parent->
setEvalErrorString( QObject::tr(
"No such aggregate '%1'" ).arg( value.toString() ) );
845 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
847 QString subExpression = node->
dump();
851 if ( values.count() > 3 )
853 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
855 value = node->
eval( parent, context );
862 if ( values.count() > 4 )
864 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
867 if ( !nl || nl->value().isValid() )
869 orderBy = node->
dump();
880 QString cacheKey = QStringLiteral(
"relagg:%1:%2:%3:%4:%5" ).arg( vl->id(),
881 QString::number(
static_cast< int >( aggregate ) ),
894 result = childLayer->
aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &error );
898 if ( !error.isEmpty() )
899 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, error ) );
901 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
915 parent->
setEvalErrorString( QObject::tr(
"Cannot use aggregate function in this context" ) );
923 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
927 parent->
setEvalErrorString( QObject::tr(
"Cannot use aggregate function in this context" ) );
936 QString subExpression = node->
dump();
940 if ( values.count() > 1 )
942 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
945 if ( !nl || nl->value().isValid() )
946 groupBy = node->
dump();
950 if ( values.count() > 2 )
952 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
955 if ( !nl || nl->value().isValid() )
961 if ( orderByPos >= 0 && values.count() > orderByPos )
963 node = QgsExpressionUtils::getNode( values.at( orderByPos ), parent );
966 if ( !nl || nl->value().isValid() )
968 orderBy = node->
dump();
976 if ( !groupBy.isEmpty() )
979 QVariant groupByValue = groupByExp.evaluate( context );
980 QString groupByClause = QStringLiteral(
"%1 %2 %3" ).arg( groupBy,
983 if ( !parameters.
filter.isEmpty() )
984 parameters.
filter = QStringLiteral(
"(%1) AND (%2)" ).arg( parameters.
filter, groupByClause );
986 parameters.
filter = groupByClause;
992 bool isStatic =
true;
993 const QSet<QString> refVars = filterExp.referencedVariables() + subExp.referencedVariables();
994 for (
const QString &varName : refVars )
997 if ( scope && !scope->
isStatic( varName ) )
1007 cacheKey = QStringLiteral(
"agg:%1:%2:%3:%4:%5%6:%7" ).arg( vl->id(), QString::number( aggregate ), subExpression, parameters.
filter,
1008 QString::number( context->
feature().
id() ), QString::number(
qHash( context->
feature() ) ), orderBy );
1012 cacheKey = QStringLiteral(
"agg:%1:%2:%3:%4:%5" ).arg( vl->id(), QString::number( aggregate ), subExpression, parameters.
filter, orderBy );
1024 subContext.appendScope( subScope );
1026 result = vl->aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &error );
1030 if ( !error.isEmpty() )
1031 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, error ) );
1033 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
1138 if ( values.count() > 3 )
1140 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
1142 QVariant value = node->
eval( parent, context );
1144 parameters.
delimiter = value.toString();
1155 if ( values.count() > 3 )
1157 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
1159 QVariant value = node->
eval( parent, context );
1161 parameters.
delimiter = value.toString();
1177 QVariant scale = context->
variable( QStringLiteral(
"map_scale" ) );
1182 const double v = scale.toDouble( &ok );
1190 double minValue = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1191 double testValue = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1192 double maxValue = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1195 if ( testValue <= minValue )
1197 return QVariant( minValue );
1199 else if ( testValue >= maxValue )
1201 return QVariant( maxValue );
1205 return QVariant( testValue );
1211 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1212 return QVariant( std::floor( x ) );
1217 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1218 return QVariant( std::ceil( x ) );
1223 return QVariant( QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) );
1227 return QVariant( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) );
1231 return QVariant( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ) );
1236 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1237 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1238 if ( format.isEmpty() && !language.isEmpty() )
1240 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to DateTime when the language is specified" ) );
1241 return QVariant( QDateTime() );
1244 if ( format.isEmpty() && language.isEmpty() )
1245 return QVariant( QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent ) );
1247 QString datetimestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1248 QLocale locale = QLocale();
1249 if ( !language.isEmpty() )
1251 locale = QLocale( language );
1254 QDateTime datetime = locale.toDateTime( datetimestring, format );
1255 if ( !datetime.isValid() )
1257 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to DateTime" ).arg( datetimestring ) );
1258 datetime = QDateTime();
1260 return QVariant( datetime );
1265 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1266 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1267 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1269 const QDate date( year, month, day );
1270 if ( !date.isValid() )
1272 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1275 return QVariant( date );
1280 const int hours = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1281 const int minutes = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1282 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1284 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1285 if ( !time.isValid() )
1287 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1290 return QVariant( time );
1295 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1296 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1297 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1298 const int hours = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
1299 const int minutes = QgsExpressionUtils::getIntValue( values.at( 4 ), parent );
1300 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1302 const QDate date( year, month, day );
1303 if ( !date.isValid() )
1305 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1308 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1309 if ( !time.isValid() )
1311 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1314 return QVariant( QDateTime( date, time ) );
1319 const double years = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1320 const double months = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1321 const double weeks = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1322 const double days = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
1323 const double hours = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
1324 const double minutes = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1325 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
1327 return QVariant::fromValue(
QgsInterval( years, months, weeks, days, hours, minutes, seconds ) );
1332 for (
const QVariant &value : values )
1343 const QVariant val1 = values.at( 0 );
1344 const QVariant val2 = values.at( 1 );
1354 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1355 return QVariant(
str.toLower() );
1359 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1360 return QVariant(
str.toUpper() );
1364 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1365 QStringList elems =
str.split(
' ' );
1366 for (
int i = 0; i < elems.size(); i++ )
1368 if ( elems[i].size() > 1 )
1369 elems[i] = elems[i].at( 0 ).toUpper() + elems[i].mid( 1 ).toLower();
1371 return QVariant( elems.join( QLatin1Char(
' ' ) ) );
1376 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1377 return QVariant(
str.trimmed() );
1382 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1384 const QString characters = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1386 const QRegularExpression re( QStringLiteral(
"^([%1]*)" ).arg( QRegularExpression::escape( characters ) ) );
1387 str.replace( re, QString() );
1388 return QVariant(
str );
1393 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1395 const QString characters = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1397 const QRegularExpression re( QStringLiteral(
"([%1]*)$" ).arg( QRegularExpression::escape( characters ) ) );
1398 str.replace( re, QString() );
1399 return QVariant(
str );
1404 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1405 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1411 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1412 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1418 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1419 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1426 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1432 QChar character = QChar( QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent ) );
1433 return QVariant( QString( character ) );
1438 QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1440 if ( value.isEmpty() )
1445 int res = value.at( 0 ).unicode();
1446 return QVariant( res );
1451 if ( values.length() == 2 || values.length() == 3 )
1453 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1454 qlonglong wrap = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1456 QString customdelimiter = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1467 if ( values.at( 0 ).userType() == QMetaType::type(
"QgsGeometry" ) )
1470 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
1471 if ( geom.
type() != Qgis::GeometryType::Line )
1474 return QVariant( geom.
length() );
1478 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1479 return QVariant(
str.length() );
1484 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
1486 if ( geom.
type() != Qgis::GeometryType::Line )
1489 double totalLength = 0;
1492 if (
const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( *it ) )
1494 totalLength += line->length3D();
1498 std::unique_ptr< QgsLineString > segmentized( qgsgeometry_cast< const QgsCurve * >( *it )->curveToLine() );
1499 totalLength += segmentized->length3D();
1508 if ( values.count() == 2 && values.at( 1 ).type() == QVariant::Map )
1510 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1511 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
1512 QVector< QPair< QString, QString > > mapItems;
1514 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
1516 mapItems.append( qMakePair( it.key(), it.value().toString() ) );
1520 std::sort( mapItems.begin(),
1522 [](
const QPair< QString, QString > &pair1,
1523 const QPair< QString, QString > &pair2 )
1525 return ( pair1.first.length() > pair2.first.length() );
1528 for (
auto it = mapItems.constBegin(); it != mapItems.constEnd(); ++it )
1530 str =
str.replace( it->first, it->second );
1533 return QVariant(
str );
1535 else if ( values.count() == 3 )
1537 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1538 QVariantList before;
1540 bool isSingleReplacement =
false;
1542 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).type() != QVariant::StringList )
1544 before = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1548 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
1551 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
1553 after = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1554 isSingleReplacement =
true;
1558 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
1561 if ( !isSingleReplacement && before.length() != after.length() )
1563 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
1567 for (
int i = 0; i < before.length(); i++ )
1569 str =
str.replace( before.at( i ).toString(), after.at( isSingleReplacement ? 0 : i ).toString() );
1572 return QVariant(
str );
1576 parent->
setEvalErrorString( QObject::tr(
"Function replace requires 2 or 3 arguments" ) );
1583 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1584 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1585 QString after = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1587 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1588 if ( !re.isValid() )
1590 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1593 return QVariant(
str.replace( re, after ) );
1598 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1599 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), 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.indexOf( re ) + 1 ) );
1612 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1613 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1614 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1616 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1617 if ( !re.isValid() )
1619 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1623 QRegularExpressionMatch matches = re.match(
str );
1624 if ( matches.hasMatch() )
1627 QStringList list = matches.capturedTexts();
1630 for ( QStringList::const_iterator it = ++list.constBegin(); it != list.constEnd(); ++it )
1632 array += ( !( *it ).isEmpty() ) ? *it : empty;
1635 return QVariant( array );
1645 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1646 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1648 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1649 if ( !re.isValid() )
1651 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1656 QRegularExpressionMatch match = re.match(
str );
1657 if ( match.hasMatch() )
1660 if ( match.lastCapturedIndex() > 0 )
1663 return QVariant( match.captured( 1 ) );
1668 return QVariant( match.captured( 0 ) );
1673 return QVariant(
"" );
1679 QString uuid = QUuid::createUuid().toString();
1680 if ( values.at( 0 ).toString().compare( QStringLiteral(
"WithoutBraces" ), Qt::CaseInsensitive ) == 0 )
1681 uuid = QUuid::createUuid().toString( QUuid::StringFormat::WithoutBraces );
1682 else if ( values.at( 0 ).toString().compare( QStringLiteral(
"Id128" ), Qt::CaseInsensitive ) == 0 )
1683 uuid = QUuid::createUuid().toString( QUuid::StringFormat::Id128 );
1689 if ( !values.at( 0 ).isValid() || !values.at( 1 ).isValid() )
1692 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1693 int from = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1696 if ( values.at( 2 ).isValid() )
1697 len = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
1703 from =
str.size() + from;
1709 else if ( from > 0 )
1717 len =
str.size() + len - from;
1724 return QVariant(
str.mid( from, len ) );
1730 return QVariant(
static_cast< int >( f.
id() ) );
1735 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1736 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
1737 bool foundLayer =
false;
1738 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, geom](
QgsMapLayer * mapLayer )
1740 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer * >( mapLayer );
1741 if ( !layer || !layer->dataProvider() )
1743 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1747 if ( bandNb < 1 || bandNb > layer->bandCount() )
1749 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster band number." ) );
1753 if ( geom.
isNull() || geom.
type() != Qgis::GeometryType::Point )
1755 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid point geometry." ) );
1762 QgsMultiPointXY multiPoint = geom.asMultiPoint();
1763 if ( multiPoint.count() == 1 )
1765 point = multiPoint[0];
1774 double value = layer->dataProvider()->sample( point, bandNb );
1775 return std::isnan( value ) ? QVariant() : value;
1781 parent->
setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1792 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1793 const double value = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1795 bool foundLayer =
false;
1796 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, value](
QgsMapLayer * mapLayer )-> QVariant
1798 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer *>( mapLayer );
1799 if ( !layer || !layer->dataProvider() )
1801 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1805 if ( bandNb < 1 || bandNb > layer->bandCount() )
1807 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster band number." ) );
1811 if ( std::isnan( value ) )
1813 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster value." ) );
1817 if ( ! layer->dataProvider()->attributeTable( bandNb ) )
1822 const QVariantList data = layer->dataProvider()->attributeTable( bandNb )->row( value );
1823 if ( data.isEmpty() )
1829 const QList<QgsRasterAttributeTable::Field> fields { layer->dataProvider()->attributeTable( bandNb )->fields() };
1830 for (
int idx = 0; idx < static_cast<int>( fields.count( ) ) && idx < static_cast<int>( data.count() ); ++idx )
1837 result.insert( fields.at( idx ).name, data.at( idx ) );
1845 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1866 if ( values.size() == 1 )
1868 attr = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1871 else if ( values.size() == 2 )
1873 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
1874 attr = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1878 parent->
setEvalErrorString( QObject::tr(
"Function `attribute` requires one or two parameters. %n given.",
nullptr, values.length() ) );
1887 QString table { R
"html(
1893 <tr><td>%2</td></tr>
1897 if ( values.size() == 1 )
1899 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1903 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_table` requires one parameter. %n given.",
nullptr, values.length() ) );
1907 if ( dict.isEmpty() )
1912 QStringList headers;
1915 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
1917 headers.push_back( it.key().toHtmlEscaped() );
1918 cells.push_back( it.value().toString( ).toHtmlEscaped() );
1921 return table.arg( headers.join( QLatin1String(
"</th><th>" ) ), cells.join( QLatin1String(
"</td><td>" ) ) );
1926 QString table { R
"html(
1931 if ( values.size() == 1 )
1933 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1937 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_dl` requires one parameter. %n given.",
nullptr, values.length() ) );
1941 if ( dict.isEmpty() )
1948 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
1950 rows.append( QStringLiteral(
"<dt>%1</dt><dd>%2</dd>" ).arg( it.key().toHtmlEscaped(), it.value().toString().toHtmlEscaped() ) );
1953 return table.arg( rows );
1961 layer = context->
variable( QStringLiteral(
"layer" ) );
1966 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
1968 layer = node->
eval( parent, context );
1979 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
1983 const QString strength = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).toLower();
1984 if ( strength == QLatin1String(
"hard" ) )
1988 else if ( strength == QLatin1String(
"soft" ) )
1993 bool foundLayer =
false;
1994 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
1996 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
1999 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2005 for (
int i = 0; i < fields.
size(); i++ )
2020 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2032 layer = context->
variable( QStringLiteral(
"layer" ) );
2037 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
2039 layer = node->
eval( parent, context );
2050 feature = QgsExpressionUtils::getFeature( values.at( 2 ), parent );
2054 const QString strength = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).toLower();
2055 if ( strength == QLatin1String(
"hard" ) )
2059 else if ( strength == QLatin1String(
"soft" ) )
2064 const QString attributeName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2066 bool foundLayer =
false;
2067 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, attributeName, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
2069 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2076 if ( fieldIndex == -1 )
2078 parent->
setEvalErrorString( QObject::tr(
"The attribute name did not match any field for the given feature" ) );
2089 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2105 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2110 for (
int i = 0; i < fields.
count(); ++i )
2124 if ( values.isEmpty() )
2127 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2129 else if ( values.size() == 1 )
2131 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2132 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2134 else if ( values.size() == 2 )
2136 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2137 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2141 parent->
setEvalErrorString( QObject::tr(
"Function `represent_attributes` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2148 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: layer could not be resolved." ) );
2154 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: feature could not be resolved." ) );
2160 for (
int fieldIndex = 0; fieldIndex < fields.
count(); ++fieldIndex )
2162 const QString fieldName { fields.
at( fieldIndex ).
name() };
2163 const QVariant attributeVal = feature.
attribute( fieldIndex );
2164 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer->
id(), fieldName, attributeVal.toString() );
2167 result.insert( fieldName, context->
cachedValue( cacheValueKey ) );
2176 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer->
id(), fieldName );
2188 QString value( fieldFormatter->
representValue( layer, fieldIndex, setup.
config(), cache, attributeVal ) );
2190 result.insert( fields.
at( fieldIndex ).
name(), value );
2206 bool evaluate =
true;
2210 if ( values.isEmpty() )
2213 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2215 else if ( values.size() == 1 )
2217 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2218 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2220 else if ( values.size() == 2 )
2222 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2223 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2225 else if ( values.size() == 3 )
2227 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2228 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2229 evaluate = values.value( 2 ).toBool();
2235 parent->
setEvalErrorString( QObject::tr(
"Function `maptip` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2239 parent->
setEvalErrorString( QObject::tr(
"Function `display` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2271 subContext.setFeature( feature );
2280 exp.prepare( &subContext );
2281 return exp.evaluate( &subContext ).toString();
2287 return fcnCoreFeatureMaptipDisplay( values, context, parent,
false );
2292 return fcnCoreFeatureMaptipDisplay( values, context, parent,
true );
2299 if ( values.isEmpty() )
2302 layer = context->
variable( QStringLiteral(
"layer" ) );
2304 else if ( values.size() == 1 )
2306 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2307 layer = context->
variable( QStringLiteral(
"layer" ) );
2309 else if ( values.size() == 2 )
2311 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2312 layer = values.at( 0 );
2316 parent->
setEvalErrorString( QObject::tr(
"Function `is_selected` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2320 bool foundLayer =
false;
2321 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [feature](
QgsMapLayer * mapLayer ) -> QVariant
2323 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2324 if ( !layer || !feature.
isValid() )
2326 return QVariant( QVariant::Bool );
2332 return QVariant( QVariant::Bool );
2341 if ( values.isEmpty() )
2342 layer = context->
variable( QStringLiteral(
"layer" ) );
2343 else if ( values.count() == 1 )
2344 layer = values.at( 0 );
2347 parent->
setEvalErrorString( QObject::tr(
"Function `num_selected` requires no more than one parameter. %n given.",
nullptr, values.length() ) );
2351 bool foundLayer =
false;
2352 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [](
QgsMapLayer * mapLayer ) -> QVariant
2354 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2357 return QVariant( QVariant::LongLong );
2363 return QVariant( QVariant::LongLong );
2370 static QMap<QString, qlonglong> counterCache;
2371 QVariant functionResult;
2373 auto fetchAndIncrementFunc = [ values, parent, &functionResult ](
QgsMapLayer * mapLayer,
const QString & databaseArgument )
2377 const QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( mapLayer );
2382 database = decodedUri.value( QStringLiteral(
"path" ) ).toString();
2383 if ( database.isEmpty() )
2385 parent->
setEvalErrorString( QObject::tr(
"Could not extract file path from layer `%1`." ).arg( layer->
name() ) );
2390 database = databaseArgument;
2393 const QString table = values.at( 1 ).toString();
2394 const QString idColumn = values.at( 2 ).toString();
2395 const QString filterAttribute = values.at( 3 ).toString();
2396 const QVariant filterValue = values.at( 4 ).toString();
2397 const QVariantMap defaultValues = values.at( 5 ).toMap();
2403 if ( sqliteDb.
open_v2( database, SQLITE_OPEN_READWRITE,
nullptr ) != SQLITE_OK )
2406 functionResult = QVariant();
2410 QString errorMessage;
2411 QString currentValSql;
2413 qlonglong nextId = 0;
2414 bool cachedMode =
false;
2415 bool valueRetrieved =
false;
2417 QString cacheString = QStringLiteral(
"%1:%2:%3:%4:%5" ).arg( database, table, idColumn, filterAttribute, filterValue.toString() );
2424 auto cachedCounter = counterCache.find( cacheString );
2426 if ( cachedCounter != counterCache.end() )
2428 qlonglong &cachedValue = cachedCounter.value();
2429 nextId = cachedValue;
2431 cachedValue = nextId;
2432 valueRetrieved =
true;
2437 if ( !cachedMode || !valueRetrieved )
2439 int result = SQLITE_ERROR;
2442 if ( !filterAttribute.isNull() )
2447 sqliteStatement = sqliteDb.
prepare( currentValSql, result );
2449 if ( result == SQLITE_OK )
2452 if ( sqliteStatement.
step() == SQLITE_ROW )
2458 if ( cachedMode && result == SQLITE_OK )
2460 counterCache.insert( cacheString, nextId );
2464 counterCache.remove( cacheString );
2467 valueRetrieved =
true;
2471 if ( valueRetrieved )
2480 if ( !filterAttribute.isNull() )
2486 for ( QVariantMap::const_iterator iter = defaultValues.constBegin(); iter != defaultValues.constEnd(); ++iter )
2489 vals << iter.value().toString();
2492 upsertSql += QLatin1String(
" (" ) + cols.join(
',' ) +
')';
2493 upsertSql += QLatin1String(
" VALUES " );
2494 upsertSql +=
'(' + vals.join(
',' ) +
')';
2496 int result = SQLITE_ERROR;
2500 if ( transaction->
executeSql( upsertSql, errorMessage ) )
2507 result = sqliteDb.
exec( upsertSql, errorMessage );
2509 if ( result == SQLITE_OK )
2511 functionResult = QVariant( nextId );
2516 parent->
setEvalErrorString( QStringLiteral(
"Could not increment value: SQLite error: \"%1\" (%2)." ).arg( errorMessage, QString::number( result ) ) );
2517 functionResult = QVariant();
2522 functionResult = QVariant();
2525 bool foundLayer =
false;
2526 QgsExpressionUtils::executeLambdaForMapLayer( values.at( 0 ), context, parent, [&fetchAndIncrementFunc](
QgsMapLayer * layer )
2528 fetchAndIncrementFunc( layer, QString() );
2532 const QString databasePath = values.at( 0 ).toString();
2535 fetchAndIncrementFunc(
nullptr, databasePath );
2539 return functionResult;
2545 for (
const QVariant &value : values )
2548 concat += QgsExpressionUtils::getStringValue( value, parent );
2555 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2556 return string.indexOf( QgsExpressionUtils::getStringValue( values.at( 1 ), parent ) ) + 1;
2561 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2562 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2563 return string.right( pos );
2568 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2569 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2570 return string.left( pos );
2575 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2576 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2577 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2578 return string.leftJustified( length, fill.at( 0 ),
true );
2583 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2584 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2585 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2586 return string.rightJustified( length, fill.at( 0 ),
true );
2591 if ( values.size() < 1 )
2593 parent->
setEvalErrorString( QObject::tr(
"Function format requires at least 1 argument" ) );
2597 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2598 for (
int n = 1; n < values.length(); n++ )
2600 string =
string.arg( QgsExpressionUtils::getStringValue( values.at( n ), parent ) );
2608 return QVariant( QDateTime::currentDateTime() );
2613 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2614 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2615 if ( format.isEmpty() && !language.isEmpty() )
2617 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Date when the language is specified" ) );
2618 return QVariant( QDate() );
2621 if ( format.isEmpty() && language.isEmpty() )
2622 return QVariant( QgsExpressionUtils::getDateValue( values.at( 0 ), parent ) );
2624 QString datestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2625 QLocale locale = QLocale();
2626 if ( !language.isEmpty() )
2628 locale = QLocale( language );
2631 QDate date = locale.toDate( datestring, format );
2632 if ( !date.isValid() )
2634 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Date" ).arg( datestring ) );
2637 return QVariant( date );
2642 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2643 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2644 if ( format.isEmpty() && !language.isEmpty() )
2646 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Time when the language is specified" ) );
2647 return QVariant( QTime() );
2650 if ( format.isEmpty() && language.isEmpty() )
2651 return QVariant( QgsExpressionUtils::getTimeValue( values.at( 0 ), parent ) );
2653 QString timestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2654 QLocale locale = QLocale();
2655 if ( !language.isEmpty() )
2657 locale = QLocale( language );
2660 QTime time = locale.toTime( timestring, format );
2661 if ( !time.isValid() )
2663 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Time" ).arg( timestring ) );
2666 return QVariant( time );
2671 return QVariant::fromValue( QgsExpressionUtils::getInterval( values.at( 0 ), parent ) );
2680 double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
2681 QString axis = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2682 int precision = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
2684 QString formatString;
2685 if ( values.count() > 3 )
2686 formatString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
2688 QgsCoordinateFormatter::FormatFlags flags = QgsCoordinateFormatter::FormatFlags();
2689 if ( formatString.compare( QLatin1String(
"suffix" ), Qt::CaseInsensitive ) == 0 )
2693 else if ( formatString.compare( QLatin1String(
"aligned" ), Qt::CaseInsensitive ) == 0 )
2697 else if ( ! formatString.isEmpty() )
2699 parent->
setEvalErrorString( QObject::tr(
"Invalid formatting parameter: '%1'. It must be empty, or 'suffix' or 'aligned'." ).arg( formatString ) );
2703 if ( axis.compare( QLatin1String(
"x" ), Qt::CaseInsensitive ) == 0 )
2707 else if ( axis.compare( QLatin1String(
"y" ), Qt::CaseInsensitive ) == 0 )
2713 parent->
setEvalErrorString( QObject::tr(
"Invalid axis name: '%1'. It must be either 'x' or 'y'." ).arg( axis ) );
2721 return floatToDegreeFormat( format, values, context, parent, node );
2728 value = QgsCoordinateUtils::dmsToDecimal( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), &ok );
2730 return ok ? QVariant( value ) : QVariant();
2736 return floatToDegreeFormat( format, values, context, parent, node );
2741 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2742 QDateTime d2 = QgsExpressionUtils::getDateTimeValue( values.at( 1 ), parent );
2743 qint64 seconds = d2.secsTo( d1 );
2744 return QVariant::fromValue(
QgsInterval( seconds ) );
2749 if ( !values.at( 0 ).canConvert<QDate>() )
2752 QDate date = QgsExpressionUtils::getDateValue( values.at( 0 ), parent );
2753 if ( !date.isValid() )
2758 return date.dayOfWeek() % 7;
2763 QVariant value = values.at( 0 );
2764 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2767 return QVariant( inter.
days() );
2771 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2772 return QVariant( d1.date().day() );
2778 QVariant value = values.at( 0 );
2779 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2782 return QVariant( inter.
years() );
2786 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2787 return QVariant( d1.date().year() );
2793 QVariant value = values.at( 0 );
2794 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2797 return QVariant( inter.
months() );
2801 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2802 return QVariant( d1.date().month() );
2808 QVariant value = values.at( 0 );
2809 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2812 return QVariant( inter.
weeks() );
2816 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2817 return QVariant( d1.date().weekNumber() );
2823 QVariant value = values.at( 0 );
2824 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2827 return QVariant( inter.
hours() );
2831 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2832 return QVariant( t1.hour() );
2838 QVariant value = values.at( 0 );
2839 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2842 return QVariant( inter.
minutes() );
2846 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2847 return QVariant( t1.minute() );
2853 QVariant value = values.at( 0 );
2854 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2857 return QVariant( inter.
seconds() );
2861 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2862 return QVariant( t1.second() );
2868 QDateTime dt = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2871 return QVariant( dt.toMSecsSinceEpoch() );
2881 long long millisecs_since_epoch = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
2883 return QVariant( QDateTime::fromMSecsSinceEpoch( millisecs_since_epoch ) );
2888 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2891 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif" ) ) );
2894 QString tag = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2900 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2903 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif_geotag" ) ) );
2910#define ENSURE_GEOM_TYPE(f, g, geomtype) \
2911 if ( !(f).hasGeometry() ) \
2912 return QVariant(); \
2913 QgsGeometry g = (f).geometry(); \
2914 if ( (g).type() != (geomtype) ) \
2921 if ( g.isMultipart() )
2923 return g.asMultiPoint().at( 0 ).x();
2927 return g.asPoint().x();
2935 if ( g.isMultipart() )
2937 return g.asMultiPoint().at( 0 ).y();
2941 return g.asPoint().y();
2955 if ( g.isEmpty() || !abGeom->
is3D() )
2958 if ( g.type() == Qgis::GeometryType::Point && !g.isMultipart() )
2960 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( g.constGet() );
2964 else if ( g.type() == Qgis::GeometryType::Point && g.isMultipart() )
2966 if (
const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( g.constGet() ) )
2968 if ( collection->numGeometries() > 0 )
2970 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
2981 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2987 return QVariant( isValid );
2992 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2996 const QString methodString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).trimmed();
2997#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
3002 if ( methodString.compare( QLatin1String(
"linework" ), Qt::CaseInsensitive ) == 0 )
3004 else if ( methodString.compare( QLatin1String(
"structure" ), Qt::CaseInsensitive ) == 0 )
3007 const bool keepCollapsed = values.value( 2 ).toBool();
3012 valid = geom.
makeValid( method, keepCollapsed );
3016 parent->
setEvalErrorString( QObject::tr(
"The make_valid parameters require a newer GEOS library version" ) );
3020 return QVariant::fromValue( valid );
3025 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3031 for (
int i = 0; i < multiGeom.size(); ++i )
3033 array += QVariant::fromValue( multiGeom.at( i ) );
3041 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3046 if ( geom.
type() == Qgis::GeometryType::Point && !geom.
isMultipart() )
3053 QVariant result(
centroid.asPoint().
x() );
3059 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3064 if ( geom.
type() == Qgis::GeometryType::Point && !geom.
isMultipart() )
3071 QVariant result(
centroid.asPoint().
y() );
3077 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3085 if ( geom.
type() == Qgis::GeometryType::Point && !geom.
isMultipart() )
3087 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3091 else if ( geom.
type() == Qgis::GeometryType::Point && geom.
isMultipart() )
3095 if ( collection->numGeometries() == 1 )
3097 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3108 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3116 if ( geom.
type() == Qgis::GeometryType::Point && !geom.
isMultipart() )
3118 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3122 else if ( geom.
type() == Qgis::GeometryType::Point && geom.
isMultipart() )
3126 if ( collection->numGeometries() == 1 )
3128 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3139 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3144 int idx = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
3171 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3188 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3205 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3210 bool ignoreClosing =
false;
3211 if ( values.length() > 1 )
3213 ignoreClosing = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3223 bool skipLast =
false;
3224 if ( ignoreClosing && ring.count() > 2 && ring.first() == ring.last() )
3229 for (
int i = 0; i < ( skipLast ? ring.count() - 1 : ring.count() ); ++ i )
3241 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3252 for (
int i = 0; i < line->numPoints() - 1; ++i )
3256 << line->pointN( i )
3257 << line->pointN( i + 1 ) );
3268 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3278 if ( collection->numGeometries() == 1 )
3280 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->geometryN( 0 ) );
3285 if ( !curvePolygon )
3289 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3295 QVariant result = curve ? QVariant::fromValue(
QgsGeometry( curve ) ) : QVariant();
3301 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3311 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3317 QVariant result = part ? QVariant::fromValue(
QgsGeometry( part ) ) : QVariant();
3323 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3332 return QVariant::fromValue(
QgsGeometry( boundary ) );
3337 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3346 return QVariant::fromValue( merged );
3351 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3355 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3360 if ( sharedPaths.
isNull() )
3363 return QVariant::fromValue( sharedPaths );
3369 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3374 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3377 if ( simplified.
isNull() )
3385 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3390 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3395 if ( simplified.
isNull() )
3403 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3408 int iterations = std::min( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), 10 );
3409 double offset = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0.0, 0.5 );
3410 double minLength = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3411 double maxAngle = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ), 0.0, 180.0 );
3413 QgsGeometry smoothed = geom.
smooth(
static_cast<unsigned int>( iterations ), offset, minLength, maxAngle );
3422 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3427 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3428 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3429 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3440 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3445 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3446 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3447 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3448 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3449 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3452 minAmplitude, maxAmplitude, seed );
3461 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3466 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3467 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3468 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3479 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3484 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3485 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3486 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3487 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3488 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3491 minAmplitude, maxAmplitude, seed );
3500 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3505 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3506 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3507 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3518 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3523 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3524 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3525 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3526 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3527 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3530 minAmplitude, maxAmplitude, seed );
3539 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3544 const QVariantList pattern = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
3545 QVector< double > dashPattern;
3546 dashPattern.reserve( pattern.size() );
3547 for (
const QVariant &value : std::as_const( pattern ) )
3550 double v = value.toDouble( &ok );
3557 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must be an array of numbers" ) );
3562 if ( dashPattern.size() % 2 != 0 )
3564 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must contain an even number of elements" ) );
3568 const QString startRuleString = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).trimmed();
3570 if ( startRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3572 else if ( startRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3574 else if ( startRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3576 else if ( startRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3578 else if ( startRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3582 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( startRuleString ) );
3586 const QString endRuleString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
3588 if ( endRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3590 else if ( endRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3592 else if ( endRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3594 else if ( endRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3596 else if ( endRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3600 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( endRuleString ) );
3604 const QString adjustString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
3606 if ( adjustString.compare( QLatin1String(
"both" ), Qt::CaseInsensitive ) == 0 )
3608 else if ( adjustString.compare( QLatin1String(
"dash" ), Qt::CaseInsensitive ) == 0 )
3610 else if ( adjustString.compare( QLatin1String(
"gap" ), Qt::CaseInsensitive ) == 0 )
3614 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern size adjustment" ).arg( adjustString ) );
3618 const double patternOffset = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
3629 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3634 const long long count = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3636 if ( densified.
isNull() )
3644 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3649 const double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3651 if ( densified.
isNull() )
3660 if ( values.size() == 1 && QgsExpressionUtils::isList( values.at( 0 ) ) )
3662 list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
3669 QVector< QgsGeometry > parts;
3670 parts.reserve( list.size() );
3671 for (
const QVariant &value : std::as_const( list ) )
3673 if ( value.userType() == QMetaType::type(
"QgsGeometry" ) )
3689 if ( values.count() < 2 || values.count() > 4 )
3691 parent->
setEvalErrorString( QObject::tr(
"Function make_point requires 2-4 arguments" ) );
3695 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3696 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3697 double z = values.count() >= 3 ? QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) : 0.0;
3698 double m = values.count() >= 4 ? QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) : 0.0;
3699 switch ( values.count() )
3713 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3714 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3715 double m = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3721 if ( values.empty() )
3726 QVector<QgsPoint> points;
3727 points.reserve( values.count() );
3729 auto addPoint = [&points](
const QgsGeometry & geom )
3737 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3744 for (
const QVariant &value : values )
3746 if ( value.type() == QVariant::List )
3748 const QVariantList list = value.toList();
3749 for (
const QVariant &v : list )
3751 addPoint( QgsExpressionUtils::getGeometry( v, parent ) );
3756 addPoint( QgsExpressionUtils::getGeometry( value, parent ) );
3760 if ( points.count() < 2 )
3768 if ( values.count() < 1 )
3770 parent->
setEvalErrorString( QObject::tr(
"Function make_polygon requires an argument" ) );
3774 QgsGeometry outerRing = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3776 if ( outerRing.
type() == Qgis::GeometryType::Polygon )
3779 if ( outerRing.
type() != Qgis::GeometryType::Line || outerRing.
isNull() )
3782 std::unique_ptr< QgsPolygon > polygon = std::make_unique< QgsPolygon >();
3784 const QgsCurve *exteriorRing = qgsgeometry_cast< QgsCurve * >( outerRing.
constGet() );
3791 exteriorRing = qgsgeometry_cast< QgsCurve * >( collection->
geometryN( 0 ) );
3796 if ( !exteriorRing )
3799 polygon->setExteriorRing( exteriorRing->
segmentize() );
3802 for (
int i = 1; i < values.count(); ++i )
3804 QgsGeometry ringGeom = QgsExpressionUtils::getGeometry( values.at( i ), parent );
3808 if ( ringGeom.
type() != Qgis::GeometryType::Line || ringGeom.
isNull() )
3811 const QgsCurve *ring = qgsgeometry_cast< QgsCurve * >( ringGeom.
constGet() );
3818 ring = qgsgeometry_cast< QgsCurve * >( collection->
geometryN( 0 ) );
3826 polygon->addInteriorRing( ring->
segmentize() );
3829 return QVariant::fromValue(
QgsGeometry( std::move( polygon ) ) );
3834 std::unique_ptr<QgsTriangle> tr(
new QgsTriangle() );
3835 std::unique_ptr<QgsLineString> lineString(
new QgsLineString() );
3836 lineString->clear();
3838 for (
const QVariant &value : values )
3840 QgsGeometry geom = QgsExpressionUtils::getGeometry( value, parent );
3847 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3854 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3862 lineString->addVertex( *point );
3865 tr->setExteriorRing( lineString.release() );
3867 return QVariant::fromValue(
QgsGeometry( tr.release() ) );
3872 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3879 double radius = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3880 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
3887 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3894 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3902 return QVariant::fromValue(
QgsGeometry( circ.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
3907 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3914 double majorAxis = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3915 double minorAxis = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3916 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3917 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 4 ), parent );
3923 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3930 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3937 QgsEllipse elp( *point, majorAxis, minorAxis, azimuth );
3938 return QVariant::fromValue(
QgsGeometry( elp.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
3944 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3951 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3958 unsigned int nbEdges =
static_cast<unsigned int>( QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) );
3961 parent->
setEvalErrorString( QObject::tr(
"Number of edges/sides must be greater than 2" ) );
3968 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (inscribed) or 1 (circumscribed)" ) );
3972 const QgsPoint *center = qgsgeometry_cast< const QgsPoint * >( pt1.
constGet() );
3979 center = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3986 const QgsPoint *corner = qgsgeometry_cast< const QgsPoint * >( pt2.
constGet() );
3993 corner = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4008 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4014 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4020 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
4021 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
4029 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4035 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4041 QgsGeometry pt3 = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
4050 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (distance) or 1 (projected)" ) );
4053 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
4054 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
4055 const QgsPoint *point3 = qgsgeometry_cast< const QgsPoint *>( pt3.
constGet() );
4074 return QVariant::fromValue( geom.
vertexAt( idx ) );
4082 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4084 const QVariant v = pointAt( geom, idx, parent );
4087 return QVariant( v.value<
QgsPoint>().
x() );
4093 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4095 return fcnOldXat( values, f, parent, node );
4097 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4099 return fcnOldXat( QVariantList() << values[1], f, parent, node );
4102 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4108 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4110 const QVariant v = pointAt( geom, vertexNumber, parent );
4112 return QVariant( v.value<
QgsPoint>().
x() );
4122 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4124 const QVariant v = pointAt( geom, idx, parent );
4127 return QVariant( v.value<
QgsPoint>().
y() );
4133 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4135 return fcnOldYat( values, f, parent, node );
4137 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4139 return fcnOldYat( QVariantList() << values[1], f, parent, node );
4142 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4148 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4150 const QVariant v = pointAt( geom, vertexNumber, parent );
4152 return QVariant( v.value<
QgsPoint>().
y() );
4159 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4165 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4167 const QVariant v = pointAt( geom, vertexNumber, parent );
4169 return QVariant( v.value<
QgsPoint>().
z() );
4176 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4182 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4184 const QVariant v = pointAt( geom, vertexNumber, parent );
4186 return QVariant( v.value<
QgsPoint>().
m() );
4205 return QVariant::fromValue( geom );
4213 QString wkt = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4215 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4221 const QByteArray wkb = QgsExpressionUtils::getBinaryValue( values.at( 0 ), parent );
4227 return !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4232 QString gml = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4239 ogcContext.
layer = mapLayerPtr.data();
4240 ogcContext.
transformContext = context->
variable( QStringLiteral(
"_project_transform_context" ) ).value<QgsCoordinateTransformContext>();
4244 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4257 return QVariant( area );
4267 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4269 if ( geom.
type() != Qgis::GeometryType::Polygon )
4272 return QVariant( geom.
area() );
4284 return QVariant( len );
4301 return QVariant( len );
4305 return f.
geometry().
isNull() ? QVariant( 0 ) : QVariant( f.geometry().constGet()->perimeter() );
4311 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4313 if ( geom.
type() != Qgis::GeometryType::Polygon )
4317 return QVariant( geom.
length() );
4322 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4328 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4337 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4346 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4361 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon *>( collection->
geometryN( i ) );
4362 if ( !curvePolygon )
4374 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4381 return QVariant( curvePolygon->
ringCount() );
4383 bool foundPoly =
false;
4391 curvePolygon = qgsgeometry_cast< QgsCurvePolygon *>( collection->
geometryN( i ) );
4392 if ( !curvePolygon )
4403 return QVariant( ringCount );
4408 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4410 QVariant result = !geomBounds.
isNull() ? QVariant::fromValue( geomBounds ) : QVariant();
4416 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4422 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4428 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4437 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4443 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4449 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4455 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4461 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4469 double max = std::numeric_limits< double >::lowest();
4473 double z = ( *it ).z();
4479 if ( max == std::numeric_limits< double >::lowest() )
4480 return QVariant( QVariant::Double );
4482 return QVariant( max );
4487 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4495 double min = std::numeric_limits< double >::max();
4499 double z = ( *it ).z();
4505 if ( min == std::numeric_limits< double >::max() )
4506 return QVariant( QVariant::Double );
4508 return QVariant( min );
4513 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4521 double min = std::numeric_limits< double >::max();
4525 double m = ( *it ).m();
4531 if ( min == std::numeric_limits< double >::max() )
4532 return QVariant( QVariant::Double );
4534 return QVariant( min );
4539 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4547 double max = std::numeric_limits< double >::lowest();
4551 double m = ( *it ).m();
4557 if ( max == std::numeric_limits< double >::lowest() )
4558 return QVariant( QVariant::Double );
4560 return QVariant( max );
4565 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4566 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom.
constGet() );
4569 parent->
setEvalErrorString( QObject::tr(
"Function `sinuosity` requires a line geometry." ) );
4578 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4582 parent->
setEvalErrorString( QObject::tr(
"Function `straight_distance_2d` requires a line geometry or a multi line geometry with a single part." ) );
4591 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4596 parent->
setEvalErrorString( QObject::tr(
"Function `roundness` requires a polygon geometry or a multi polygon geometry with a single part." ) );
4607 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4611 std::unique_ptr< QgsAbstractGeometry > flipped( geom.
constGet()->
clone() );
4613 return QVariant::fromValue(
QgsGeometry( std::move( flipped ) ) );
4618 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4622 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( fGeom.
constGet() );
4629 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
4637 return QVariant::fromValue( curve->
isClosed() );
4642 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4655 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4656 closedLine->close();
4658 result = QVariant::fromValue(
QgsGeometry( std::move( closedLine ) ) );
4668 if (
const QgsLineString *line = qgsgeometry_cast<const QgsLineString * >( collection->
geometryN( i ) ) )
4670 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4671 closedLine->close();
4673 closed->addGeometry( closedLine.release() );
4676 result = QVariant::fromValue(
QgsGeometry( std::move( closed ) ) );
4684 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4688 return QVariant::fromValue( fGeom.
isEmpty() );
4694 return QVariant::fromValue(
true );
4696 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4697 return QVariant::fromValue( fGeom.
isNull() || fGeom.
isEmpty() );
4702 if ( values.length() < 2 || values.length() > 3 )
4705 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4706 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4713 if ( values.length() == 2 )
4716 QString result = engine->relate( sGeom.
constGet() );
4717 return QVariant::fromValue( result );
4722 QString pattern = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
4723 bool result = engine->relatePattern( sGeom.
constGet(), pattern );
4724 return QVariant::fromValue( result );
4730 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4731 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4736 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4737 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4738 return fGeom.
disjoint( sGeom ) ? TVL_True : TVL_False;
4742 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4743 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4744 return fGeom.
intersects( sGeom ) ? TVL_True : TVL_False;
4748 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4749 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4750 return fGeom.
touches( sGeom ) ? TVL_True : TVL_False;
4754 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4755 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4756 return fGeom.
crosses( sGeom ) ? TVL_True : TVL_False;
4760 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4761 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4762 return fGeom.
contains( sGeom ) ? TVL_True : TVL_False;
4766 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4767 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4768 return fGeom.
overlaps( sGeom ) ? TVL_True : TVL_False;
4772 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4773 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4774 return fGeom.
within( sGeom ) ? TVL_True : TVL_False;
4779 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4780 const double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4781 const int seg = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4782 const QString endCapString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
4783 const QString joinString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
4784 const double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
4787 if ( endCapString.compare( QLatin1String(
"flat" ), Qt::CaseInsensitive ) == 0 )
4788 capStyle = Qgis::EndCapStyle::Flat;
4789 else if ( endCapString.compare( QLatin1String(
"square" ), Qt::CaseInsensitive ) == 0 )
4790 capStyle = Qgis::EndCapStyle::Square;
4793 if ( joinString.compare( QLatin1String(
"miter" ), Qt::CaseInsensitive ) == 0 )
4794 joinStyle = Qgis::JoinStyle::Miter;
4795 else if ( joinString.compare( QLatin1String(
"bevel" ), Qt::CaseInsensitive ) == 0 )
4796 joinStyle = Qgis::JoinStyle::Bevel;
4799 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4805 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4807 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4812 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4814 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4819 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4821 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4826 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4827 const QgsPoint *pt = qgsgeometry_cast<const QgsPoint *>( fGeom.
constGet() );
4834 pt = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4841 parent->
setEvalErrorString( QObject::tr(
"Function `wedge_buffer` requires a point value for the center." ) );
4845 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4846 double width = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4847 double outerRadius = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4848 double innerRadius = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
4851 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4857 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4858 if ( fGeom.
type() != Qgis::GeometryType::Line )
4860 parent->
setEvalErrorString( QObject::tr(
"Function `tapered_buffer` requires a line geometry." ) );
4864 double startWidth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4865 double endWidth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4866 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) );
4869 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4875 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4876 if ( fGeom.
type() != Qgis::GeometryType::Line )
4878 parent->
setEvalErrorString( QObject::tr(
"Function `buffer_by_m` requires a line geometry." ) );
4882 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) );
4885 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4891 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4892 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4893 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4894 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4895 if ( joinInt < 1 || joinInt > 3 )
4899 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4902 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4908 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4909 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4910 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4912 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4913 if ( joinInt < 1 || joinInt > 3 )
4917 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4920 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4926 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4927 double distStart = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4928 double distEnd = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4931 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4937 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4938 double dx = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4939 double dy = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4941 return QVariant::fromValue( fGeom );
4946 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4947 const double rotation = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4948 const QgsGeometry center = values.at( 2 ).
isValid() ? QgsExpressionUtils::getGeometry( values.at( 2 ), parent )
4950 const bool perPart = values.value( 3 ).toBool();
4957 std::unique_ptr< QgsGeometryCollection > collection( qgsgeometry_cast< QgsGeometryCollection * >( fGeom.
constGet()->
clone() ) );
4960 const QgsPointXY partCenter = ( *it )->boundingBox().center();
4961 QTransform t = QTransform::fromTranslate( partCenter.
x(), partCenter.
y() );
4962 t.rotate( -rotation );
4963 t.translate( -partCenter.
x(), -partCenter.
y() );
4964 ( *it )->transform( t );
4966 return QVariant::fromValue(
QgsGeometry( std::move( collection ) ) );
4978 parent->
setEvalErrorString( QObject::tr(
"Function 'rotate' requires a point value for the center" ) );
4986 fGeom.
rotate( rotation, pt );
4987 return QVariant::fromValue( fGeom );
4993 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4994 const double xScale = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4995 const double yScale = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4996 const QgsGeometry center = values.at( 3 ).isValid() ? QgsExpressionUtils::getGeometry( values.at( 3 ), parent )
5007 parent->
setEvalErrorString( QObject::tr(
"Function 'scale' requires a point value for the center" ) );
5015 QTransform t = QTransform::fromTranslate( pt.
x(), pt.
y() );
5016 t.scale( xScale, yScale );
5017 t.translate( -pt.
x(), -pt.
y() );
5019 return QVariant::fromValue( fGeom );
5024 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5030 const double deltaX = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5031 const double deltaY = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5033 const double rotationZ = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5035 const double scaleX = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
5036 const double scaleY = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
5038 const double deltaZ = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
5039 const double deltaM = QgsExpressionUtils::getDoubleValue( values.at( 7 ), parent );
5040 const double scaleZ = QgsExpressionUtils::getDoubleValue( values.at( 8 ), parent );
5041 const double scaleM = QgsExpressionUtils::getDoubleValue( values.at( 9 ), parent );
5052 QTransform transform;
5053 transform.translate( deltaX, deltaY );
5054 transform.rotate( rotationZ );
5055 transform.scale( scaleX, scaleY );
5056 fGeom.
transform( transform, deltaZ, scaleZ, deltaM, scaleM );
5058 return QVariant::fromValue( fGeom );
5064 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5066 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5071 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5073 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5079 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5080 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5082 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5088 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5090 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5094#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
5099 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5100 const double targetPercent = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5101 const bool allowHoles = values.value( 2 ).toBool();
5103 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5116 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5118 if ( values.length() == 2 )
5119 segments = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5127 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5133 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5135 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5141 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5147 double area,
angle, width, height;
5160 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5161 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5163 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5169 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5176 const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( fGeom.
constGet() );
5181 result = reversed ? QVariant::fromValue(
QgsGeometry( reversed ) ) : QVariant();
5189 if (
const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( collection->
geometryN( i ) ) )
5191 reversed->addGeometry( curve->
reversed() );
5198 result = reversed ? QVariant::fromValue(
QgsGeometry( std::move( reversed ) ) ) : QVariant();
5205 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5216 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->
geometryN( 0 ) );
5225 QVariant result = exterior ? QVariant::fromValue(
QgsGeometry( exterior ) ) : QVariant();
5231 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5232 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5233 return QVariant( fGeom.
distance( sGeom ) );
5238 QgsGeometry g1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5239 QgsGeometry g2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5242 if ( values.length() == 3 && values.at( 2 ).isValid() )
5244 double densify = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5245 densify = std::clamp( densify, 0.0, 1.0 );
5253 return res > -1 ? QVariant( res ) : QVariant();
5258 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5259 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5261 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5266 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5267 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5269 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5274 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5275 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5277 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5283 if ( values.length() < 1 || values.length() > 2 )
5286 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5288 if ( values.length() == 2 )
5289 prec = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5290 QString wkt = fGeom.
asWkt( prec );
5291 return QVariant( wkt );
5296 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5297 return fGeom.
isNull() ? QVariant() : QVariant( fGeom.asWkb() );
5302 if ( values.length() != 2 )
5304 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires exactly two parameters. %n given.",
nullptr, values.length() ) );
5308 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5309 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5311 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5318 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5323 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5330 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5337 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires two points as arguments." ) );
5344 if ( pt1->
y() < pt2->
y() )
5346 else if ( pt1->
y() > pt2->
y() )
5354 if ( pt1->
x() < pt2->
x() )
5356 else if ( pt1->
x() > pt2->
x() )
5357 return M_PI + ( M_PI_2 );
5362 if ( pt1->
x() < pt2->
x() )
5364 if ( pt1->
y() < pt2->
y() )
5366 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) );
5370 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5377 if ( pt1->
y() > pt2->
y() )
5379 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() ) )
5385 + ( M_PI + ( M_PI_2 ) );
5392 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5396 parent->
setEvalErrorString( QStringLiteral(
"'project' requires a point geometry" ) );
5400 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5401 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5402 double inclination = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5405 QgsPoint newPoint = p->
project( distance, 180.0 * azimuth / M_PI, 180.0 * inclination / M_PI );
5412 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5413 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5415 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5422 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5426 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5433 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5438 if ( ( fGeom1.
type() != Qgis::GeometryType::Point ) || ( fGeom2.
type() != Qgis::GeometryType::Point ) ||
5441 parent->
setEvalErrorString( QStringLiteral(
"Function 'inclination' requires two points as arguments." ) );
5451 if ( values.length() != 3 )
5454 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5455 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5456 double y = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5460 QVariant result = geom.
constGet() ? QVariant::fromValue( geom ) : QVariant();
5466 if ( values.length() < 2 )
5469 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5472 return values.at( 0 );
5474 QString expString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5475 QVariant cachedExpression;
5480 if ( cachedExpression.isValid() )
5487 bool asc = values.value( 2 ).toBool();
5505 Q_ASSERT( collection );
5509 QgsExpressionSorter sorter( orderBy );
5511 QList<QgsFeature> partFeatures;
5512 partFeatures.reserve( collection->
partCount() );
5513 for (
int i = 0; i < collection->
partCount(); ++i )
5519 sorter.sortFeatures( partFeatures, unconstedContext );
5523 Q_ASSERT( orderedGeom );
5528 for (
const QgsFeature &feature : std::as_const( partFeatures ) )
5533 QVariant result = QVariant::fromValue(
QgsGeometry( orderedGeom ) );
5536 delete unconstedContext;
5543 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5544 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5548 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5554 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5555 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5559 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5565 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5566 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5570 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5576 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5577 if ( lineGeom.
type() != Qgis::GeometryType::Line )
5579 parent->
setEvalErrorString( QObject::tr(
"line_substring requires a curve geometry input" ) );
5585 curve = qgsgeometry_cast< const QgsCurve * >( lineGeom.
constGet() );
5592 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
5599 double startDistance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5600 double endDistance = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5602 std::unique_ptr< QgsCurve > substring( curve->
curveSubstring( startDistance, endDistance ) );
5604 return !result.isNull() ? QVariant::fromValue( result ) : QVariant();
5609 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5610 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5617 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5618 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5623 vertex = count + vertex;
5631 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5632 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5637 vertex = count + vertex;
5645 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5646 QgsGeometry pointGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5650 return distance >= 0 ? distance : QVariant();
5655 if ( values.length() == 2 && values.at( 1 ).toInt() != 0 )
5657 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5658 return qgsRound( number, QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
5661 if ( values.length() >= 1 )
5663 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5664 return QVariant( qlonglong( std::round( number ) ) );
5679 const double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5680 const int places = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5681 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5688 const bool omitGroupSeparator = values.value( 3 ).toBool();
5689 const bool trimTrailingZeros = values.value( 4 ).toBool();
5691 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5692 if ( !omitGroupSeparator )
5693 locale.setNumberOptions( locale.numberOptions() & ~QLocale::NumberOption::OmitGroupSeparator );
5695 locale.setNumberOptions( locale.numberOptions() | QLocale::NumberOption::OmitGroupSeparator );
5697 QString res = locale.toString( value,
'f', places );
5699 if ( trimTrailingZeros )
5701#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
5702 const QChar decimal = locale.decimalPoint();
5703 const QChar zeroDigit = locale.zeroDigit();
5705 const QChar decimal = locale.decimalPoint().at( 0 );
5706 const QChar zeroDigit = locale.zeroDigit().at( 0 );
5709 if ( res.contains( decimal ) )
5711 int trimPoint = res.length() - 1;
5713 while ( res.at( trimPoint ) == zeroDigit )
5716 if ( res.at( trimPoint ) == decimal )
5719 res.truncate( trimPoint + 1 );
5728 const QDateTime datetime = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
5729 const QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5730 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5732 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5733 return locale.toString( datetime, format );
5739 int avg = ( color.red() + color.green() + color.blue() ) / 3;
5740 int alpha = color.alpha();
5742 color.setRgb( avg, avg, avg, alpha );
5751 double ratio = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5756 else if ( ratio < 0 )
5761 int red =
static_cast<int>( color1.red() * ( 1 - ratio ) + color2.red() * ratio );
5762 int green =
static_cast<int>( color1.green() * ( 1 - ratio ) + color2.green() * ratio );
5763 int blue =
static_cast<int>( color1.blue() * ( 1 - ratio ) + color2.blue() * ratio );
5764 int alpha =
static_cast<int>( color1.alpha() * ( 1 - ratio ) + color2.alpha() * ratio );
5766 QColor newColor( red, green, blue, alpha );
5773 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
5774 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5775 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
5776 QColor color = QColor( red, green, blue );
5777 if ( ! color.isValid() )
5779 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( red ).arg( green ).arg( blue ) );
5780 color = QColor( 0, 0, 0 );
5783 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
5788 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
5789 QVariant value = node->
eval( parent, context );
5793 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
5795 value = node->
eval( parent, context );
5803 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
5805 QVariant value = node->
eval( parent, context );
5807 if ( value.toBool() )
5809 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
5811 value = node->
eval( parent, context );
5816 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
5818 value = node->
eval( parent, context );
5826 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
5827 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5828 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
5829 int alpha = QgsExpressionUtils::getNativeIntValue( values.at( 3 ), parent );
5830 QColor color = QColor( red, green, blue, alpha );
5831 if ( ! color.isValid() )
5833 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
5834 color = QColor( 0, 0, 0 );
5843 if ( values.at( 0 ).userType() == QMetaType::type(
"QgsGradientColorRamp" ) )
5845 expRamp = QgsExpressionUtils::getRamp( values.at( 0 ), parent );
5850 QString rampName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
5854 parent->
setEvalErrorString( QObject::tr(
"\"%1\" is not a valid color ramp" ).arg( rampName ) );
5859 double value = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5860 QColor color = ramp->
color( value );
5867 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
5869 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5871 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5873 QColor color = QColor::fromHslF( hue, saturation, lightness );
5875 if ( ! color.isValid() )
5877 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( lightness ) );
5878 color = QColor( 0, 0, 0 );
5881 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
5887 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
5889 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5891 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5893 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
5895 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
5896 if ( ! color.isValid() )
5898 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
5899 color = QColor( 0, 0, 0 );
5907 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
5909 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5911 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5913 QColor color = QColor::fromHsvF( hue, saturation, value );
5915 if ( ! color.isValid() )
5917 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( value ) );
5918 color = QColor( 0, 0, 0 );
5921 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
5927 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
5929 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5931 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5933 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
5935 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
5936 if ( ! color.isValid() )
5938 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
5939 color = QColor( 0, 0, 0 );
5947 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
5949 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5951 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5953 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
5955 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black );
5957 if ( ! color.isValid() )
5959 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ) );
5960 color = QColor( 0, 0, 0 );
5963 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
5969 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
5971 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5973 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5975 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
5977 double alpha = QgsExpressionUtils::getIntValue( values.at( 4 ), parent ) / 255.0;
5979 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
5980 if ( ! color.isValid() )
5982 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
5983 color = QColor( 0, 0, 0 );
5991 if ( ! color.isValid() )
5993 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( values.at( 0 ).toString() ) );
5997 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5998 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6000 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6001 return color.green();
6002 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6003 return color.blue();
6004 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6005 return color.alpha();
6006 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6007 return static_cast< double >( color.hsvHueF() * 360 );
6008 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6009 return static_cast< double >( color.hsvSaturationF() * 100 );
6010 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6011 return static_cast< double >( color.valueF() * 100 );
6012 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6013 return static_cast< double >( color.hslHueF() * 360 );
6014 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6015 return static_cast< double >( color.hslSaturationF() * 100 );
6016 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6017 return static_cast< double >( color.lightnessF() * 100 );
6018 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6019 return static_cast< double >( color.cyanF() * 100 );
6020 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6021 return static_cast< double >( color.magentaF() * 100 );
6022 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6023 return static_cast< double >( color.yellowF() * 100 );
6024 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6025 return static_cast< double >( color.blackF() * 100 );
6027 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6033 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
6036 parent->
setEvalErrorString( QObject::tr(
"A minimum of two colors is required to create a ramp" ) );
6040 QList< QColor > colors;
6042 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
6045 if ( !colors.last().isValid() )
6047 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( it.value().toString() ) );
6051 double step = it.key().toDouble();
6052 if ( it == map.constBegin() )
6057 else if ( it == map.constEnd() )
6067 bool discrete = values.at( 1 ).toBool();
6069 if ( colors.empty() )
6072 return QVariant::fromValue(
QgsGradientColorRamp( colors.first(), colors.last(), discrete, stops ) );
6078 if ( ! color.isValid() )
6080 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( values.at( 0 ).toString() ) );
6084 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6085 int value = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6086 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6087 color.setRed( value );
6088 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6089 color.setGreen( value );
6090 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6091 color.setBlue( value );
6092 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6093 color.setAlpha( value );
6094 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6095 color.setHsv( value, color.hsvSaturation(), color.value(), color.alpha() );
6096 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6097 color.setHsvF( color.hsvHueF(), value / 100.0, color.valueF(), color.alphaF() );
6098 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6099 color.setHsvF( color.hsvHueF(), color.hsvSaturationF(), value / 100.0, color.alphaF() );
6100 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6101 color.setHsl( value, color.hslSaturation(), color.lightness(), color.alpha() );
6102 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6103 color.setHslF( color.hslHueF(), value / 100.0, color.lightnessF(), color.alphaF() );
6104 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6105 color.setHslF( color.hslHueF(), color.hslSaturationF(), value / 100.0, color.alphaF() );
6106 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6107 color.setCmykF( value / 100.0, color.magentaF(), color.yellowF(), color.blackF(), color.alphaF() );
6108 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6109 color.setCmykF( color.cyanF(), value / 100.0, color.yellowF(), color.blackF(), color.alphaF() );
6110 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6111 color.setCmykF( color.cyanF(), color.magentaF(), value / 100.0, color.blackF(), color.alphaF() );
6112 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6113 color.setCmykF( color.cyanF(), color.magentaF(), color.yellowF(), value / 100.0, color.alphaF() );
6116 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6125 if ( ! color.isValid() )
6127 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( values.at( 0 ).toString() ) );
6131 color = color.darker( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6139 if ( ! color.isValid() )
6141 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( values.at( 0 ).toString() ) );
6145 color = color.lighter( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6152 QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6155 return QVariant::fromValue( geom );
6161 const QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6169 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
6170 QString sAuthId = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6171 QString dAuthId = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6175 return QVariant::fromValue( fGeom );
6178 return QVariant::fromValue( fGeom );
6187 return QVariant::fromValue( fGeom );
6200 bool foundLayer =
false;
6201 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6204 if ( !featureSource || !foundLayer )
6209 const QgsFeatureId fid = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
6222 result = QVariant::fromValue( fet );
6230 bool foundLayer =
false;
6231 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6234 if ( !featureSource || !foundLayer )
6239 QString cacheValueKey;
6240 if ( values.at( 1 ).type() == QVariant::Map )
6242 QVariantMap attributeMap = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
6244 QMap <QString, QVariant>::const_iterator i = attributeMap.constBegin();
6245 QString filterString;
6246 for ( ; i != attributeMap.constEnd(); ++i )
6248 if ( !filterString.isEmpty() )
6250 filterString.append(
" AND " );
6254 cacheValueKey = QStringLiteral(
"getfeature:%1:%2" ).arg( featureSource->id(), filterString );
6263 QString attribute = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6264 int attributeId = featureSource->fields().lookupField( attribute );
6265 if ( attributeId == -1 )
6270 const QVariant &attVal = values.at( 2 );
6272 cacheValueKey = QStringLiteral(
"getfeature:%1:%2:%3" ).arg( featureSource->id(), QString::number( attributeId ), attVal.toString() );
6295 res = QVariant::fromValue( fet );
6310 if ( !values.isEmpty() )
6313 if ( col && ( values.size() == 1 || !values.at( 1 ).isValid() ) )
6314 fieldName = col->
name();
6315 else if ( values.size() == 2 )
6316 fieldName = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6319 QVariant value = values.at( 0 );
6324 if ( fieldIndex == -1 )
6326 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: Field not found %2" ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6332 QgsVectorLayer *layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
6335 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName, value.toString() );
6344 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName );
6355 result =
formatter->representValue( layer, fieldIndex, setup.
config(), cache, value );
6362 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: function cannot be evaluated without a context." ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6370 const QVariant data = values.at( 0 );
6371 const QMimeDatabase db;
6372 return db.mimeTypeForData( data.toByteArray() ).name();
6377 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6379 bool foundLayer =
false;
6380 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [layerProperty](
QgsMapLayer * layer )-> QVariant
6386 if ( QString::compare( layerProperty, QStringLiteral(
"name" ), Qt::CaseInsensitive ) == 0 )
6387 return layer->name();
6388 else if ( QString::compare( layerProperty, QStringLiteral(
"id" ), Qt::CaseInsensitive ) == 0 )
6390 else if ( QString::compare( layerProperty, QStringLiteral(
"title" ), Qt::CaseInsensitive ) == 0 )
6391 return !layer->metadata().title().isEmpty() ? layer->metadata().title() : layer->title();
6392 else if ( QString::compare( layerProperty, QStringLiteral(
"abstract" ), Qt::CaseInsensitive ) == 0 )
6393 return !layer->metadata().abstract().isEmpty() ? layer->metadata().abstract() : layer->abstract();
6394 else if ( QString::compare( layerProperty, QStringLiteral(
"keywords" ), Qt::CaseInsensitive ) == 0 )
6396 QStringList keywords;
6397 const QgsAbstractMetadataBase::KeywordMap keywordMap = layer->metadata().keywords();
6398 for ( auto it = keywordMap.constBegin(); it != keywordMap.constEnd(); ++it )
6400 keywords.append( it.value() );
6402 if ( !keywords.isEmpty() )
6404 return layer->keywordList();
6406 else if ( QString::compare( layerProperty, QStringLiteral(
"data_url" ), Qt::CaseInsensitive ) == 0 )
6408 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution" ), Qt::CaseInsensitive ) == 0 )
6412 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution_url" ), Qt::CaseInsensitive ) == 0 )
6414 else if ( QString::compare( layerProperty, QStringLiteral(
"source" ), Qt::CaseInsensitive ) == 0 )
6416 else if ( QString::compare( layerProperty, QStringLiteral(
"min_scale" ), Qt::CaseInsensitive ) == 0 )
6418 else if ( QString::compare( layerProperty, QStringLiteral(
"max_scale" ), Qt::CaseInsensitive ) == 0 )
6420 else if ( QString::compare( layerProperty, QStringLiteral(
"is_editable" ), Qt::CaseInsensitive ) == 0 )
6422 else if ( QString::compare( layerProperty, QStringLiteral(
"crs" ), Qt::CaseInsensitive ) == 0 )
6424 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_definition" ), Qt::CaseInsensitive ) == 0 )
6426 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_description" ), Qt::CaseInsensitive ) == 0 )
6428 else if ( QString::compare( layerProperty, QStringLiteral(
"extent" ), Qt::CaseInsensitive ) == 0 )
6431 QVariant result = QVariant::fromValue( extentGeom );
6434 else if ( QString::compare( layerProperty, QStringLiteral(
"distance_units" ), Qt::CaseInsensitive ) == 0 )
6436 else if ( QString::compare( layerProperty, QStringLiteral(
"path" ), Qt::CaseInsensitive ) == 0 )
6439 return decodedUri.value( QStringLiteral(
"path" ) );
6441 else if ( QString::compare( layerProperty, QStringLiteral(
"type" ), Qt::CaseInsensitive ) == 0 )
6443 switch ( layer->
type() )
6445 case Qgis::LayerType::Vector:
6446 return QCoreApplication::translate(
"expressions",
"Vector" );
6447 case Qgis::LayerType::Raster:
6448 return QCoreApplication::translate(
"expressions",
"Raster" );
6449 case Qgis::LayerType::Mesh:
6450 return QCoreApplication::translate(
"expressions",
"Mesh" );
6451 case Qgis::LayerType::VectorTile:
6452 return QCoreApplication::translate(
"expressions",
"Vector Tile" );
6453 case Qgis::LayerType::Plugin:
6454 return QCoreApplication::translate(
"expressions",
"Plugin" );
6455 case Qgis::LayerType::Annotation:
6456 return QCoreApplication::translate(
"expressions",
"Annotation" );
6457 case Qgis::LayerType::PointCloud:
6458 return QCoreApplication::translate(
"expressions",
"Point Cloud" );
6459 case Qgis::LayerType::Group:
6460 return QCoreApplication::translate(
"expressions",
"Group" );
6466 QgsVectorLayer *vLayer = qobject_cast< QgsVectorLayer * >( layer );
6469 if ( QString::compare( layerProperty, QStringLiteral(
"storage_type" ), Qt::CaseInsensitive ) == 0 )
6471 else if ( QString::compare( layerProperty, QStringLiteral(
"geometry_type" ), Qt::CaseInsensitive ) == 0 )
6473 else if ( QString::compare( layerProperty, QStringLiteral(
"feature_count" ), Qt::CaseInsensitive ) == 0 )
6489 const QString uriPart = values.at( 1 ).toString();
6491 bool foundLayer =
false;
6493 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, uriPart](
QgsMapLayer * layer )-> QVariant
6495 if ( !layer->dataProvider() )
6497 parent->setEvalErrorString( QObject::tr(
"Layer %1 has invalid data provider" ).arg( layer->name() ) );
6503 if ( !uriPart.isNull() )
6505 return decodedUri.value( uriPart );
6515 parent->
setEvalErrorString( QObject::tr(
"Function `decode_uri` requires a valid layer." ) );
6526 const int band = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6527 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6529 bool foundLayer =
false;
6530 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, band, layerProperty](
QgsMapLayer * layer )-> QVariant
6532 QgsRasterLayer *rl = qobject_cast< QgsRasterLayer * >( layer );
6536 if ( band < 1 || band > rl->bandCount() )
6538 parent->setEvalErrorString( QObject::tr(
"Invalid band number %1 for layer" ).arg( band ) );
6544 if ( QString::compare( layerProperty, QStringLiteral(
"avg" ), Qt::CaseInsensitive ) == 0 )
6546 else if ( QString::compare( layerProperty, QStringLiteral(
"stdev" ), Qt::CaseInsensitive ) == 0 )
6548 else if ( QString::compare( layerProperty, QStringLiteral(
"min" ), Qt::CaseInsensitive ) == 0 )
6550 else if ( QString::compare( layerProperty, QStringLiteral(
"max" ), Qt::CaseInsensitive ) == 0 )
6552 else if ( QString::compare( layerProperty, QStringLiteral(
"range" ), Qt::CaseInsensitive ) == 0 )
6554 else if ( QString::compare( layerProperty, QStringLiteral(
"sum" ), Qt::CaseInsensitive ) == 0 )
6558 parent->
setEvalErrorString( QObject::tr(
"Invalid raster statistic: '%1'" ).arg( layerProperty ) );
6584 parent->
setEvalErrorString( QObject::tr(
"Function `raster_statistic` requires a valid raster layer." ) );
6601 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6602 bool ascending = values.value( 1 ).toBool();
6603 std::sort( list.begin(), list.end(), [ascending]( QVariant a, QVariant b ) ->
bool { return ( !ascending ? qgsVariantLessThan( b, a ) : qgsVariantLessThan( a, b ) ); } );
6609 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).length();
6614 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).contains( values.at( 1 ) ) );
6619 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).count( values.at( 1 ) ) );
6624 QVariantList listA = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6625 QVariantList listB = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
6627 for (
const auto &item : listB )
6629 if ( listA.contains( item ) )
6633 return QVariant( match == listB.count() );
6638 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).indexOf( values.at( 1 ) );
6643 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6644 const int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6645 if ( pos < list.length() && pos >= 0 )
return list.at( pos );
6646 else if ( pos < 0 && ( list.length() + pos ) >= 0 )
6647 return list.at( list.length() + pos );
6653 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6654 return list.value( 0 );
6659 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6660 return list.value( list.size() - 1 );
6665 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6666 return list.isEmpty() ? QVariant() : *std::min_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
6671 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6672 return list.isEmpty() ? QVariant() : *std::max_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
6677 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6680 for (
const QVariant &item : list )
6682 switch ( item.userType() )
6684 case QMetaType::Int:
6685 case QMetaType::UInt:
6686 case QMetaType::LongLong:
6687 case QMetaType::ULongLong:
6688 case QMetaType::Float:
6689 case QMetaType::Double:
6690 total += item.toDouble();
6695 return i == 0 ? QVariant() : total / i;
6700 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6701 QVariantList numbers;
6702 for (
const auto &item : list )
6704 switch ( item.userType() )
6706 case QMetaType::Int:
6707 case QMetaType::UInt:
6708 case QMetaType::LongLong:
6709 case QMetaType::ULongLong:
6710 case QMetaType::Float:
6711 case QMetaType::Double:
6712 numbers.append( item );
6716 std::sort( numbers.begin(), numbers.end(), []( QVariant a, QVariant b ) ->
bool { return ( qgsVariantLessThan( a, b ) ); } );
6717 const int count = numbers.count();
6722 else if ( count % 2 )
6724 return numbers.at( count / 2 );
6728 return ( numbers.at( count / 2 - 1 ).toDouble() + numbers.at( count / 2 ).toDouble() ) / 2;
6734 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6737 for (
const QVariant &item : list )
6739 switch ( item.userType() )
6741 case QMetaType::Int:
6742 case QMetaType::UInt:
6743 case QMetaType::LongLong:
6744 case QMetaType::ULongLong:
6745 case QMetaType::Float:
6746 case QMetaType::Double:
6747 total += item.toDouble();
6752 return i == 0 ? QVariant() : total;
6755static QVariant convertToSameType(
const QVariant &value, QVariant::Type type )
6757 QVariant result = value;
6758 result.convert(
static_cast<int>( type ) );
6764 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6765 QHash< QVariant, int > hash;
6766 for (
const auto &item : list )
6770 const QList< int > occurrences = hash.values();
6771 if ( occurrences.empty() )
6772 return QVariantList();
6774 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
6776 const QString option = values.at( 1 ).toString();
6777 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
6779 return convertToSameType( hash.keys( maxValue ), values.at( 0 ).type() );
6781 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
6783 if ( hash.isEmpty() )
6786 return QVariant( hash.key( maxValue ) );
6788 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
6790 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( maxValue ), values.at( 0 ).type() ), context, parent, node );
6792 else if ( option.compare( QLatin1String(
"real_majority" ), Qt::CaseInsensitive ) == 0 )
6794 if ( maxValue * 2 <= list.size() )
6797 return QVariant( hash.key( maxValue ) );
6808 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6809 QHash< QVariant, int > hash;
6810 for (
const auto &item : list )
6814 const QList< int > occurrences = hash.values();
6815 if ( occurrences.empty() )
6816 return QVariantList();
6818 const int minValue = *std::min_element( occurrences.constBegin(), occurrences.constEnd() );
6820 const QString option = values.at( 1 ).toString();
6821 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
6823 return convertToSameType( hash.keys( minValue ), values.at( 0 ).type() );
6825 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
6827 if ( hash.isEmpty() )
6830 return QVariant( hash.key( minValue ) );
6832 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
6834 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( minValue ), values.at( 0 ).type() ), context, parent, node );
6836 else if ( option.compare( QLatin1String(
"real_minority" ), Qt::CaseInsensitive ) == 0 )
6838 if ( hash.isEmpty() )
6842 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
6843 if ( maxValue * 2 > list.size() )
6844 hash.remove( hash.key( maxValue ) );
6846 return convertToSameType( hash.keys(), values.at( 0 ).type() );
6857 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6858 list.append( values.at( 1 ) );
6859 return convertToSameType( list, values.at( 0 ).type() );
6864 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6865 list.prepend( values.at( 1 ) );
6866 return convertToSameType( list, values.at( 0 ).type() );
6871 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6872 list.insert( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), values.at( 2 ) );
6873 return convertToSameType( list, values.at( 0 ).type() );
6878 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6879 int position = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6881 position = position + list.length();
6882 if ( position >= 0 && position < list.length() )
6883 list.removeAt( position );
6884 return convertToSameType( list, values.at( 0 ).type() );
6892 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6894 const QVariant toRemove = values.at( 1 );
6897 list.erase( std::remove_if( list.begin(), list.end(), [](
const QVariant & element )
6899 return QgsVariantUtils::isNull( element );
6904 list.removeAll( toRemove );
6906 return convertToSameType( list, values.at( 0 ).type() );
6911 if ( values.count() == 2 && values.at( 1 ).type() == QVariant::Map )
6913 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
6915 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6916 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
6918 int index = list.indexOf( it.key() );
6919 while ( index >= 0 )
6921 list.replace( index, it.value() );
6922 index = list.indexOf( it.key() );
6926 return convertToSameType( list, values.at( 0 ).type() );
6928 else if ( values.count() == 3 )
6930 QVariantList before;
6932 bool isSingleReplacement =
false;
6934 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).type() != QVariant::StringList )
6936 before = QVariantList() << values.at( 1 );
6940 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
6943 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
6945 after = QVariantList() << values.at( 2 );
6946 isSingleReplacement =
true;
6950 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
6953 if ( !isSingleReplacement && before.length() != after.length() )
6955 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
6959 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6960 for (
int i = 0; i < before.length(); i++ )
6962 int index = list.indexOf( before.at( i ) );
6963 while ( index >= 0 )
6965 list.replace( index, after.at( isSingleReplacement ? 0 : i ) );
6966 index = list.indexOf( before.at( i ) );
6970 return convertToSameType( list, values.at( 0 ).type() );
6974 parent->
setEvalErrorString( QObject::tr(
"Function array_replace requires 2 or 3 arguments" ) );
6981 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6982 QVariantList list_new;
6984 for (
const QVariant &cur : QgsExpressionUtils::getListValue( values.at( 1 ), parent ) )
6986 while ( list.removeOne( cur ) )
6988 list_new.append( cur );
6992 list_new.append( list );
6994 return convertToSameType( list_new, values.at( 0 ).type() );
7000 for (
const QVariant &cur : values )
7002 list += QgsExpressionUtils::getListValue( cur, parent );
7004 return convertToSameType( list, values.at( 0 ).type() );
7009 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7010 int start_pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
7011 const int end_pos = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
7012 int slice_length = 0;
7014 if ( start_pos < 0 )
7016 start_pos = list.length() + start_pos;
7020 slice_length = end_pos - start_pos + 1;
7024 slice_length = list.length() + end_pos - start_pos + 1;
7027 if ( slice_length < 0 )
7031 list = list.mid( start_pos, slice_length );
7037 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7038 std::reverse( list.begin(), list.end() );
7044 const QVariantList array1 = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7045 const QVariantList array2 = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
7046 for (
const QVariant &cur : array2 )
7048 if ( array1.contains( cur ) )
7049 return QVariant(
true );
7051 return QVariant(
false );
7056 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7058 QVariantList distinct;
7060 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7062 if ( !distinct.contains( *it ) )
7064 distinct += ( *it );
7073 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7074 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7075 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7079 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7081 str += ( !( *it ).toString().isEmpty() ) ? ( *it ).toString() : empty;
7082 if ( it != ( array.constEnd() - 1 ) )
7088 return QVariant(
str );
7093 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7094 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7095 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7097 QStringList list =
str.split( delimiter );
7100 for ( QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
7102 array += ( !( *it ).isEmpty() ) ? *it : empty;
7110 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7111 QJsonDocument document = QJsonDocument::fromJson(
str.toUtf8() );
7112 if ( document.isNull() )
7115 return document.toVariant();
7121 QJsonDocument document = QJsonDocument::fromVariant( values.at( 0 ) );
7122 return QString( document.toJson( QJsonDocument::Compact ) );
7127 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7128 if (
str.isEmpty() )
7129 return QVariantMap();
7137 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7144 for (
int i = 0; i + 1 < values.length(); i += 2 )
7146 result.insert( QgsExpressionUtils::getStringValue( values.at( i ), parent ), values.at( i + 1 ) );
7153 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7154 const QString prefix = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7155 QVariantMap resultMap;
7157 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7159 resultMap.insert( QString( it.key() ).prepend( prefix ), it.value() );
7167 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).value( values.at( 1 ).toString() );
7172 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).contains( values.at( 1 ).toString() );
7177 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7178 map.remove( values.at( 1 ).toString() );
7184 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7185 map.insert( values.at( 1 ).toString(), values.at( 2 ) );
7192 for (
const QVariant &cur : values )
7194 const QVariantMap curMap = QgsExpressionUtils::getMapValue( cur, parent );
7195 for ( QVariantMap::const_iterator it = curMap.constBegin(); it != curMap.constEnd(); ++it )
7196 result.insert( it.key(), it.value() );
7203 return QStringList( QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).keys() );
7208 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).values();
7213 const QString envVarName = values.at( 0 ).toString();
7214 if ( !QProcessEnvironment::systemEnvironment().contains( envVarName ) )
7217 return QProcessEnvironment::systemEnvironment().value( envVarName );
7222 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7225 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"base_file_name" ) ) );
7228 return QFileInfo( file ).completeBaseName();
7233 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7236 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_suffix" ) ) );
7239 return QFileInfo( file ).completeSuffix();
7244 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7247 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_exists" ) ) );
7250 return QFileInfo::exists( file );
7255 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7258 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_name" ) ) );
7261 return QFileInfo( file ).fileName();
7266 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7269 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_file" ) ) );
7272 return QFileInfo( file ).isFile();
7277 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7280 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_directory" ) ) );
7283 return QFileInfo( file ).isDir();
7288 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7291 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_path" ) ) );
7294 return QDir::toNativeSeparators( QFileInfo( file ).path() );
7299 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7302 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_size" ) ) );
7305 return QFileInfo( file ).size();
7308static QVariant fcnHash(
const QString &
str,
const QCryptographicHash::Algorithm
algorithm )
7310 return QString( QCryptographicHash::hash(
str.toUtf8(),
algorithm ).toHex() );
7316 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7317 QString method = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).toLower();
7319 if ( method == QLatin1String(
"md4" ) )
7321 hash = fcnHash(
str, QCryptographicHash::Md4 );
7323 else if ( method == QLatin1String(
"md5" ) )
7325 hash = fcnHash(
str, QCryptographicHash::Md5 );
7327 else if ( method == QLatin1String(
"sha1" ) )
7329 hash = fcnHash(
str, QCryptographicHash::Sha1 );
7331 else if ( method == QLatin1String(
"sha224" ) )
7333 hash = fcnHash(
str, QCryptographicHash::Sha224 );
7335 else if ( method == QLatin1String(
"sha256" ) )
7337 hash = fcnHash(
str, QCryptographicHash::Sha256 );
7339 else if ( method == QLatin1String(
"sha384" ) )
7341 hash = fcnHash(
str, QCryptographicHash::Sha384 );
7343 else if ( method == QLatin1String(
"sha512" ) )
7345 hash = fcnHash(
str, QCryptographicHash::Sha512 );
7347 else if ( method == QLatin1String(
"sha3_224" ) )
7349 hash = fcnHash(
str, QCryptographicHash::Sha3_224 );
7351 else if ( method == QLatin1String(
"sha3_256" ) )
7353 hash = fcnHash(
str, QCryptographicHash::Sha3_256 );
7355 else if ( method == QLatin1String(
"sha3_384" ) )
7357 hash = fcnHash(
str, QCryptographicHash::Sha3_384 );
7359 else if ( method == QLatin1String(
"sha3_512" ) )
7361 hash = fcnHash(
str, QCryptographicHash::Sha3_512 );
7363 else if ( method == QLatin1String(
"keccak_224" ) )
7365 hash = fcnHash(
str, QCryptographicHash::Keccak_224 );
7367 else if ( method == QLatin1String(
"keccak_256" ) )
7369 hash = fcnHash(
str, QCryptographicHash::Keccak_256 );
7371 else if ( method == QLatin1String(
"keccak_384" ) )
7373 hash = fcnHash(
str, QCryptographicHash::Keccak_384 );
7375 else if ( method == QLatin1String(
"keccak_512" ) )
7377 hash = fcnHash(
str, QCryptographicHash::Keccak_512 );
7381 parent->
setEvalErrorString( QObject::tr(
"Hash method %1 is not available on this system." ).arg(
str ) );
7388 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Md5 );
7393 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Sha256 );
7398 const QByteArray input = values.at( 0 ).toByteArray();
7399 return QVariant( QString( input.toBase64() ) );
7404 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7406 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7408 query.addQueryItem( it.key(), it.value().toString() );
7410 return query.toString( QUrl::ComponentFormattingOption::FullyEncoded );
7415 const QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7416 const QByteArray base64 = value.toLocal8Bit();
7417 const QByteArray decoded = QByteArray::fromBase64( base64 );
7418 return QVariant( decoded );
7423static 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 )
7426 const QVariant sourceLayerRef = context->
variable( QStringLiteral(
"layer" ) );
7429 QgsVectorLayer *sourceLayer = QgsExpressionUtils::getVectorLayer( sourceLayerRef, context, parent );
7438 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
7441 const bool layerCanBeCached = node->
isStatic( parent, context );
7442 QVariant targetLayerValue = node->
eval( parent, context );
7446 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
7448 QString subExpString = node->dump();
7450 bool testOnly = ( subExpString ==
"NULL" );
7453 QgsVectorLayer *targetLayer = QgsExpressionUtils::getVectorLayer( targetLayerValue, context, parent );
7457 parent->
setEvalErrorString( QObject::tr(
"Layer '%1' could not be loaded." ).arg( targetLayerValue.toString() ) );
7462 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
7464 QString filterString = node->dump();
7465 if ( filterString !=
"NULL" )
7467 request.setFilterExpression( filterString );
7471 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
7473 QVariant limitValue = node->eval( parent, context );
7475 qlonglong limit = QgsExpressionUtils::getIntValue( limitValue, parent );
7478 double max_distance = 0;
7479 if ( isNearestFunc )
7481 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
7483 QVariant distanceValue = node->eval( parent, context );
7485 max_distance = QgsExpressionUtils::getDoubleValue( distanceValue, parent );
7489 node = QgsExpressionUtils::getNode( values.at( isNearestFunc ? 5 : 4 ), parent );
7491 QVariant cacheValue = node->eval( parent, context );
7493 bool cacheEnabled = cacheValue.toBool();
7499 double minOverlap { -1 };
7500 double minInscribedCircleRadius { -1 };
7501 bool returnDetails =
false;
7502 bool sortByMeasure =
false;
7503 bool sortAscending =
false;
7504 bool requireMeasures =
false;
7505 bool overlapOrRadiusFilter =
false;
7506 if ( isIntersectsFunc )
7509 node = QgsExpressionUtils::getNode( values.at( 5 ), parent );
7511 const QVariant minOverlapValue = node->eval( parent, context );
7513 minOverlap = QgsExpressionUtils::getDoubleValue( minOverlapValue, parent );
7514 node = QgsExpressionUtils::getNode( values.at( 6 ), parent );
7516 const QVariant minInscribedCircleRadiusValue = node->eval( parent, context );
7518 minInscribedCircleRadius = QgsExpressionUtils::getDoubleValue( minInscribedCircleRadiusValue, parent );
7519 node = QgsExpressionUtils::getNode( values.at( 7 ), parent );
7521 returnDetails = !testOnly && node->eval( parent, context ).toBool();
7522 node = QgsExpressionUtils::getNode( values.at( 8 ), parent );
7524 const QString sorting { node->eval( parent, context ).toString().toLower() };
7525 sortByMeasure = !testOnly && ( sorting.startsWith(
"asc" ) || sorting.startsWith(
"des" ) );
7526 sortAscending = sorting.startsWith(
"asc" );
7527 requireMeasures = sortByMeasure || returnDetails;
7528 overlapOrRadiusFilter = minInscribedCircleRadius != -1 || minOverlap != -1;
7535 if ( sourceLayer && targetLayer->crs() != sourceLayer->crs() )
7538 request.setDestinationCrs( sourceLayer->crs(), TransformContext );
7541 bool sameLayers = ( sourceLayer && sourceLayer->id() == targetLayer->id() );
7544 if ( bboxGrow != 0 )
7546 intDomain.
grow( bboxGrow );
7549 const QString cacheBase { QStringLiteral(
"%1:%2:%3" ).arg( targetLayer->id(), subExpString, filterString ) };
7555 QList<QgsFeature> features;
7556 if ( isNearestFunc || ( layerCanBeCached && cacheEnabled ) )
7560 const QString cacheLayer { QStringLiteral(
"ovrlaylyr:%1" ).arg( cacheBase ) };
7561 const QString cacheIndex { QStringLiteral(
"ovrlayidx:%1" ).arg( cacheBase ) };
7565 cachedTarget = targetLayer->
materialize( request );
7566 if ( layerCanBeCached )
7567 context->
setCachedValue( cacheLayer, QVariant::fromValue( cachedTarget ) );
7577 if ( layerCanBeCached )
7578 context->
setCachedValue( cacheIndex, QVariant::fromValue( spatialIndex ) );
7585 QList<QgsFeatureId> fidsList;
7586 if ( isNearestFunc )
7588 fidsList = spatialIndex.
nearestNeighbor( geometry, sameLayers ? limit + 1 : limit, max_distance );
7592 fidsList = spatialIndex.
intersects( intDomain );
7595 QListIterator<QgsFeatureId> i( fidsList );
7596 while ( i.hasNext() )
7599 if ( sameLayers && feat.
id() == fId2 )
7601 features.append( cachedTarget->
getFeature( fId2 ) );
7609 request.setFilterRect( intDomain );
7614 if ( sameLayers && feat.
id() == feat2.
id() )
7616 features.append( feat2 );
7624 const QString expCacheKey { QStringLiteral(
"exp:%1" ).arg( cacheBase ) };
7625 const QString ctxCacheKey { QStringLiteral(
"ctx:%1" ).arg( cacheBase ) };
7631 subExpression.
prepare( &subContext );
7644 auto testLinestring = [ = ](
const QgsGeometry intersection,
double & overlapValue ) ->
bool
7646 bool testResult {
false };
7648 QVector<double> overlapValues;
7651 const QgsCurve *geom = qgsgeometry_cast< const QgsCurve * >( *it );
7653 if ( minOverlap != -1 || requireMeasures )
7655 overlapValue = geom->
length();
7656 overlapValues.append( overlapValue );
7657 if ( minOverlap != -1 )
7659 if ( overlapValue >= minOverlap )
7671 if ( ! overlapValues.isEmpty() )
7673 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
7680 auto testPolygon = [ = ](
const QgsGeometry intersection,
double & radiusValue,
double & overlapValue ) ->
bool
7683 bool testResult {
false };
7685 QVector<double> overlapValues;
7686 QVector<double> radiusValues;
7689 const QgsCurvePolygon *geom = qgsgeometry_cast< const QgsCurvePolygon * >( *it );
7691 if ( minOverlap != -1 || requireMeasures )
7693 overlapValue = geom->
area();
7694 overlapValues.append( geom->
area() );
7695 if ( minOverlap != - 1 )
7697 if ( overlapValue >= minOverlap )
7709 if ( minInscribedCircleRadius != -1 || requireMeasures )
7712 const double width = bbox.
width();
7713 const double height = bbox.
height();
7714 const double size = width > height ? width : height;
7715 const double tolerance = size / 100.0;
7717 testResult = radiusValue >= minInscribedCircleRadius;
7718 radiusValues.append( radiusValues );
7723 if ( !radiusValues.isEmpty() )
7725 radiusValue = *std::max_element( radiusValues.cbegin(), radiusValues.cend() );
7728 if ( ! overlapValues.isEmpty() )
7730 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
7740 QVariantList results;
7742 QListIterator<QgsFeature> i( features );
7743 while ( i.hasNext() && ( sortByMeasure || limit == -1 || foundCount < limit ) )
7749 if ( ! relationFunction || ( geometry.*relationFunction )( feat2.
geometry() ) )
7752 double overlapValue = -1;
7753 double radiusValue = -1;
7755 if ( isIntersectsFunc && ( requireMeasures || overlapOrRadiusFilter ) )
7762 switch ( intersection.
type() )
7765 case Qgis::GeometryType::Polygon:
7769 bool testResult { testPolygon( intersection, radiusValue, overlapValue ) };
7771 if ( ! testResult && overlapOrRadiusFilter )
7779 case Qgis::GeometryType::Line:
7784 if ( minInscribedCircleRadius != -1 )
7790 const bool testResult { testLinestring( intersection, overlapValue ) };
7792 if ( ! testResult && overlapOrRadiusFilter )
7800 case Qgis::GeometryType::Point:
7805 if ( minInscribedCircleRadius != -1 )
7810 bool testResult {
false };
7811 if ( minOverlap != -1 || requireMeasures )
7819 if ( geometry.
type() == Qgis::GeometryType::Point )
7823 case Qgis::GeometryType::Unknown:
7824 case Qgis::GeometryType::Null:
7825 case Qgis::GeometryType::Point:
7829 case Qgis::GeometryType::Line:
7831 testResult = testLinestring( feat2.
geometry(), overlapValue );
7834 case Qgis::GeometryType::Polygon:
7836 testResult = testPolygon( feat2.
geometry(), radiusValue, overlapValue );
7842 if ( ! testResult && overlapOrRadiusFilter )
7851 case Qgis::GeometryType::Null:
7852 case Qgis::GeometryType::Unknown:
7870 const QVariant expResult = subExpression.
evaluate( &subContext );
7872 if ( requireMeasures )
7874 QVariantMap resultRecord;
7875 resultRecord.insert( QStringLiteral(
"id" ), feat2.
id() );
7876 resultRecord.insert( QStringLiteral(
"result" ), expResult );
7878 resultRecord.insert( QStringLiteral(
"overlap" ), overlapValue );
7880 if ( radiusValue != -1 )
7882 resultRecord.insert( QStringLiteral(
"radius" ), radiusValue );
7884 results.append( resultRecord );
7888 results.append( expResult );
7894 results.append( feat2.
id() );
7908 if ( requireMeasures )
7910 if ( sortByMeasure )
7912 std::sort( results.begin(), results.end(), [ sortAscending ](
const QVariant & recordA,
const QVariant & recordB ) ->
bool
7914 return sortAscending ?
7915 recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble()
7916 : recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble();
7920 if ( limit > 0 && results.size() > limit )
7922 results.erase( results.begin() + limit );
7925 if ( ! returnDetails )
7927 QVariantList expResults;
7928 for (
auto it = results.constBegin(); it != results.constEnd(); ++it )
7930 expResults.append( it->toMap().value( QStringLiteral(
"result" ) ) );
7940 QVariantList disjoint_results;
7949 if ( !results.contains( feat2.
id() ) )
7952 disjoint_results.append( subExpression.
evaluate( &subContext ) );
7955 return disjoint_results;
7998 return executeGeomOverlay( values, context, parent,
nullptr,
false, 0,
true );
8007 static QRecursiveMutex sFunctionsMutex;
8008 QMutexLocker locker( &sFunctionsMutex );
8010 QList<QgsExpressionFunction *> &functions = *sFunctions();
8012 if ( functions.isEmpty() )
8049 functions << randFunc;
8053 functions << randfFunc;
8056 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max" ), -1, fcnMax, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8057 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min" ), -1, fcnMin, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8064 <<
new QgsStaticExpressionFunction( QStringLiteral(
"pi" ), 0, fcnPi, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$pi" ) )
8068 <<
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" ) )
8069 <<
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" ) )
8070 <<
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" ) )
8075 <<
new QgsStaticExpressionFunction( QStringLiteral(
"coalesce" ), -1, fcnCoalesce, QStringLiteral(
"Conditionals" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8089 QStringLiteral(
"Aggregates" ),
8098 if ( !node->
args() )
8101 QSet<QString> referencedVars;
8104 QgsExpressionNode *subExpressionNode = node->args()->at( 2 );
8105 referencedVars = subExpressionNode->referencedVariables();
8110 QgsExpressionNode *filterNode = node->args()->at( 3 );
8111 referencedVars.unite( filterNode->referencedVariables() );
8113 return referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() );
8122 if ( !node->
args() )
8123 return QSet<QString>();
8125 QSet<QString> referencedCols;
8126 QSet<QString> referencedVars;
8141 if ( referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() ) )
8144 return referencedCols;
8157 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count" ), aggParams, fcnAggregateCount, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8158 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_distinct" ), aggParams, fcnAggregateCountDistinct, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8159 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_missing" ), aggParams, fcnAggregateCountMissing, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8160 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minimum" ), aggParams, fcnAggregateMin, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8161 <<
new QgsStaticExpressionFunction( QStringLiteral(
"maximum" ), aggParams, fcnAggregateMax, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8162 <<
new QgsStaticExpressionFunction( QStringLiteral(
"sum" ), aggParams, fcnAggregateSum, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8163 <<
new QgsStaticExpressionFunction( QStringLiteral(
"mean" ), aggParams, fcnAggregateMean, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8164 <<
new QgsStaticExpressionFunction( QStringLiteral(
"median" ), aggParams, fcnAggregateMedian, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8165 <<
new QgsStaticExpressionFunction( QStringLiteral(
"stdev" ), aggParams, fcnAggregateStdev, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8166 <<
new QgsStaticExpressionFunction( QStringLiteral(
"range" ), aggParams, fcnAggregateRange, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8167 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minority" ), aggParams, fcnAggregateMinority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8168 <<
new QgsStaticExpressionFunction( QStringLiteral(
"majority" ), aggParams, fcnAggregateMajority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8169 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q1" ), aggParams, fcnAggregateQ1, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8170 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q3" ), aggParams, fcnAggregateQ3, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8171 <<
new QgsStaticExpressionFunction( QStringLiteral(
"iqr" ), aggParams, fcnAggregateIQR, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8172 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min_length" ), aggParams, fcnAggregateMinLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8173 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max_length" ), aggParams, fcnAggregateMaxLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8174 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect" ), aggParams, fcnAggregateCollectGeometry, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8175 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate" ), aggParamsConcat, fcnAggregateStringConcat, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8176 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate_unique" ), aggParamsConcat, fcnAggregateStringConcatUnique, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8177 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array_agg" ), aggParamsArray, fcnAggregateArray, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8182 <<
new QgsStaticExpressionFunction( QStringLiteral(
"now" ), 0, fcnNow, QStringLiteral(
"Date and Time" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$now" ) )
8185 fcnAge, QStringLiteral(
"Date and Time" ) )
8199 fcnMakeDate, QStringLiteral(
"Date and Time" ) )
8203 fcnMakeTime, QStringLiteral(
"Date and Time" ) )
8210 fcnMakeDateTime, QStringLiteral(
"Date and Time" ) )
8218 fcnMakeInterval, QStringLiteral(
"Date and Time" ) )
8243 false, QSet< QString >(),
false, QStringList(), true )
8244 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concat" ), -1, fcnConcat, QStringLiteral(
"String" ), QString(),
false, QSet<QString>(),
false, QStringList(), true )
8262 fcnColorMixRgb, QStringLiteral(
"Color" ) )
8266 fcnColorRgb, QStringLiteral(
"Color" ) )
8271 fncColorRgba, QStringLiteral(
"Color" ) )
8277 fcnCreateRamp, QStringLiteral(
"Color" ) )
8281 fcnColorHsl, QStringLiteral(
"Color" ) )
8286 fncColorHsla, QStringLiteral(
"Color" ) )
8290 fcnColorHsv, QStringLiteral(
"Color" ) )
8295 fncColorHsva, QStringLiteral(
"Color" ) )
8300 fcnColorCmyk, QStringLiteral(
"Color" ) )
8306 fncColorCmyka, QStringLiteral(
"Color" ) )
8309 fncColorPart, QStringLiteral(
"Color" ) )
8312 fncDarker, QStringLiteral(
"Color" ) )
8315 fncLighter, QStringLiteral(
"Color" ) )
8320 fcnBaseFileName, QStringLiteral(
"Files and Paths" ) )
8322 fcnFileSuffix, QStringLiteral(
"Files and Paths" ) )
8324 fcnFileExists, QStringLiteral(
"Files and Paths" ) )
8326 fcnFileName, QStringLiteral(
"Files and Paths" ) )
8328 fcnPathIsFile, QStringLiteral(
"Files and Paths" ) )
8330 fcnPathIsDir, QStringLiteral(
"Files and Paths" ) )
8332 fcnFilePath, QStringLiteral(
"Files and Paths" ) )
8334 fcnFileSize, QStringLiteral(
"Files and Paths" ) )
8337 fcnExif, QStringLiteral(
"Files and Paths" ) )
8339 fcnExifGeoTag, QStringLiteral(
"GeometryGroup" ) )
8343 fcnGenericHash, QStringLiteral(
"Conversions" ) )
8345 fcnHashMd5, QStringLiteral(
"Conversions" ) )
8347 fcnHashSha256, QStringLiteral(
"Conversions" ) )
8351 fcnToBase64, QStringLiteral(
"Conversions" ) )
8353 fcnFromBase64, QStringLiteral(
"Conversions" ) )
8359 geomFunc->setIsStatic(
false );
8360 functions << geomFunc;
8364 functions << areaFunc;
8370 functions << lengthFunc;
8374 functions << perimeterFunc;
8380 fcnRoundness, QStringLiteral(
"GeometryGroup" ) );
8394 QMap< QString, QgsExpressionFunction::FcnEval > geometry_overlay_definitions
8396 { QStringLiteral(
"overlay_intersects" ), fcnGeomOverlayIntersects },
8397 { QStringLiteral(
"overlay_contains" ), fcnGeomOverlayContains },
8398 { QStringLiteral(
"overlay_crosses" ), fcnGeomOverlayCrosses },
8399 { QStringLiteral(
"overlay_equals" ), fcnGeomOverlayEquals },
8400 { QStringLiteral(
"overlay_touches" ), fcnGeomOverlayTouches },
8401 { QStringLiteral(
"overlay_disjoint" ), fcnGeomOverlayDisjoint },
8402 { QStringLiteral(
"overlay_within" ), fcnGeomOverlayWithin },
8404 QMapIterator< QString, QgsExpressionFunction::FcnEval > i( geometry_overlay_definitions );
8405 while ( i.hasNext() )
8422 functions << fcnGeomOverlayFunc;
8435 functions << fcnGeomOverlayNearestFunc;
8448 fcnNodesToPoints, QStringLiteral(
"GeometryGroup" ) )
8450 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect_geometries" ), -1, fcnCollectGeometries, QStringLiteral(
"GeometryGroup" ) )
8455 fcnMakePointM, QStringLiteral(
"GeometryGroup" ) )
8461 fcnMakeTriangle, QStringLiteral(
"GeometryGroup" ) )
8466 fcnMakeCircle, QStringLiteral(
"GeometryGroup" ) )
8473 fcnMakeEllipse, QStringLiteral(
"GeometryGroup" ) )
8479 fcnMakeRegularPolygon, QStringLiteral(
"GeometryGroup" ) )
8483 fcnMakeSquare, QStringLiteral(
"GeometryGroup" ) )
8489 fcnMakeRectangleFrom3Points, QStringLiteral(
"GeometryGroup" ) )
8493#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
8499 }, fcnGeomMakeValid, QStringLiteral(
"GeometryGroup" ) );
8508 functions << xAtFunc;
8513 functions << yAtFunc;
8529 fcnDisjoint, QStringLiteral(
"GeometryGroup" ) )
8532 fcnIntersects, QStringLiteral(
"GeometryGroup" ) )
8535 fcnTouches, QStringLiteral(
"GeometryGroup" ) )
8538 fcnCrosses, QStringLiteral(
"GeometryGroup" ) )
8541 fcnContains, QStringLiteral(
"GeometryGroup" ) )
8544 fcnOverlaps, QStringLiteral(
"GeometryGroup" ) )
8547 fcnWithin, QStringLiteral(
"GeometryGroup" ) )
8551 fcnTranslate, QStringLiteral(
"GeometryGroup" ) )
8556 fcnRotate, QStringLiteral(
"GeometryGroup" ) )
8561 fcnScale, QStringLiteral(
"GeometryGroup" ) )
8572 fcnAffineTransform, QStringLiteral(
"GeometryGroup" ) )
8579 fcnBuffer, QStringLiteral(
"GeometryGroup" ) )
8581 fcnForceRHR, QStringLiteral(
"GeometryGroup" ) )
8583 fcnForcePolygonCW, QStringLiteral(
"GeometryGroup" ) )
8585 fcnForcePolygonCCW, QStringLiteral(
"GeometryGroup" ) )
8595 , fcnTaperedBuffer, QStringLiteral(
"GeometryGroup" ) )
8598 , fcnBufferByM, QStringLiteral(
"GeometryGroup" ) )
8604 fcnOffsetCurve, QStringLiteral(
"GeometryGroup" ) )
8610 fcnSingleSidedBuffer, QStringLiteral(
"GeometryGroup" ) )
8614 fcnExtend, QStringLiteral(
"GeometryGroup" ) )
8623 fcnInteriorRingN, QStringLiteral(
"GeometryGroup" ) )
8626 fcnGeometryN, QStringLiteral(
"GeometryGroup" ) )
8633 }, fcnSharedPaths, QStringLiteral(
"GeometryGroup" ) )
8647 }, fcnTriangularWave, QStringLiteral(
"GeometryGroup" ) )
8656 }, fcnTriangularWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
8663 }, fcnSquareWave, QStringLiteral(
"GeometryGroup" ) )
8672 }, fcnSquareWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
8679 }, fcnRoundWave, QStringLiteral(
"GeometryGroup" ) )
8688 }, fcnRoundWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
8697 }, fcnApplyDashPattern, QStringLiteral(
"GeometryGroup" ) )
8702 }, fcnDensifyByCount, QStringLiteral(
"GeometryGroup" ) )
8707 }, fcnDensifyByDistance, QStringLiteral(
"GeometryGroup" ) )
8719#
if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
8726 fcnOrientedBBox, QStringLiteral(
"GeometryGroup" ) )
8729 fcnMainAngle, QStringLiteral(
"GeometryGroup" ) )
8733 fcnMinimalCircle, QStringLiteral(
"GeometryGroup" ) )
8736 fcnDifference, QStringLiteral(
"GeometryGroup" ) )
8739 fcnDistance, QStringLiteral(
"GeometryGroup" ) )
8742 fcnHausdorffDistance, QStringLiteral(
"GeometryGroup" ) )
8745 fcnIntersection, QStringLiteral(
"GeometryGroup" ) )
8748 fcnSymDifference, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"symDifference" ) )
8751 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
8754 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
8757 fcnGeomToWKT, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"geomToWKT" ) )
8759 fcnGeomToWKB, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false )
8764 fcnTransformGeometry, QStringLiteral(
"GeometryGroup" ) )
8768 fcnExtrude, QStringLiteral(
"GeometryGroup" ), QString() )
8770 fcnGeomIsMultipart, QStringLiteral(
"GeometryGroup" ) )
8772 fcnZMax, QStringLiteral(
"GeometryGroup" ) )
8774 fcnZMin, QStringLiteral(
"GeometryGroup" ) )
8776 fcnMMax, QStringLiteral(
"GeometryGroup" ) )
8778 fcnMMin, QStringLiteral(
"GeometryGroup" ) )
8780 fcnSinuosity, QStringLiteral(
"GeometryGroup" ) )
8782 fcnStraightDistance2d, QStringLiteral(
"GeometryGroup" ) );
8788 fcnOrderParts, QStringLiteral(
"GeometryGroup" ), QString() );
8793 const QList< QgsExpressionNode *> argList = node->
args()->list();
8796 if ( !argNode->isStatic( parent, context ) )
8802 QgsExpressionNode *argNode = node->args()->at( 1 );
8804 QString expString = argNode->eval( parent, context ).toString();
8806 QgsExpression e( expString );
8808 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
8819 QgsExpressionNode *argNode = node->args()->at( 1 );
8820 QString expression = argNode->eval( parent, context ).toString();
8821 QgsExpression e( expression );
8822 e.prepare( context );
8823 context->setCachedValue( expression, QVariant::fromValue( e ) );
8828 functions << orderPartsFunc;
8833 fcnClosestPoint, QStringLiteral(
"GeometryGroup" ) )
8836 fcnShortestLine, QStringLiteral(
"GeometryGroup" ) )
8855 functions << idFunc;
8859 functions << currentFeatureFunc;
8861 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" ) );
8863 functions << uuidFunc;
8870 fcnGetFeature, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"QgsExpressionUtils::getFeature" ) )
8873 fcnGetFeatureById, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false );
8878 functions << attributesFunc;
8882 functions << representAttributesFunc;
8890 functions << validateFeature;
8899 functions << validateAttribute;
8902 QStringLiteral(
"maptip" ),
8905 QStringLiteral(
"Record and Attributes" ),
8911 functions << maptipFunc;
8914 QStringLiteral(
"display_expression" ),
8916 fcnFeatureDisplayExpression,
8917 QStringLiteral(
"Record and Attributes" ),
8923 functions << displayFunc;
8926 QStringLiteral(
"is_selected" ),
8929 QStringLiteral(
"Record and Attributes" ),
8935 functions << isSelectedFunc;
8939 QStringLiteral(
"num_selected" ),
8942 QStringLiteral(
"Record and Attributes" ),
8950 QStringLiteral(
"sqlite_fetch_and_increment" ),
8958 fcnSqliteFetchAndIncrement,
8959 QStringLiteral(
"Record and Attributes" )
8977 parent->
setEvalErrorString( tr(
"If represent_value is called with 1 parameter, it must be an attribute." ) );
8987 parent->
setEvalErrorString( tr(
"represent_value must be called with exactly 1 or 2 parameters." ) );
8993 functions << representValueFunc;
8999 fcnGetLayerProperty, QStringLiteral(
"Map Layers" ) )
9004 fcnDecodeUri, QStringLiteral(
"Map Layers" ) )
9008 fcnMimeType, QStringLiteral(
"General" ) )
9025 QgsExpressionNode *argNode = node->args()->at( 0 );
9027 if ( !argNode->isStatic( parent, context ) )
9030 const QString varName = argNode->eval( parent, context ).toString();
9031 if ( varName == QLatin1String(
"feature" ) || varName == QLatin1String(
"id" ) || varName == QLatin1String(
"geometry" ) )
9034 const QgsExpressionContextScope *scope = context->activeScopeForVariable( varName );
9035 return scope ? scope->isStatic( varName ) : false;
9043 if ( node && node->
args()->
count() > 0 )
9045 QgsExpressionNode *argNode = node->args()->at( 0 );
9046 if ( QgsExpressionNodeLiteral *literal = dynamic_cast<QgsExpressionNodeLiteral *>( argNode ) )
9048 if ( literal->value() == QLatin1String(
"geometry" ) || literal->value() == QLatin1String(
"feature" ) )
9067 QgsExpressionNode *argNode = node->args()->at( 0 );
9069 if ( argNode->isStatic( parent, context ) )
9071 QString expString = argNode->eval( parent, context ).toString();
9073 QgsExpression e( expString );
9075 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9083 functions << evalFunc;
9089 const QList< QgsExpressionNode *> argList = node->
args()->list();
9092 if ( !argNode->isStatic( parent, context ) )
9104 functions << attributeFunc;
9115 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array" ), -1, fcnArray, QStringLiteral(
"Arrays" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
9164 fcnMapPrefixKeys, QStringLiteral(
"Maps" ) )
9166 fcnMapToHtmlTable, QStringLiteral(
"Maps" ) )
9168 fcnMapToHtmlDefinitionList, QStringLiteral(
"Maps" ) )
9170 fcnToFormUrlEncode, QStringLiteral(
"Maps" ) )
9179 *sOwnedFunctions() << func;
9180 *sBuiltinFunctions() << func->name();
9181 sBuiltinFunctions()->append( func->aliases() );
9194 sFunctions()->append( function );
9195 if ( transferOwnership )
9196 sOwnedFunctions()->append( function );
9210 sFunctions()->removeAt( fnIdx );
9218 qDeleteAll( *sOwnedFunctions() );
9219 sOwnedFunctions()->clear();
9224 if ( sBuiltinFunctions()->isEmpty() )
9228 return *sBuiltinFunctions();
9236 QStringLiteral(
"Arrays" ) )
9247 if ( args->
count() < 2 )
9250 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9260 QVariantList result;
9262 if ( args->
count() < 2 )
9266 QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9269 std::unique_ptr< QgsExpressionContext > tempContext;
9272 tempContext = std::make_unique< QgsExpressionContext >();
9273 subContext = tempContext.get();
9279 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
9282 result << args->
at( 1 )->
eval( parent, subContext );
9307 if ( args->
count() < 2 )
9311 args->
at( 0 )->
prepare( parent, context );
9315 subContext = *context;
9321 args->
at( 1 )->
prepare( parent, &subContext );
9331 QStringLiteral(
"Arrays" ) )
9342 if ( args->
count() < 2 )
9345 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9355 QVariantList result;
9357 if ( args->
count() < 2 )
9361 const QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9364 std::unique_ptr< QgsExpressionContext > tempContext;
9367 tempContext = std::make_unique< QgsExpressionContext >();
9368 subContext = tempContext.get();
9375 if ( args->
count() >= 3 )
9377 const QVariant limitVar = args->
at( 2 )->
eval( parent, context );
9379 if ( QgsExpressionUtils::isIntSafe( limitVar ) )
9381 limit = limitVar.toInt();
9389 for (
const QVariant &value : array )
9392 if ( args->
at( 1 )->
eval( parent, subContext ).toBool() )
9396 if ( limit > 0 && limit == result.size() )
9423 if ( args->
count() < 2 )
9427 args->
at( 0 )->
prepare( parent, context );
9431 subContext = *context;
9437 args->
at( 1 )->
prepare( parent, &subContext );
9446 QStringLiteral(
"General" ) )
9457 if ( args->
count() < 3 )
9461 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9463 QVariant
name = args->
at( 0 )->
eval( parent, context );
9464 QVariant value = args->
at( 1 )->
eval( parent, context );
9467 appendTemporaryVariable( context,
name.toString(), value );
9468 if ( args->
at( 2 )->
isStatic( parent, context ) )
9470 popTemporaryVariable( context );
9481 if ( args->
count() < 3 )
9485 QVariant
name = args->
at( 0 )->
eval( parent, context );
9486 QVariant value = args->
at( 1 )->
eval( parent, context );
9489 std::unique_ptr< QgsExpressionContext > tempContext;
9490 if ( !updatedContext )
9492 tempContext = std::make_unique< QgsExpressionContext >();
9493 updatedContext = tempContext.get();
9496 appendTemporaryVariable( updatedContext,
name.toString(), value );
9497 result = args->
at( 2 )->
eval( parent, updatedContext );
9500 popTemporaryVariable( updatedContext );
9521 if ( args->
count() < 3 )
9526 QVariant value = args->
at( 1 )->
prepare( parent, context );
9529 std::unique_ptr< QgsExpressionContext > tempContext;
9530 if ( !updatedContext )
9532 tempContext = std::make_unique< QgsExpressionContext >();
9533 updatedContext = tempContext.get();
9536 appendTemporaryVariable( updatedContext,
name.toString(), value );
9537 args->
at( 2 )->
prepare( parent, updatedContext );
9540 popTemporaryVariable( updatedContext );
9545void QgsWithVariableExpressionFunction::popTemporaryVariable(
const QgsExpressionContext *context )
const
9551void QgsWithVariableExpressionFunction::appendTemporaryVariable(
const QgsExpressionContext *context,
const QString &name,
const QVariant &value )
const
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.
JoinStyle
Join styles for buffers.
EndCapStyle
End cap styles for buffers.
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...
bool is3D() const SIP_HOLDGIL
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.
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 const QgsAbstractGeometry * simplifiedTypeRef() const SIP_HOLDGIL
Returns a reference to the simplest lossless representation of this geometry, e.g.
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.
Qgis::WkbType wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
part_iterator parts_begin()
Returns STL-style iterator pointing to the first part of the geometry.
bool isMeasure() const SIP_HOLDGIL
Returns true if the geometry contains m values.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
Aggregate
Available aggregates to calculate.
@ StringConcatenateUnique
Concatenate unique values with a joining string (string fields only). Specify the delimiter using set...
@ StringMaximumLength
Maximum length of string (string fields only)
@ ThirdQuartile
Third quartile (numeric fields only)
@ Range
Range of values (max - min) (numeric and datetime fields only)
@ ArrayAggregate
Create an array of values.
@ InterQuartileRange
Inter quartile range (IQR) (numeric fields only)
@ FirstQuartile
First quartile (numeric fields only)
@ Median
Median of values (numeric fields only)
@ GeometryCollect
Create a multipart geometry from aggregated geometries.
@ CountMissing
Number of missing (null) values.
@ StDevSample
Sample standard deviation of values (numeric fields only)
@ Majority
Majority of values.
@ StringConcatenate
Concatenate values with a joining string (string fields only). Specify the delimiter using setDelimit...
@ Mean
Mean of values (numeric fields only)
@ StringMinimumLength
Minimum length of string (string fields only)
@ CountDistinct
Number of distinct values.
@ Minority
Minority of values.
static 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.
Q_GADGET Qgis::DistanceUnit mapUnits
QString toProj() const
Returns a Proj string representation of this CRS.
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 ringCount(int part=0) const override SIP_HOLDGIL
Returns the number of rings of which this geometry is built.
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
const QgsCurve * interiorRing(int i) const SIP_HOLDGIL
Retrieves an interior ring from the curve polygon.
const QgsCurve * exteriorRing() const SIP_HOLDGIL
Returns the curve polygon's exterior ring.
double roundness() const
Returns the roundness of the curve polygon.
double area() const override SIP_HOLDGIL
Returns the planar, 2-dimensional area of the geometry.
int numInteriorRings() const SIP_HOLDGIL
Returns the number of interior rings contained with the curve polygon.
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 bool isClosed() const SIP_HOLDGIL
Returns true if the curve is closed.
virtual QgsCurve * curveSubstring(double startDistance, double endDistance) const =0
Returns a new curve representing a substring of this curve.
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 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()
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 QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required.
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
static const QStringList & BuiltinFunctions()
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value, QVariant::Type fieldType=QVariant::Type::Invalid)
Create an expression allowing to evaluate if a field is equal to a value.
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 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)
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 & 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 & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
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...
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
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.
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.
int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
int count() const
Returns number of items.
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).
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
int numGeometries() const SIP_HOLDGIL
Returns the number of geometries within the collection.
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.
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...
double lineLocatePoint(const QgsGeometry &point) const
Returns a distance representing the location along this linestring of the closest point on this lines...
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
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 concaveHull(double targetPercent, bool allowHoles=false) const SIP_THROW(QgsNotSupportedException)
Returns a possibly concave polygon that contains all the points in the geometry.
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.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
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 ...
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.
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
bool isMultipart() const SIP_HOLDGIL
Returns true if WKB of the geometry is of WKBMulti* type.
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.
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.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine representing the specified geometry.
double hausdorffDistance(const QgsGeometry &geom) const
Returns the Hausdorff distance between this geometry and geom.
QString lastError() const SIP_HOLDGIL
Returns an error string referring to the last error encountered either when this geometry was created...
QgsGeometry makeValid(Qgis::MakeValidMethod method=Qgis::MakeValidMethod::Linework, bool keepCollapsed=false) const SIP_THROW(QgsNotSupportedException)
Attempts to make an invalid geometry valid without losing vertices.
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...
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
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...
QString asWkt(int precision=17) const
Exports the geometry to WKT.
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.
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
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.
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
QgsCoordinateReferenceSystem crs
QString attribution() const
Returns the attribution of the layer used by QGIS Server in GetCapabilities request.
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
QgsLayerMetadata metadata
virtual bool isEditable() const
Returns true if the layer can be edited.
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.
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.
@ Visvalingam
The simplification gives each point in a line an importance weighting, so that least important points...
@ 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.
Point geometry type, with support for z-dimension and m-values.
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override SIP_HOLDGIL
Checks validity of the geometry, and returns true if the geometry is valid.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const SIP_HOLDGIL
Returns a new point which corresponds to this point projected by a specified distance with specified ...
double inclination(const QgsPoint &other) const SIP_HOLDGIL
Calculates Cartesian inclination between this point and other one (starting from zenith = 0 to nadir ...
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) SIP_HOLDGIL
Construct a QgsQuadrilateral as a square from a diagonal.
QgsPolygon * toPolygon(bool force2D=false) const
Returns the quadrilateral as a new polygon.
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...
static QgsQuadrilateral rectangleFrom3Points(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &p3, ConstructionOption mode) SIP_HOLDGIL
Construct a QgsQuadrilateral as a Rectangle from 3 points.
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 yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
void grow(double delta)
Grows the rectangle in place by the specified amount.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
QgsPointXY center() const SIP_HOLDGIL
Returns the center point 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.
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.
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()
Returns default application-wide style.
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
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)
Returns true if the specified variant should be considered a NULL value.
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.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
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
The editor widget setup defines which QgsFieldFormatter and editor widget will be used for the field ...
QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.
Q_INVOKABLE Qgis::GeometryType geometryType() const
Returns point, line or polygon.
QVariant aggregate(QgsAggregateCalculator::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.
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) SIP_HOLDGIL
Returns a display string for a geometry type.
static Qgis::WkbType flatType(Qgis::WkbType type) SIP_HOLDGIL
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.
CORE_EXPORT QgsMeshVertex centroid(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns the centroid of the face.
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
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.