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 QVariant result( QVariant::Double );
556 double maxVal = std::numeric_limits<double>::quiet_NaN();
557 for (
const QVariant &val : values )
560 if ( std::isnan( maxVal ) )
564 else if ( !std::isnan( testVal ) )
566 maxVal = std::max( maxVal, testVal );
570 if ( !std::isnan( maxVal ) )
572 result = QVariant( maxVal );
579 QVariant result( QVariant::Double );
580 double minVal = std::numeric_limits<double>::quiet_NaN();
581 for (
const QVariant &val : values )
584 if ( std::isnan( minVal ) )
588 else if ( !std::isnan( testVal ) )
590 minVal = std::min( minVal, testVal );
594 if ( !std::isnan( minVal ) )
596 result = QVariant( minVal );
608 QVariant value = node->
eval( parent, context );
613 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( value, context, parent );
617 parent->
setEvalErrorString( QObject::tr(
"Cannot find layer with name or ID '%1'" ).arg( value.toString() ) );
622 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
624 value = node->
eval( parent, context );
630 parent->
setEvalErrorString( QObject::tr(
"No such aggregate '%1'" ).arg( value.toString() ) );
635 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
637 QString subExpression = node->
dump();
641 if ( values.count() > 3 )
643 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
646 if ( !nl || nl->value().isValid() )
651 if ( values.count() > 4 )
653 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
655 value = node->
eval( parent, context );
662 if ( values.count() > 5 )
664 node = QgsExpressionUtils::getNode( values.at( 5 ), parent );
667 if ( !nl || nl->value().isValid() )
669 orderBy = node->
dump();
674 QString aggregateError;
682 bool isStatic =
true;
683 if ( filterExp.referencedVariables().contains( QStringLiteral(
"parent" ) )
684 || filterExp.referencedVariables().contains( QString() )
685 || subExp.referencedVariables().contains( QStringLiteral(
"parent" ) )
686 || subExp.referencedVariables().contains( QString() ) )
692 const QSet<QString> refVars = filterExp.referencedVariables() + subExp.referencedVariables();
693 for (
const QString &varName : refVars )
696 if ( scope && !scope->
isStatic( varName ) )
706 cacheKey = QStringLiteral(
"aggfcn:%1:%2:%3:%4:%5%6:%7" ).arg( vl->id(), QString::number( aggregate ), subExpression, parameters.
filter,
707 QString::number( context->
feature().
id() ), QString::number(
qHash( context->
feature() ) ), orderBy );
711 cacheKey = QStringLiteral(
"aggfcn:%1:%2:%3:%4:%5" ).arg( vl->id(), QString::number( aggregate ), subExpression, parameters.
filter, orderBy );
722 subContext.appendScope( subScope );
723 result = vl->aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &aggregateError );
735 result = vl->aggregate( aggregate, subExpression, parameters,
nullptr, &ok,
nullptr,
nullptr, &aggregateError );
739 if ( !aggregateError.isEmpty() )
740 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, aggregateError ) );
742 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
753 parent->
setEvalErrorString( QObject::tr(
"Cannot use relation aggregate function in this context" ) );
761 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
765 parent->
setEvalErrorString( QObject::tr(
"Cannot use relation aggregate function in this context" ) );
774 QVariant value = node->
eval( parent, context );
776 QString relationId = value.toString();
783 if ( relations.isEmpty() || relations.at( 0 ).referencedLayer() != vl )
785 parent->
setEvalErrorString( QObject::tr(
"Cannot find relation with id '%1'" ).arg( relationId ) );
790 relation = relations.at( 0 );
797 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
799 value = node->
eval( parent, context );
805 parent->
setEvalErrorString( QObject::tr(
"No such aggregate '%1'" ).arg( value.toString() ) );
810 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
812 QString subExpression = node->
dump();
816 if ( values.count() > 3 )
818 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
820 value = node->
eval( parent, context );
827 if ( values.count() > 4 )
829 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
832 if ( !nl || nl->value().isValid() )
834 orderBy = node->
dump();
845 QString cacheKey = QStringLiteral(
"relagg:%1:%2:%3:%4:%5" ).arg( vl->id(),
846 QString::number(
static_cast< int >( aggregate ) ),
859 result = childLayer->
aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &error );
863 if ( !error.isEmpty() )
864 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, error ) );
866 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
880 parent->
setEvalErrorString( QObject::tr(
"Cannot use aggregate function in this context" ) );
888 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
892 parent->
setEvalErrorString( QObject::tr(
"Cannot use aggregate function in this context" ) );
901 QString subExpression = node->
dump();
905 if ( values.count() > 1 )
907 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
910 if ( !nl || nl->value().isValid() )
911 groupBy = node->
dump();
915 if ( values.count() > 2 )
917 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
920 if ( !nl || nl->value().isValid() )
926 if ( orderByPos >= 0 && values.count() > orderByPos )
928 node = QgsExpressionUtils::getNode( values.at( orderByPos ), parent );
931 if ( !nl || nl->value().isValid() )
933 orderBy = node->
dump();
941 if ( !groupBy.isEmpty() )
944 QVariant groupByValue = groupByExp.evaluate( context );
945 QString groupByClause = QStringLiteral(
"%1 %2 %3" ).arg( groupBy,
948 if ( !parameters.
filter.isEmpty() )
949 parameters.
filter = QStringLiteral(
"(%1) AND (%2)" ).arg( parameters.
filter, groupByClause );
951 parameters.
filter = groupByClause;
957 bool isStatic =
true;
958 const QSet<QString> refVars = filterExp.referencedVariables() + subExp.referencedVariables();
959 for (
const QString &varName : refVars )
962 if ( scope && !scope->
isStatic( varName ) )
972 cacheKey = QStringLiteral(
"agg:%1:%2:%3:%4:%5%6:%7" ).arg( vl->id(), QString::number( aggregate ), subExpression, parameters.
filter,
973 QString::number( context->
feature().
id() ), QString::number(
qHash( context->
feature() ) ), orderBy );
977 cacheKey = QStringLiteral(
"agg:%1:%2:%3:%4:%5" ).arg( vl->id(), QString::number( aggregate ), subExpression, parameters.
filter, orderBy );
989 subContext.appendScope( subScope );
991 result = vl->aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &error );
995 if ( !error.isEmpty() )
996 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, error ) );
998 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
1103 if ( values.count() > 3 )
1105 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
1107 QVariant value = node->
eval( parent, context );
1109 parameters.
delimiter = value.toString();
1120 if ( values.count() > 3 )
1122 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
1124 QVariant value = node->
eval( parent, context );
1126 parameters.
delimiter = value.toString();
1142 QVariant scale = context->
variable( QStringLiteral(
"map_scale" ) );
1147 const double v = scale.toDouble( &ok );
1155 double minValue = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1156 double testValue = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1157 double maxValue = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1160 if ( testValue <= minValue )
1162 return QVariant( minValue );
1164 else if ( testValue >= maxValue )
1166 return QVariant( maxValue );
1170 return QVariant( testValue );
1176 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1177 return QVariant( std::floor( x ) );
1182 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1183 return QVariant( std::ceil( x ) );
1188 return QVariant( QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) );
1192 return QVariant( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) );
1196 return QVariant( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ) );
1201 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1202 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1203 if ( format.isEmpty() && !language.isEmpty() )
1205 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to DateTime when the language is specified" ) );
1206 return QVariant( QDateTime() );
1209 if ( format.isEmpty() && language.isEmpty() )
1210 return QVariant( QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent ) );
1212 QString datetimestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1213 QLocale locale = QLocale();
1214 if ( !language.isEmpty() )
1216 locale = QLocale( language );
1219 QDateTime datetime = locale.toDateTime( datetimestring, format );
1220 if ( !datetime.isValid() )
1222 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to DateTime" ).arg( datetimestring ) );
1223 datetime = QDateTime();
1225 return QVariant( datetime );
1230 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1231 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1232 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1234 const QDate date( year, month, day );
1235 if ( !date.isValid() )
1237 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1240 return QVariant( date );
1245 const int hours = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1246 const int minutes = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1247 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1249 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1250 if ( !time.isValid() )
1252 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1255 return QVariant( time );
1260 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1261 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1262 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1263 const int hours = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
1264 const int minutes = QgsExpressionUtils::getIntValue( values.at( 4 ), parent );
1265 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1267 const QDate date( year, month, day );
1268 if ( !date.isValid() )
1270 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1273 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1274 if ( !time.isValid() )
1276 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1279 return QVariant( QDateTime( date, time ) );
1284 const double years = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1285 const double months = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1286 const double weeks = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1287 const double days = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
1288 const double hours = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
1289 const double minutes = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1290 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
1292 return QVariant::fromValue(
QgsInterval( years, months, weeks, days, hours, minutes, seconds ) );
1297 for (
const QVariant &value : values )
1308 const QVariant val1 = values.at( 0 );
1309 const QVariant val2 = values.at( 1 );
1319 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1320 return QVariant(
str.toLower() );
1324 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1325 return QVariant(
str.toUpper() );
1329 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1330 QStringList elems =
str.split(
' ' );
1331 for (
int i = 0; i < elems.size(); i++ )
1333 if ( elems[i].size() > 1 )
1334 elems[i] = elems[i].at( 0 ).toUpper() + elems[i].mid( 1 ).toLower();
1336 return QVariant( elems.join( QLatin1Char(
' ' ) ) );
1341 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1342 return QVariant(
str.trimmed() );
1347 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1348 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1354 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1355 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1361 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1362 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1369 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1375 QChar character = QChar( QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent ) );
1376 return QVariant( QString( character ) );
1381 QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1383 if ( value.isEmpty() )
1388 int res = value.at( 0 ).unicode();
1389 return QVariant( res );
1394 if ( values.length() == 2 || values.length() == 3 )
1396 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1397 qlonglong wrap = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1399 QString customdelimiter = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1410 if ( values.at( 0 ).userType() == QMetaType::type(
"QgsGeometry" ) )
1413 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
1414 if ( geom.
type() != Qgis::GeometryType::Line )
1417 return QVariant( geom.
length() );
1421 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1422 return QVariant(
str.length() );
1427 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
1429 if ( geom.
type() != Qgis::GeometryType::Line )
1432 double totalLength = 0;
1435 if (
const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( *it ) )
1437 totalLength += line->length3D();
1441 std::unique_ptr< QgsLineString > segmentized( qgsgeometry_cast< const QgsCurve * >( *it )->curveToLine() );
1442 totalLength += segmentized->length3D();
1451 if ( values.count() == 2 && values.at( 1 ).type() == QVariant::Map )
1453 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1454 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
1455 QVector< QPair< QString, QString > > mapItems;
1457 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
1459 mapItems.append( qMakePair( it.key(), it.value().toString() ) );
1463 std::sort( mapItems.begin(),
1465 [](
const QPair< QString, QString > &pair1,
1466 const QPair< QString, QString > &pair2 )
1468 return ( pair1.first.length() > pair2.first.length() );
1471 for (
auto it = mapItems.constBegin(); it != mapItems.constEnd(); ++it )
1473 str =
str.replace( it->first, it->second );
1476 return QVariant(
str );
1478 else if ( values.count() == 3 )
1480 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1481 QVariantList before;
1483 bool isSingleReplacement =
false;
1485 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).type() != QVariant::StringList )
1487 before = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1491 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
1494 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
1496 after = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1497 isSingleReplacement =
true;
1501 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
1504 if ( !isSingleReplacement && before.length() != after.length() )
1506 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
1510 for (
int i = 0; i < before.length(); i++ )
1512 str =
str.replace( before.at( i ).toString(), after.at( isSingleReplacement ? 0 : i ).toString() );
1515 return QVariant(
str );
1519 parent->
setEvalErrorString( QObject::tr(
"Function replace requires 2 or 3 arguments" ) );
1526 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1527 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1528 QString after = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1530 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1531 if ( !re.isValid() )
1533 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1536 return QVariant(
str.replace( re, after ) );
1541 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1542 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1544 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1545 if ( !re.isValid() )
1547 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1550 return QVariant( (
str.indexOf( re ) + 1 ) );
1555 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1556 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1557 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1559 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1560 if ( !re.isValid() )
1562 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1566 QRegularExpressionMatch matches = re.match(
str );
1567 if ( matches.hasMatch() )
1570 QStringList list = matches.capturedTexts();
1573 for ( QStringList::const_iterator it = ++list.constBegin(); it != list.constEnd(); ++it )
1575 array += ( !( *it ).isEmpty() ) ? *it : empty;
1578 return QVariant( array );
1588 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1589 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1591 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1592 if ( !re.isValid() )
1594 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1599 QRegularExpressionMatch match = re.match(
str );
1600 if ( match.hasMatch() )
1603 if ( match.lastCapturedIndex() > 0 )
1606 return QVariant( match.captured( 1 ) );
1611 return QVariant( match.captured( 0 ) );
1616 return QVariant(
"" );
1622 QString uuid = QUuid::createUuid().toString();
1623 if ( values.at( 0 ).toString().compare( QStringLiteral(
"WithoutBraces" ), Qt::CaseInsensitive ) == 0 )
1624 uuid = QUuid::createUuid().toString( QUuid::StringFormat::WithoutBraces );
1625 else if ( values.at( 0 ).toString().compare( QStringLiteral(
"Id128" ), Qt::CaseInsensitive ) == 0 )
1626 uuid = QUuid::createUuid().toString( QUuid::StringFormat::Id128 );
1632 if ( !values.at( 0 ).isValid() || !values.at( 1 ).isValid() )
1635 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1636 int from = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1639 if ( values.at( 2 ).isValid() )
1640 len = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
1646 from =
str.size() + from;
1652 else if ( from > 0 )
1660 len =
str.size() + len - from;
1667 return QVariant(
str.mid( from, len ) );
1673 return QVariant(
static_cast< int >( f.
id() ) );
1678 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1679 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
1680 bool foundLayer =
false;
1681 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, geom](
QgsMapLayer * mapLayer )
1683 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer * >( mapLayer );
1684 if ( !layer || !layer->dataProvider() )
1686 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1690 if ( bandNb < 1 || bandNb > layer->bandCount() )
1692 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster band number." ) );
1696 if ( geom.
isNull() || geom.
type() != Qgis::GeometryType::Point )
1698 parent->setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid point geometry." ) );
1705 QgsMultiPointXY multiPoint = geom.asMultiPoint();
1706 if ( multiPoint.count() == 1 )
1708 point = multiPoint[0];
1717 double value = layer->dataProvider()->sample( point, bandNb );
1718 return std::isnan( value ) ? QVariant() : value;
1724 parent->
setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1735 const int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1736 const double value = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1738 bool foundLayer =
false;
1739 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, bandNb, value](
QgsMapLayer * mapLayer )-> QVariant
1741 QgsRasterLayer *layer = qobject_cast< QgsRasterLayer *>( mapLayer );
1742 if ( !layer || !layer->dataProvider() )
1744 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1748 if ( bandNb < 1 || bandNb > layer->bandCount() )
1750 parent->setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster band number." ) );
1754 if ( std::isnan( value ) )
1756 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster value." ) );
1760 if ( ! layer->dataProvider()->attributeTable( bandNb ) )
1765 const QVariantList data = layer->dataProvider()->attributeTable( bandNb )->row( value );
1766 if ( data.isEmpty() )
1772 const QList<QgsRasterAttributeTable::Field> fields { layer->dataProvider()->attributeTable( bandNb )->fields() };
1773 for (
int idx = 0; idx < static_cast<int>( fields.count( ) ) && idx < static_cast<int>( data.count() ); ++idx )
1780 result.insert( fields.at( idx ).name, data.at( idx ) );
1788 parent->
setEvalErrorString( QObject::tr(
"Function `raster_attributes` requires a valid raster layer." ) );
1809 if ( values.size() == 1 )
1811 attr = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1814 else if ( values.size() == 2 )
1816 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
1817 attr = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1821 parent->
setEvalErrorString( QObject::tr(
"Function `attribute` requires one or two parameters. %n given.",
nullptr, values.length() ) );
1830 QString table { R
"html(
1836 <tr><td>%2</td></tr>
1840 if ( values.size() == 1 )
1842 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1846 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_table` requires one parameter. %n given.",
nullptr, values.length() ) );
1850 if ( dict.isEmpty() )
1855 QStringList headers;
1858 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
1860 headers.push_back( it.key().toHtmlEscaped() );
1861 cells.push_back( it.value().toString( ).toHtmlEscaped() );
1864 return table.arg( headers.join( QLatin1String(
"</th><th>" ) ), cells.join( QLatin1String(
"</td><td>" ) ) );
1869 QString table { R
"html(
1874 if ( values.size() == 1 )
1876 dict = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
1880 parent->
setEvalErrorString( QObject::tr(
"Function `map_to_html_dl` requires one parameter. %n given.",
nullptr, values.length() ) );
1884 if ( dict.isEmpty() )
1891 for (
auto it = dict.cbegin(); it != dict.cend(); ++it )
1893 rows.append( QStringLiteral(
"<dt>%1</dt><dd>%2</dd>" ).arg( it.key().toHtmlEscaped(), it.value().toString().toHtmlEscaped() ) );
1896 return table.arg( rows );
1904 layer = context->
variable( QStringLiteral(
"layer" ) );
1909 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
1911 layer = node->
eval( parent, context );
1922 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
1926 const QString strength = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).toLower();
1927 if ( strength == QLatin1String(
"hard" ) )
1931 else if ( strength == QLatin1String(
"soft" ) )
1936 bool foundLayer =
false;
1937 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
1939 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
1942 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
1948 for (
int i = 0; i < fields.
size(); i++ )
1963 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
1975 layer = context->
variable( QStringLiteral(
"layer" ) );
1980 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
1982 layer = node->
eval( parent, context );
1993 feature = QgsExpressionUtils::getFeature( values.at( 2 ), parent );
1997 const QString strength = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).toLower();
1998 if ( strength == QLatin1String(
"hard" ) )
2002 else if ( strength == QLatin1String(
"soft" ) )
2007 const QString attributeName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2009 bool foundLayer =
false;
2010 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [parent, feature, attributeName, constraintStrength](
QgsMapLayer * mapLayer ) -> QVariant
2012 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2019 if ( fieldIndex == -1 )
2021 parent->
setEvalErrorString( QObject::tr(
"The attribute name did not match any field for the given feature" ) );
2032 parent->
setEvalErrorString( QObject::tr(
"No layer provided to conduct constraints checks" ) );
2048 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2053 for (
int i = 0; i < fields.
count(); ++i )
2067 if ( values.isEmpty() )
2070 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2072 else if ( values.size() == 1 )
2074 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2075 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2077 else if ( values.size() == 2 )
2079 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2080 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2084 parent->
setEvalErrorString( QObject::tr(
"Function `represent_attributes` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2091 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: layer could not be resolved." ) );
2097 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: feature could not be resolved." ) );
2103 for (
int fieldIndex = 0; fieldIndex < fields.
count(); ++fieldIndex )
2105 const QString fieldName { fields.
at( fieldIndex ).
name() };
2106 const QVariant attributeVal = feature.
attribute( fieldIndex );
2107 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer->
id(), fieldName, attributeVal.toString() );
2110 result.insert( fieldName, context->
cachedValue( cacheValueKey ) );
2119 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer->
id(), fieldName );
2131 QString value( fieldFormatter->
representValue( layer, fieldIndex, setup.
config(), cache, attributeVal ) );
2133 result.insert( fields.
at( fieldIndex ).
name(), value );
2149 bool evaluate =
true;
2153 if ( values.isEmpty() )
2156 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2158 else if ( values.size() == 1 )
2160 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
2161 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2163 else if ( values.size() == 2 )
2165 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2166 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2168 else if ( values.size() == 3 )
2170 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), context, parent );
2171 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2172 evaluate = values.value( 2 ).toBool();
2178 parent->
setEvalErrorString( QObject::tr(
"Function `maptip` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2182 parent->
setEvalErrorString( QObject::tr(
"Function `display` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
2214 subContext.setFeature( feature );
2223 exp.prepare( &subContext );
2224 return exp.evaluate( &subContext ).toString();
2230 return fcnCoreFeatureMaptipDisplay( values, context, parent,
false );
2235 return fcnCoreFeatureMaptipDisplay( values, context, parent,
true );
2242 if ( values.isEmpty() )
2245 layer = context->
variable( QStringLiteral(
"layer" ) );
2247 else if ( values.size() == 1 )
2249 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
2250 layer = context->
variable( QStringLiteral(
"layer" ) );
2252 else if ( values.size() == 2 )
2254 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
2255 layer = values.at( 0 );
2259 parent->
setEvalErrorString( QObject::tr(
"Function `is_selected` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
2263 bool foundLayer =
false;
2264 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [feature](
QgsMapLayer * mapLayer ) -> QVariant
2266 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2267 if ( !layer || !feature.
isValid() )
2269 return QVariant( QVariant::Bool );
2275 return QVariant( QVariant::Bool );
2284 if ( values.isEmpty() )
2285 layer = context->
variable( QStringLiteral(
"layer" ) );
2286 else if ( values.count() == 1 )
2287 layer = values.at( 0 );
2290 parent->
setEvalErrorString( QObject::tr(
"Function `num_selected` requires no more than one parameter. %n given.",
nullptr, values.length() ) );
2294 bool foundLayer =
false;
2295 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( layer, context, parent, [](
QgsMapLayer * mapLayer ) -> QVariant
2297 QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( mapLayer );
2300 return QVariant( QVariant::LongLong );
2306 return QVariant( QVariant::LongLong );
2313 static QMap<QString, qlonglong> counterCache;
2314 QVariant functionResult;
2316 auto fetchAndIncrementFunc = [ values, parent, &functionResult ](
QgsMapLayer * mapLayer,
const QString & databaseArgument )
2320 const QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( mapLayer );
2325 database = decodedUri.value( QStringLiteral(
"path" ) ).toString();
2326 if ( database.isEmpty() )
2328 parent->
setEvalErrorString( QObject::tr(
"Could not extract file path from layer `%1`." ).arg( layer->
name() ) );
2333 database = databaseArgument;
2336 const QString table = values.at( 1 ).toString();
2337 const QString idColumn = values.at( 2 ).toString();
2338 const QString filterAttribute = values.at( 3 ).toString();
2339 const QVariant filterValue = values.at( 4 ).toString();
2340 const QVariantMap defaultValues = values.at( 5 ).toMap();
2346 if ( sqliteDb.
open_v2( database, SQLITE_OPEN_READWRITE,
nullptr ) != SQLITE_OK )
2349 functionResult = QVariant();
2353 QString errorMessage;
2354 QString currentValSql;
2356 qlonglong nextId = 0;
2357 bool cachedMode =
false;
2358 bool valueRetrieved =
false;
2360 QString cacheString = QStringLiteral(
"%1:%2:%3:%4:%5" ).arg( database, table, idColumn, filterAttribute, filterValue.toString() );
2367 auto cachedCounter = counterCache.find( cacheString );
2369 if ( cachedCounter != counterCache.end() )
2371 qlonglong &cachedValue = cachedCounter.value();
2372 nextId = cachedValue;
2374 cachedValue = nextId;
2375 valueRetrieved =
true;
2380 if ( !cachedMode || !valueRetrieved )
2382 int result = SQLITE_ERROR;
2385 if ( !filterAttribute.isNull() )
2390 sqliteStatement = sqliteDb.
prepare( currentValSql, result );
2392 if ( result == SQLITE_OK )
2395 if ( sqliteStatement.
step() == SQLITE_ROW )
2401 if ( cachedMode && result == SQLITE_OK )
2403 counterCache.insert( cacheString, nextId );
2407 counterCache.remove( cacheString );
2410 valueRetrieved =
true;
2414 if ( valueRetrieved )
2423 if ( !filterAttribute.isNull() )
2429 for ( QVariantMap::const_iterator iter = defaultValues.constBegin(); iter != defaultValues.constEnd(); ++iter )
2432 vals << iter.value().toString();
2435 upsertSql += QLatin1String(
" (" ) + cols.join(
',' ) +
')';
2436 upsertSql += QLatin1String(
" VALUES " );
2437 upsertSql +=
'(' + vals.join(
',' ) +
')';
2439 int result = SQLITE_ERROR;
2443 if ( transaction->
executeSql( upsertSql, errorMessage ) )
2450 result = sqliteDb.
exec( upsertSql, errorMessage );
2452 if ( result == SQLITE_OK )
2454 functionResult = QVariant( nextId );
2459 parent->
setEvalErrorString( QStringLiteral(
"Could not increment value: SQLite error: \"%1\" (%2)." ).arg( errorMessage, QString::number( result ) ) );
2460 functionResult = QVariant();
2465 functionResult = QVariant();
2468 bool foundLayer =
false;
2469 QgsExpressionUtils::executeLambdaForMapLayer( values.at( 0 ), context, parent, [&fetchAndIncrementFunc](
QgsMapLayer * layer )
2471 fetchAndIncrementFunc( layer, QString() );
2475 const QString databasePath = values.at( 0 ).toString();
2478 fetchAndIncrementFunc(
nullptr, databasePath );
2482 return functionResult;
2488 for (
const QVariant &value : values )
2491 concat += QgsExpressionUtils::getStringValue( value, parent );
2498 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2499 return string.indexOf( QgsExpressionUtils::getStringValue( values.at( 1 ), parent ) ) + 1;
2504 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2505 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2506 return string.right( pos );
2511 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2512 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2513 return string.left( pos );
2518 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2519 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2520 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2521 return string.leftJustified( length, fill.at( 0 ),
true );
2526 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2527 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2528 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2529 return string.rightJustified( length, fill.at( 0 ),
true );
2534 if ( values.size() < 1 )
2536 parent->
setEvalErrorString( QObject::tr(
"Function format requires at least 1 argument" ) );
2540 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2541 for (
int n = 1; n < values.length(); n++ )
2543 string =
string.arg( QgsExpressionUtils::getStringValue( values.at( n ), parent ) );
2551 return QVariant( QDateTime::currentDateTime() );
2556 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2557 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2558 if ( format.isEmpty() && !language.isEmpty() )
2560 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Date when the language is specified" ) );
2561 return QVariant( QDate() );
2564 if ( format.isEmpty() && language.isEmpty() )
2565 return QVariant( QgsExpressionUtils::getDateValue( values.at( 0 ), parent ) );
2567 QString datestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2568 QLocale locale = QLocale();
2569 if ( !language.isEmpty() )
2571 locale = QLocale( language );
2574 QDate date = locale.toDate( datestring, format );
2575 if ( !date.isValid() )
2577 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Date" ).arg( datestring ) );
2580 return QVariant( date );
2585 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2586 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2587 if ( format.isEmpty() && !language.isEmpty() )
2589 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Time when the language is specified" ) );
2590 return QVariant( QTime() );
2593 if ( format.isEmpty() && language.isEmpty() )
2594 return QVariant( QgsExpressionUtils::getTimeValue( values.at( 0 ), parent ) );
2596 QString timestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2597 QLocale locale = QLocale();
2598 if ( !language.isEmpty() )
2600 locale = QLocale( language );
2603 QTime time = locale.toTime( timestring, format );
2604 if ( !time.isValid() )
2606 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Time" ).arg( timestring ) );
2609 return QVariant( time );
2614 return QVariant::fromValue( QgsExpressionUtils::getInterval( values.at( 0 ), parent ) );
2623 double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
2624 QString axis = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2625 int precision = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
2627 QString formatString;
2628 if ( values.count() > 3 )
2629 formatString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
2631 QgsCoordinateFormatter::FormatFlags flags = QgsCoordinateFormatter::FormatFlags();
2632 if ( formatString.compare( QLatin1String(
"suffix" ), Qt::CaseInsensitive ) == 0 )
2636 else if ( formatString.compare( QLatin1String(
"aligned" ), Qt::CaseInsensitive ) == 0 )
2640 else if ( ! formatString.isEmpty() )
2642 parent->
setEvalErrorString( QObject::tr(
"Invalid formatting parameter: '%1'. It must be empty, or 'suffix' or 'aligned'." ).arg( formatString ) );
2646 if ( axis.compare( QLatin1String(
"x" ), Qt::CaseInsensitive ) == 0 )
2650 else if ( axis.compare( QLatin1String(
"y" ), Qt::CaseInsensitive ) == 0 )
2656 parent->
setEvalErrorString( QObject::tr(
"Invalid axis name: '%1'. It must be either 'x' or 'y'." ).arg( axis ) );
2664 return floatToDegreeFormat( format, values, context, parent, node );
2671 value = QgsCoordinateUtils::dmsToDecimal( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), &ok );
2673 return ok ? QVariant( value ) : QVariant();
2679 return floatToDegreeFormat( format, values, context, parent, node );
2684 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2685 QDateTime d2 = QgsExpressionUtils::getDateTimeValue( values.at( 1 ), parent );
2686 qint64 seconds = d2.secsTo( d1 );
2687 return QVariant::fromValue(
QgsInterval( seconds ) );
2692 if ( !values.at( 0 ).canConvert<QDate>() )
2695 QDate date = QgsExpressionUtils::getDateValue( values.at( 0 ), parent );
2696 if ( !date.isValid() )
2701 return date.dayOfWeek() % 7;
2706 QVariant value = values.at( 0 );
2707 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2710 return QVariant( inter.
days() );
2714 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2715 return QVariant( d1.date().day() );
2721 QVariant value = values.at( 0 );
2722 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2725 return QVariant( inter.
years() );
2729 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2730 return QVariant( d1.date().year() );
2736 QVariant value = values.at( 0 );
2737 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2740 return QVariant( inter.
months() );
2744 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2745 return QVariant( d1.date().month() );
2751 QVariant value = values.at( 0 );
2752 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2755 return QVariant( inter.
weeks() );
2759 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2760 return QVariant( d1.date().weekNumber() );
2766 QVariant value = values.at( 0 );
2767 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2770 return QVariant( inter.
hours() );
2774 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2775 return QVariant( t1.hour() );
2781 QVariant value = values.at( 0 );
2782 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2785 return QVariant( inter.
minutes() );
2789 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2790 return QVariant( t1.minute() );
2796 QVariant value = values.at( 0 );
2797 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2800 return QVariant( inter.
seconds() );
2804 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2805 return QVariant( t1.second() );
2811 QDateTime dt = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2814 return QVariant( dt.toMSecsSinceEpoch() );
2824 long long millisecs_since_epoch = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
2826 return QVariant( QDateTime::fromMSecsSinceEpoch( millisecs_since_epoch ) );
2831 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2834 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif" ) ) );
2837 QString tag = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2843 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
2846 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif_geotag" ) ) );
2853#define ENSURE_GEOM_TYPE(f, g, geomtype) \
2854 if ( !(f).hasGeometry() ) \
2855 return QVariant(); \
2856 QgsGeometry g = (f).geometry(); \
2857 if ( (g).type() != (geomtype) ) \
2864 if ( g.isMultipart() )
2866 return g.asMultiPoint().at( 0 ).x();
2870 return g.asPoint().x();
2878 if ( g.isMultipart() )
2880 return g.asMultiPoint().at( 0 ).y();
2884 return g.asPoint().y();
2898 if ( g.isEmpty() || !abGeom->
is3D() )
2901 if ( g.type() == Qgis::GeometryType::Point && !g.isMultipart() )
2903 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( g.constGet() );
2907 else if ( g.type() == Qgis::GeometryType::Point && g.isMultipart() )
2909 if (
const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( g.constGet() ) )
2911 if ( collection->numGeometries() > 0 )
2913 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
2924 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2930 return QVariant( isValid );
2935 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2939 const QString methodString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).trimmed();
2940#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
2945 if ( methodString.compare( QLatin1String(
"linework" ), Qt::CaseInsensitive ) == 0 )
2947 else if ( methodString.compare( QLatin1String(
"structure" ), Qt::CaseInsensitive ) == 0 )
2950 const bool keepCollapsed = values.value( 2 ).toBool();
2955 valid = geom.
makeValid( method, keepCollapsed );
2959 parent->
setEvalErrorString( QObject::tr(
"The make_valid parameters require a newer GEOS library version" ) );
2963 return QVariant::fromValue( valid );
2968 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2974 for (
int i = 0; i < multiGeom.size(); ++i )
2976 array += QVariant::fromValue( multiGeom.at( i ) );
2984 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2989 if ( geom.
type() == Qgis::GeometryType::Point && !geom.
isMultipart() )
2996 QVariant result(
centroid.asPoint().
x() );
3002 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3007 if ( geom.
type() == Qgis::GeometryType::Point && !geom.
isMultipart() )
3014 QVariant result(
centroid.asPoint().
y() );
3020 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3028 if ( geom.
type() == Qgis::GeometryType::Point && !geom.
isMultipart() )
3030 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3034 else if ( geom.
type() == Qgis::GeometryType::Point && geom.
isMultipart() )
3038 if ( collection->numGeometries() == 1 )
3040 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3051 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3059 if ( geom.
type() == Qgis::GeometryType::Point && !geom.
isMultipart() )
3061 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3065 else if ( geom.
type() == Qgis::GeometryType::Point && geom.
isMultipart() )
3069 if ( collection->numGeometries() == 1 )
3071 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
3082 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3087 int idx = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
3114 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3131 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3148 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3153 bool ignoreClosing =
false;
3154 if ( values.length() > 1 )
3156 ignoreClosing = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3166 bool skipLast =
false;
3167 if ( ignoreClosing && ring.count() > 2 && ring.first() == ring.last() )
3172 for (
int i = 0; i < ( skipLast ? ring.count() - 1 : ring.count() ); ++ i )
3184 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3195 for (
int i = 0; i < line->numPoints() - 1; ++i )
3199 << line->pointN( i )
3200 << line->pointN( i + 1 ) );
3211 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3221 if ( collection->numGeometries() == 1 )
3223 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->geometryN( 0 ) );
3228 if ( !curvePolygon )
3232 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3238 QVariant result = curve ? QVariant::fromValue(
QgsGeometry( curve ) ) : QVariant();
3244 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3254 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
3260 QVariant result = part ? QVariant::fromValue(
QgsGeometry( part ) ) : QVariant();
3266 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3275 return QVariant::fromValue(
QgsGeometry( boundary ) );
3280 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3289 return QVariant::fromValue( merged );
3294 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3298 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3303 if ( sharedPaths.
isNull() )
3306 return QVariant::fromValue( sharedPaths );
3312 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3317 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3320 if ( simplified.
isNull() )
3328 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3333 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3338 if ( simplified.
isNull() )
3346 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3351 int iterations = std::min( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), 10 );
3352 double offset = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0.0, 0.5 );
3353 double minLength = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3354 double maxAngle = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ), 0.0, 180.0 );
3356 QgsGeometry smoothed = geom.
smooth(
static_cast<unsigned int>( iterations ), offset, minLength, maxAngle );
3365 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3370 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3371 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3372 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3383 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3388 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3389 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3390 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3391 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3392 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3395 minAmplitude, maxAmplitude, seed );
3404 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3409 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3410 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3411 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3422 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3427 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3428 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3429 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3430 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3431 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3434 minAmplitude, maxAmplitude, seed );
3443 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3448 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3449 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3450 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3461 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3466 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3467 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3468 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3469 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3470 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3473 minAmplitude, maxAmplitude, seed );
3482 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3487 const QVariantList pattern = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
3488 QVector< double > dashPattern;
3489 dashPattern.reserve( pattern.size() );
3490 for (
const QVariant &value : std::as_const( pattern ) )
3493 double v = value.toDouble( &ok );
3500 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must be an array of numbers" ) );
3505 if ( dashPattern.size() % 2 != 0 )
3507 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must contain an even number of elements" ) );
3511 const QString startRuleString = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).trimmed();
3513 if ( startRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3515 else if ( startRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3517 else if ( startRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3519 else if ( startRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3521 else if ( startRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3525 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( startRuleString ) );
3529 const QString endRuleString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
3531 if ( endRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3533 else if ( endRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3535 else if ( endRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3537 else if ( endRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3539 else if ( endRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3543 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( endRuleString ) );
3547 const QString adjustString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
3549 if ( adjustString.compare( QLatin1String(
"both" ), Qt::CaseInsensitive ) == 0 )
3551 else if ( adjustString.compare( QLatin1String(
"dash" ), Qt::CaseInsensitive ) == 0 )
3553 else if ( adjustString.compare( QLatin1String(
"gap" ), Qt::CaseInsensitive ) == 0 )
3557 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern size adjustment" ).arg( adjustString ) );
3561 const double patternOffset = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
3572 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3577 const long long count = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3579 if ( densified.
isNull() )
3587 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3592 const double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3594 if ( densified.
isNull() )
3603 if ( values.size() == 1 && QgsExpressionUtils::isList( values.at( 0 ) ) )
3605 list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
3612 QVector< QgsGeometry > parts;
3613 parts.reserve( list.size() );
3614 for (
const QVariant &value : std::as_const( list ) )
3616 if ( value.userType() == QMetaType::type(
"QgsGeometry" ) )
3632 if ( values.count() < 2 || values.count() > 4 )
3634 parent->
setEvalErrorString( QObject::tr(
"Function make_point requires 2-4 arguments" ) );
3638 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3639 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3640 double z = values.count() >= 3 ? QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) : 0.0;
3641 double m = values.count() >= 4 ? QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) : 0.0;
3642 switch ( values.count() )
3656 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3657 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3658 double m = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3664 if ( values.empty() )
3669 QVector<QgsPoint> points;
3670 points.reserve( values.count() );
3672 auto addPoint = [&points](
const QgsGeometry & geom )
3680 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3687 for (
const QVariant &value : values )
3689 if ( value.type() == QVariant::List )
3691 const QVariantList list = value.toList();
3692 for (
const QVariant &v : list )
3694 addPoint( QgsExpressionUtils::getGeometry( v, parent ) );
3699 addPoint( QgsExpressionUtils::getGeometry( value, parent ) );
3703 if ( points.count() < 2 )
3711 if ( values.count() < 1 )
3713 parent->
setEvalErrorString( QObject::tr(
"Function make_polygon requires an argument" ) );
3717 QgsGeometry outerRing = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3719 if ( outerRing.
type() == Qgis::GeometryType::Polygon )
3722 if ( outerRing.
type() != Qgis::GeometryType::Line || outerRing.
isNull() )
3725 std::unique_ptr< QgsPolygon > polygon = std::make_unique< QgsPolygon >();
3727 const QgsCurve *exteriorRing = qgsgeometry_cast< QgsCurve * >( outerRing.
constGet() );
3734 exteriorRing = qgsgeometry_cast< QgsCurve * >( collection->
geometryN( 0 ) );
3739 if ( !exteriorRing )
3742 polygon->setExteriorRing( exteriorRing->
segmentize() );
3745 for (
int i = 1; i < values.count(); ++i )
3747 QgsGeometry ringGeom = QgsExpressionUtils::getGeometry( values.at( i ), parent );
3751 if ( ringGeom.
type() != Qgis::GeometryType::Line || ringGeom.
isNull() )
3754 const QgsCurve *ring = qgsgeometry_cast< QgsCurve * >( ringGeom.
constGet() );
3761 ring = qgsgeometry_cast< QgsCurve * >( collection->
geometryN( 0 ) );
3769 polygon->addInteriorRing( ring->
segmentize() );
3772 return QVariant::fromValue(
QgsGeometry( std::move( polygon ) ) );
3777 std::unique_ptr<QgsTriangle> tr(
new QgsTriangle() );
3778 std::unique_ptr<QgsLineString> lineString(
new QgsLineString() );
3779 lineString->clear();
3781 for (
const QVariant &value : values )
3783 QgsGeometry geom = QgsExpressionUtils::getGeometry( value, parent );
3790 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3797 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3805 lineString->addVertex( *point );
3808 tr->setExteriorRing( lineString.release() );
3810 return QVariant::fromValue(
QgsGeometry( tr.release() ) );
3815 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3822 double radius = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3823 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
3830 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3837 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3845 return QVariant::fromValue(
QgsGeometry( circ.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
3850 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3857 double majorAxis = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3858 double minorAxis = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3859 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3860 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 4 ), parent );
3866 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3873 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3880 QgsEllipse elp( *point, majorAxis, minorAxis, azimuth );
3881 return QVariant::fromValue(
QgsGeometry( elp.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
3887 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3894 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3901 unsigned int nbEdges =
static_cast<unsigned int>( QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) );
3904 parent->
setEvalErrorString( QObject::tr(
"Number of edges/sides must be greater than 2" ) );
3911 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (inscribed) or 1 (circumscribed)" ) );
3915 const QgsPoint *center = qgsgeometry_cast< const QgsPoint * >( pt1.
constGet() );
3922 center = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3929 const QgsPoint *corner = qgsgeometry_cast< const QgsPoint * >( pt2.
constGet() );
3936 corner = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3951 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3957 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3963 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
3964 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
3972 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3978 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3984 QgsGeometry pt3 = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
3993 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (distance) or 1 (projected)" ) );
3996 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
3997 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
3998 const QgsPoint *point3 = qgsgeometry_cast< const QgsPoint *>( pt3.
constGet() );
4017 return QVariant::fromValue( geom.
vertexAt( idx ) );
4025 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4027 const QVariant v = pointAt( geom, idx, parent );
4030 return QVariant( v.value<
QgsPoint>().
x() );
4036 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4038 return fcnOldXat( values, f, parent, node );
4040 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4042 return fcnOldXat( QVariantList() << values[1], f, parent, node );
4045 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4051 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4053 const QVariant v = pointAt( geom, vertexNumber, parent );
4055 return QVariant( v.value<
QgsPoint>().
x() );
4065 const int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
4067 const QVariant v = pointAt( geom, idx, parent );
4070 return QVariant( v.value<
QgsPoint>().
y() );
4076 if ( values.at( 1 ).isNull() && !values.at( 0 ).isNull() )
4078 return fcnOldYat( values, f, parent, node );
4080 else if ( values.at( 0 ).isNull() && !values.at( 1 ).isNull() )
4082 return fcnOldYat( QVariantList() << values[1], f, parent, node );
4085 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4091 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4093 const QVariant v = pointAt( geom, vertexNumber, parent );
4095 return QVariant( v.value<
QgsPoint>().
y() );
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>().
z() );
4119 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4125 const int vertexNumber = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4127 const QVariant v = pointAt( geom, vertexNumber, parent );
4129 return QVariant( v.value<
QgsPoint>().
m() );
4148 return QVariant::fromValue( geom );
4156 QString wkt = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4158 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4164 const QByteArray wkb = QgsExpressionUtils::getBinaryValue( values.at( 0 ), parent );
4170 return !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4175 QString gml = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
4182 ogcContext.
layer = mapLayerPtr.data();
4183 ogcContext.
transformContext = context->
variable( QStringLiteral(
"_project_transform_context" ) ).value<QgsCoordinateTransformContext>();
4187 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4200 return QVariant( area );
4210 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4212 if ( geom.
type() != Qgis::GeometryType::Polygon )
4215 return QVariant( geom.
area() );
4227 return QVariant( len );
4244 return QVariant( len );
4248 return f.
geometry().
isNull() ? QVariant( 0 ) : QVariant( f.geometry().constGet()->perimeter() );
4254 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4256 if ( geom.
type() != Qgis::GeometryType::Polygon )
4260 return QVariant( geom.
length() );
4265 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4271 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4280 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4289 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4304 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon *>( collection->
geometryN( i ) );
4305 if ( !curvePolygon )
4317 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4324 return QVariant( curvePolygon->
ringCount() );
4326 bool foundPoly =
false;
4334 curvePolygon = qgsgeometry_cast< QgsCurvePolygon *>( collection->
geometryN( i ) );
4335 if ( !curvePolygon )
4346 return QVariant( ringCount );
4351 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4353 QVariant result = !geomBounds.
isNull() ? QVariant::fromValue( geomBounds ) : QVariant();
4359 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4365 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4371 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4380 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4386 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4392 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4398 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4404 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4412 double max = std::numeric_limits< double >::lowest();
4416 double z = ( *it ).z();
4422 if ( max == std::numeric_limits< double >::lowest() )
4423 return QVariant( QVariant::Double );
4425 return QVariant( max );
4430 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4438 double min = std::numeric_limits< double >::max();
4442 double z = ( *it ).z();
4448 if ( min == std::numeric_limits< double >::max() )
4449 return QVariant( QVariant::Double );
4451 return QVariant( min );
4456 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4464 double min = std::numeric_limits< double >::max();
4468 double m = ( *it ).m();
4474 if ( min == std::numeric_limits< double >::max() )
4475 return QVariant( QVariant::Double );
4477 return QVariant( min );
4482 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4490 double max = std::numeric_limits< double >::lowest();
4494 double m = ( *it ).m();
4500 if ( max == std::numeric_limits< double >::lowest() )
4501 return QVariant( QVariant::Double );
4503 return QVariant( max );
4508 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4509 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom.
constGet() );
4512 parent->
setEvalErrorString( QObject::tr(
"Function `sinuosity` requires a line geometry." ) );
4521 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4525 parent->
setEvalErrorString( QObject::tr(
"Function `straight_distance_2d` requires a line geometry or a multi line geometry with a single part." ) );
4534 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4539 parent->
setEvalErrorString( QObject::tr(
"Function `roundness` requires a polygon geometry or a multi polygon geometry with a single part." ) );
4550 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4554 std::unique_ptr< QgsAbstractGeometry > flipped( geom.
constGet()->
clone() );
4556 return QVariant::fromValue(
QgsGeometry( std::move( flipped ) ) );
4561 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4565 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( fGeom.
constGet() );
4572 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
4580 return QVariant::fromValue( curve->
isClosed() );
4585 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4598 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4599 closedLine->close();
4601 result = QVariant::fromValue(
QgsGeometry( std::move( closedLine ) ) );
4611 if (
const QgsLineString *line = qgsgeometry_cast<const QgsLineString * >( collection->
geometryN( i ) ) )
4613 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4614 closedLine->close();
4616 closed->addGeometry( closedLine.release() );
4619 result = QVariant::fromValue(
QgsGeometry( std::move( closed ) ) );
4627 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4631 return QVariant::fromValue( fGeom.
isEmpty() );
4637 return QVariant::fromValue(
true );
4639 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4640 return QVariant::fromValue( fGeom.
isNull() || fGeom.
isEmpty() );
4645 if ( values.length() < 2 || values.length() > 3 )
4648 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4649 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4656 if ( values.length() == 2 )
4659 QString result = engine->relate( sGeom.
constGet() );
4660 return QVariant::fromValue( result );
4665 QString pattern = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
4666 bool result = engine->relatePattern( sGeom.
constGet(), pattern );
4667 return QVariant::fromValue( result );
4673 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4674 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4679 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4680 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4681 return fGeom.
disjoint( sGeom ) ? TVL_True : TVL_False;
4685 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4686 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4687 return fGeom.
intersects( sGeom ) ? TVL_True : TVL_False;
4691 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4692 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4693 return fGeom.
touches( sGeom ) ? TVL_True : TVL_False;
4697 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4698 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4699 return fGeom.
crosses( sGeom ) ? TVL_True : TVL_False;
4703 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4704 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4705 return fGeom.
contains( sGeom ) ? TVL_True : TVL_False;
4709 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4710 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4711 return fGeom.
overlaps( sGeom ) ? TVL_True : TVL_False;
4715 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4716 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4717 return fGeom.
within( sGeom ) ? TVL_True : TVL_False;
4722 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4723 const double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4724 const int seg = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4725 const QString endCapString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
4726 const QString joinString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
4727 const double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
4730 if ( endCapString.compare( QLatin1String(
"flat" ), Qt::CaseInsensitive ) == 0 )
4731 capStyle = Qgis::EndCapStyle::Flat;
4732 else if ( endCapString.compare( QLatin1String(
"square" ), Qt::CaseInsensitive ) == 0 )
4733 capStyle = Qgis::EndCapStyle::Square;
4736 if ( joinString.compare( QLatin1String(
"miter" ), Qt::CaseInsensitive ) == 0 )
4737 joinStyle = Qgis::JoinStyle::Miter;
4738 else if ( joinString.compare( QLatin1String(
"bevel" ), Qt::CaseInsensitive ) == 0 )
4739 joinStyle = Qgis::JoinStyle::Bevel;
4742 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4748 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4750 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4755 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4757 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4762 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4764 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4769 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4770 const QgsPoint *pt = qgsgeometry_cast<const QgsPoint *>( fGeom.
constGet() );
4777 pt = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4784 parent->
setEvalErrorString( QObject::tr(
"Function `wedge_buffer` requires a point value for the center." ) );
4788 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4789 double width = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4790 double outerRadius = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4791 double innerRadius = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
4794 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4800 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4801 if ( fGeom.
type() != Qgis::GeometryType::Line )
4803 parent->
setEvalErrorString( QObject::tr(
"Function `tapered_buffer` requires a line geometry." ) );
4807 double startWidth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4808 double endWidth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4809 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) );
4812 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4818 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4819 if ( fGeom.
type() != Qgis::GeometryType::Line )
4821 parent->
setEvalErrorString( QObject::tr(
"Function `buffer_by_m` requires a line geometry." ) );
4825 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) );
4828 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4834 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4835 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4836 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4837 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4838 if ( joinInt < 1 || joinInt > 3 )
4842 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4845 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4851 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4852 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4853 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4855 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4856 if ( joinInt < 1 || joinInt > 3 )
4860 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4863 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4869 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4870 double distStart = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4871 double distEnd = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4874 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4880 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4881 double dx = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4882 double dy = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4884 return QVariant::fromValue( fGeom );
4889 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4890 const double rotation = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4891 const QgsGeometry center = values.at( 2 ).
isValid() ? QgsExpressionUtils::getGeometry( values.at( 2 ), parent )
4893 const bool perPart = values.value( 3 ).toBool();
4900 std::unique_ptr< QgsGeometryCollection > collection( qgsgeometry_cast< QgsGeometryCollection * >( fGeom.
constGet()->
clone() ) );
4903 const QgsPointXY partCenter = ( *it )->boundingBox().center();
4904 QTransform t = QTransform::fromTranslate( partCenter.
x(), partCenter.
y() );
4905 t.rotate( -rotation );
4906 t.translate( -partCenter.
x(), -partCenter.
y() );
4907 ( *it )->transform( t );
4909 return QVariant::fromValue(
QgsGeometry( std::move( collection ) ) );
4921 parent->
setEvalErrorString( QObject::tr(
"Function 'rotate' requires a point value for the center" ) );
4929 fGeom.
rotate( rotation, pt );
4930 return QVariant::fromValue( fGeom );
4936 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4937 const double xScale = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4938 const double yScale = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4939 const QgsGeometry center = values.at( 3 ).isValid() ? QgsExpressionUtils::getGeometry( values.at( 3 ), parent )
4950 parent->
setEvalErrorString( QObject::tr(
"Function 'scale' requires a point value for the center" ) );
4958 QTransform t = QTransform::fromTranslate( pt.
x(), pt.
y() );
4959 t.scale( xScale, yScale );
4960 t.translate( -pt.
x(), -pt.
y() );
4962 return QVariant::fromValue( fGeom );
4967 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4973 const double deltaX = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4974 const double deltaY = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4976 const double rotationZ = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4978 const double scaleX = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
4979 const double scaleY = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
4981 const double deltaZ = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
4982 const double deltaM = QgsExpressionUtils::getDoubleValue( values.at( 7 ), parent );
4983 const double scaleZ = QgsExpressionUtils::getDoubleValue( values.at( 8 ), parent );
4984 const double scaleM = QgsExpressionUtils::getDoubleValue( values.at( 9 ), parent );
4995 QTransform transform;
4996 transform.translate( deltaX, deltaY );
4997 transform.rotate( rotationZ );
4998 transform.scale( scaleX, scaleY );
4999 fGeom.
transform( transform, deltaZ, scaleZ, deltaM, scaleM );
5001 return QVariant::fromValue( fGeom );
5007 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5009 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5014 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5016 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5022 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5023 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5025 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5031 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5033 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5037#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
5042 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5043 const double targetPercent = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5044 const bool allowHoles = values.value( 2 ).toBool();
5046 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5059 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5061 if ( values.length() == 2 )
5062 segments = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5070 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5076 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5078 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5084 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5090 double area,
angle, width, height;
5103 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5104 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5106 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5112 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5119 const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( fGeom.
constGet() );
5124 result = reversed ? QVariant::fromValue(
QgsGeometry( reversed ) ) : QVariant();
5132 if (
const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( collection->
geometryN( i ) ) )
5134 reversed->addGeometry( curve->
reversed() );
5141 result = reversed ? QVariant::fromValue(
QgsGeometry( std::move( reversed ) ) ) : QVariant();
5148 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5159 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->
geometryN( 0 ) );
5168 QVariant result = exterior ? QVariant::fromValue(
QgsGeometry( exterior ) ) : QVariant();
5174 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5175 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5176 return QVariant( fGeom.
distance( sGeom ) );
5181 QgsGeometry g1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5182 QgsGeometry g2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5185 if ( values.length() == 3 && values.at( 2 ).isValid() )
5187 double densify = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5188 densify = std::clamp( densify, 0.0, 1.0 );
5196 return res > -1 ? QVariant( res ) : QVariant();
5201 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5202 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5204 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5209 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5210 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5212 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5217 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5218 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5220 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5226 if ( values.length() < 1 || values.length() > 2 )
5229 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5231 if ( values.length() == 2 )
5232 prec = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5233 QString wkt = fGeom.
asWkt( prec );
5234 return QVariant( wkt );
5239 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5240 return fGeom.
isNull() ? QVariant() : QVariant( fGeom.asWkb() );
5245 if ( values.length() != 2 )
5247 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires exactly two parameters. %n given.",
nullptr, values.length() ) );
5251 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5252 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5254 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5261 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5266 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5273 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5280 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires two points as arguments." ) );
5287 if ( pt1->
y() < pt2->
y() )
5289 else if ( pt1->
y() > pt2->
y() )
5297 if ( pt1->
x() < pt2->
x() )
5299 else if ( pt1->
x() > pt2->
x() )
5300 return M_PI + ( M_PI_2 );
5305 if ( pt1->
x() < pt2->
x() )
5307 if ( pt1->
y() < pt2->
y() )
5309 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) );
5313 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5320 if ( pt1->
y() > pt2->
y() )
5322 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) )
5327 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
5328 + ( M_PI + ( M_PI_2 ) );
5335 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5339 parent->
setEvalErrorString( QStringLiteral(
"'project' requires a point geometry" ) );
5343 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5344 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5345 double inclination = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
5348 QgsPoint newPoint = p->
project( distance, 180.0 * azimuth / M_PI, 180.0 * inclination / M_PI );
5355 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5356 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5358 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
5365 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5369 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
5376 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
5381 if ( ( fGeom1.
type() != Qgis::GeometryType::Point ) || ( fGeom2.
type() != Qgis::GeometryType::Point ) ||
5384 parent->
setEvalErrorString( QStringLiteral(
"Function 'inclination' requires two points as arguments." ) );
5394 if ( values.length() != 3 )
5397 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5398 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5399 double y = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5403 QVariant result = geom.
constGet() ? QVariant::fromValue( geom ) : QVariant();
5409 if ( values.length() < 2 )
5412 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5415 return values.at( 0 );
5417 QString expString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5418 QVariant cachedExpression;
5423 if ( cachedExpression.isValid() )
5430 bool asc = values.value( 2 ).toBool();
5448 Q_ASSERT( collection );
5452 QgsExpressionSorter sorter( orderBy );
5454 QList<QgsFeature> partFeatures;
5455 partFeatures.reserve( collection->
partCount() );
5456 for (
int i = 0; i < collection->
partCount(); ++i )
5462 sorter.sortFeatures( partFeatures, unconstedContext );
5466 Q_ASSERT( orderedGeom );
5471 for (
const QgsFeature &feature : std::as_const( partFeatures ) )
5476 QVariant result = QVariant::fromValue(
QgsGeometry( orderedGeom ) );
5479 delete unconstedContext;
5486 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5487 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5491 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5497 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5498 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5502 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5508 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5509 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5513 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5519 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5520 if ( lineGeom.
type() != Qgis::GeometryType::Line )
5522 parent->
setEvalErrorString( QObject::tr(
"line_substring requires a curve geometry input" ) );
5528 curve = qgsgeometry_cast< const QgsCurve * >( lineGeom.
constGet() );
5535 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
5542 double startDistance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5543 double endDistance = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5545 std::unique_ptr< QgsCurve > substring( curve->
curveSubstring( startDistance, endDistance ) );
5547 return !result.isNull() ? QVariant::fromValue( result ) : QVariant();
5552 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5553 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5560 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5561 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5566 vertex = count + vertex;
5574 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5575 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5580 vertex = count + vertex;
5588 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5589 QgsGeometry pointGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5593 return distance >= 0 ? distance : QVariant();
5598 if ( values.length() == 2 && values.at( 1 ).toInt() != 0 )
5600 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5601 return qgsRound( number, QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
5604 if ( values.length() >= 1 )
5606 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5607 return QVariant( qlonglong( std::round( number ) ) );
5622 const double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5623 const int places = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5624 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5631 const bool omitGroupSeparator = values.value( 3 ).toBool();
5632 const bool trimTrailingZeros = values.value( 4 ).toBool();
5634 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5635 if ( !omitGroupSeparator )
5636 locale.setNumberOptions( locale.numberOptions() & ~QLocale::NumberOption::OmitGroupSeparator );
5638 locale.setNumberOptions( locale.numberOptions() | QLocale::NumberOption::OmitGroupSeparator );
5640 QString res = locale.toString( value,
'f', places );
5642 if ( trimTrailingZeros )
5644#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
5645 const QChar decimal = locale.decimalPoint();
5646 const QChar zeroDigit = locale.zeroDigit();
5648 const QChar decimal = locale.decimalPoint().at( 0 );
5649 const QChar zeroDigit = locale.zeroDigit().at( 0 );
5652 if ( res.contains( decimal ) )
5654 int trimPoint = res.length() - 1;
5656 while ( res.at( trimPoint ) == zeroDigit )
5659 if ( res.at( trimPoint ) == decimal )
5662 res.truncate( trimPoint + 1 );
5671 const QDateTime datetime = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
5672 const QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5673 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5675 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5676 return locale.toString( datetime, format );
5682 int avg = ( color.red() + color.green() + color.blue() ) / 3;
5683 int alpha = color.alpha();
5685 color.setRgb( avg, avg, avg, alpha );
5694 double ratio = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5699 else if ( ratio < 0 )
5704 int red =
static_cast<int>( color1.red() * ( 1 - ratio ) + color2.red() * ratio );
5705 int green =
static_cast<int>( color1.green() * ( 1 - ratio ) + color2.green() * ratio );
5706 int blue =
static_cast<int>( color1.blue() * ( 1 - ratio ) + color2.blue() * ratio );
5707 int alpha =
static_cast<int>( color1.alpha() * ( 1 - ratio ) + color2.alpha() * ratio );
5709 QColor newColor( red, green, blue, alpha );
5716 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
5717 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5718 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
5719 QColor color = QColor( red, green, blue );
5720 if ( ! color.isValid() )
5722 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( red ).arg( green ).arg( blue ) );
5723 color = QColor( 0, 0, 0 );
5726 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
5731 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
5732 QVariant value = node->
eval( parent, context );
5736 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
5738 value = node->
eval( parent, context );
5746 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
5748 QVariant value = node->
eval( parent, context );
5750 if ( value.toBool() )
5752 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
5754 value = node->
eval( parent, context );
5759 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
5761 value = node->
eval( parent, context );
5769 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
5770 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5771 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
5772 int alpha = QgsExpressionUtils::getNativeIntValue( values.at( 3 ), parent );
5773 QColor color = QColor( red, green, blue, alpha );
5774 if ( ! color.isValid() )
5776 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
5777 color = QColor( 0, 0, 0 );
5786 if ( values.at( 0 ).userType() == QMetaType::type(
"QgsGradientColorRamp" ) )
5788 expRamp = QgsExpressionUtils::getRamp( values.at( 0 ), parent );
5793 QString rampName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
5797 parent->
setEvalErrorString( QObject::tr(
"\"%1\" is not a valid color ramp" ).arg( rampName ) );
5802 double value = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5803 QColor color = ramp->
color( value );
5810 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
5812 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5814 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5816 QColor color = QColor::fromHslF( hue, saturation, lightness );
5818 if ( ! color.isValid() )
5820 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( lightness ) );
5821 color = QColor( 0, 0, 0 );
5824 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
5830 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
5832 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5834 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5836 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
5838 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
5839 if ( ! color.isValid() )
5841 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
5842 color = QColor( 0, 0, 0 );
5850 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
5852 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5854 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5856 QColor color = QColor::fromHsvF( hue, saturation, value );
5858 if ( ! color.isValid() )
5860 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( value ) );
5861 color = QColor( 0, 0, 0 );
5864 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
5870 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
5872 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5874 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5876 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
5878 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
5879 if ( ! color.isValid() )
5881 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
5882 color = QColor( 0, 0, 0 );
5890 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
5892 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5894 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5896 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
5898 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black );
5900 if ( ! color.isValid() )
5902 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ) );
5903 color = QColor( 0, 0, 0 );
5906 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
5912 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
5914 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5916 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5918 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
5920 double alpha = QgsExpressionUtils::getIntValue( values.at( 4 ), parent ) / 255.0;
5922 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
5923 if ( ! color.isValid() )
5925 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
5926 color = QColor( 0, 0, 0 );
5934 if ( ! color.isValid() )
5936 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( values.at( 0 ).toString() ) );
5940 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5941 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
5943 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
5944 return color.green();
5945 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
5946 return color.blue();
5947 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
5948 return color.alpha();
5949 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
5950 return static_cast< double >( color.hsvHueF() * 360 );
5951 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
5952 return static_cast< double >( color.hsvSaturationF() * 100 );
5953 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
5954 return static_cast< double >( color.valueF() * 100 );
5955 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
5956 return static_cast< double >( color.hslHueF() * 360 );
5957 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
5958 return static_cast< double >( color.hslSaturationF() * 100 );
5959 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
5960 return static_cast< double >( color.lightnessF() * 100 );
5961 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
5962 return static_cast< double >( color.cyanF() * 100 );
5963 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
5964 return static_cast< double >( color.magentaF() * 100 );
5965 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
5966 return static_cast< double >( color.yellowF() * 100 );
5967 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
5968 return static_cast< double >( color.blackF() * 100 );
5970 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
5976 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
5977 if ( map.count() < 1 )
5979 parent->
setEvalErrorString( QObject::tr(
"A minimum of two colors is required to create a ramp" ) );
5983 QList< QColor > colors;
5985 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
5988 if ( !colors.last().isValid() )
5990 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( it.value().toString() ) );
5994 double step = it.key().toDouble();
5995 if ( it == map.constBegin() )
6000 else if ( it == map.constEnd() )
6010 bool discrete = values.at( 1 ).toBool();
6012 return QVariant::fromValue(
QgsGradientColorRamp( colors.first(), colors.last(), discrete, stops ) );
6018 if ( ! color.isValid() )
6020 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( values.at( 0 ).toString() ) );
6024 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6025 int value = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6026 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
6027 color.setRed( value );
6028 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
6029 color.setGreen( value );
6030 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
6031 color.setBlue( value );
6032 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
6033 color.setAlpha( value );
6034 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
6035 color.setHsv( value, color.hsvSaturation(), color.value(), color.alpha() );
6036 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
6037 color.setHsvF( color.hsvHueF(), value / 100.0, color.valueF(), color.alphaF() );
6038 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
6039 color.setHsvF( color.hsvHueF(), color.hsvSaturationF(), value / 100.0, color.alphaF() );
6040 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
6041 color.setHsl( value, color.hslSaturation(), color.lightness(), color.alpha() );
6042 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
6043 color.setHslF( color.hslHueF(), value / 100.0, color.lightnessF(), color.alphaF() );
6044 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
6045 color.setHslF( color.hslHueF(), color.hslSaturationF(), value / 100.0, color.alphaF() );
6046 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
6047 color.setCmykF( value / 100.0, color.magentaF(), color.yellowF(), color.blackF(), color.alphaF() );
6048 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
6049 color.setCmykF( color.cyanF(), value / 100.0, color.yellowF(), color.blackF(), color.alphaF() );
6050 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
6051 color.setCmykF( color.cyanF(), color.magentaF(), value / 100.0, color.blackF(), color.alphaF() );
6052 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
6053 color.setCmykF( color.cyanF(), color.magentaF(), color.yellowF(), value / 100.0, color.alphaF() );
6056 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
6065 if ( ! color.isValid() )
6067 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( values.at( 0 ).toString() ) );
6071 color = color.darker( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6079 if ( ! color.isValid() )
6081 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( values.at( 0 ).toString() ) );
6085 color = color.lighter( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
6092 QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6095 return QVariant::fromValue( geom );
6101 const QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
6109 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
6110 QString sAuthId = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6111 QString dAuthId = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6115 return QVariant::fromValue( fGeom );
6118 return QVariant::fromValue( fGeom );
6127 return QVariant::fromValue( fGeom );
6140 bool foundLayer =
false;
6141 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6144 if ( !featureSource || !foundLayer )
6149 const QgsFeatureId fid = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
6162 result = QVariant::fromValue( fet );
6170 bool foundLayer =
false;
6171 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), context, parent, foundLayer );
6174 if ( !featureSource || !foundLayer )
6179 QString cacheValueKey;
6180 if ( values.at( 1 ).type() == QVariant::Map )
6182 QVariantMap attributeMap = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
6184 QMap <QString, QVariant>::const_iterator i = attributeMap.constBegin();
6185 QString filterString;
6186 for ( ; i != attributeMap.constEnd(); ++i )
6188 if ( !filterString.isEmpty() )
6190 filterString.append(
" AND " );
6194 cacheValueKey = QStringLiteral(
"getfeature:%1:%2" ).arg( featureSource->id(), filterString );
6203 QString attribute = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6204 int attributeId = featureSource->fields().lookupField( attribute );
6205 if ( attributeId == -1 )
6210 const QVariant &attVal = values.at( 2 );
6212 cacheValueKey = QStringLiteral(
"getfeature:%1:%2:%3" ).arg( featureSource->id(), QString::number( attributeId ), attVal.toString() );
6235 res = QVariant::fromValue( fet );
6250 if ( !values.isEmpty() )
6253 if ( col && ( values.size() == 1 || !values.at( 1 ).isValid() ) )
6254 fieldName = col->
name();
6255 else if ( values.size() == 2 )
6256 fieldName = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6259 QVariant value = values.at( 0 );
6264 if ( fieldIndex == -1 )
6266 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: Field not found %2" ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6272 QgsVectorLayer *layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), context, parent );
6275 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName, value.toString() );
6284 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer ? layer->id() : QStringLiteral(
"[None]" ), fieldName );
6295 result =
formatter->representValue( layer, fieldIndex, setup.
config(), cache, value );
6302 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: function cannot be evaluated without a context." ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
6310 const QVariant data = values.at( 0 );
6311 const QMimeDatabase db;
6312 return db.mimeTypeForData( data.toByteArray() ).name();
6317 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6319 bool foundLayer =
false;
6320 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [layerProperty](
QgsMapLayer * layer )-> QVariant
6326 if ( QString::compare( layerProperty, QStringLiteral(
"name" ), Qt::CaseInsensitive ) == 0 )
6327 return layer->name();
6328 else if ( QString::compare( layerProperty, QStringLiteral(
"id" ), Qt::CaseInsensitive ) == 0 )
6330 else if ( QString::compare( layerProperty, QStringLiteral(
"title" ), Qt::CaseInsensitive ) == 0 )
6331 return !layer->metadata().title().isEmpty() ? layer->metadata().title() : layer->title();
6332 else if ( QString::compare( layerProperty, QStringLiteral(
"abstract" ), Qt::CaseInsensitive ) == 0 )
6333 return !layer->metadata().abstract().isEmpty() ? layer->metadata().abstract() : layer->abstract();
6334 else if ( QString::compare( layerProperty, QStringLiteral(
"keywords" ), Qt::CaseInsensitive ) == 0 )
6336 QStringList keywords;
6337 const QgsAbstractMetadataBase::KeywordMap keywordMap = layer->metadata().keywords();
6338 for ( auto it = keywordMap.constBegin(); it != keywordMap.constEnd(); ++it )
6340 keywords.append( it.value() );
6342 if ( !keywords.isEmpty() )
6344 return layer->keywordList();
6346 else if ( QString::compare( layerProperty, QStringLiteral(
"data_url" ), Qt::CaseInsensitive ) == 0 )
6348 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution" ), Qt::CaseInsensitive ) == 0 )
6352 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution_url" ), Qt::CaseInsensitive ) == 0 )
6354 else if ( QString::compare( layerProperty, QStringLiteral(
"source" ), Qt::CaseInsensitive ) == 0 )
6356 else if ( QString::compare( layerProperty, QStringLiteral(
"min_scale" ), Qt::CaseInsensitive ) == 0 )
6358 else if ( QString::compare( layerProperty, QStringLiteral(
"max_scale" ), Qt::CaseInsensitive ) == 0 )
6360 else if ( QString::compare( layerProperty, QStringLiteral(
"is_editable" ), Qt::CaseInsensitive ) == 0 )
6362 else if ( QString::compare( layerProperty, QStringLiteral(
"crs" ), Qt::CaseInsensitive ) == 0 )
6364 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_definition" ), Qt::CaseInsensitive ) == 0 )
6366 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_description" ), Qt::CaseInsensitive ) == 0 )
6368 else if ( QString::compare( layerProperty, QStringLiteral(
"extent" ), Qt::CaseInsensitive ) == 0 )
6371 QVariant result = QVariant::fromValue( extentGeom );
6374 else if ( QString::compare( layerProperty, QStringLiteral(
"distance_units" ), Qt::CaseInsensitive ) == 0 )
6376 else if ( QString::compare( layerProperty, QStringLiteral(
"path" ), Qt::CaseInsensitive ) == 0 )
6379 return decodedUri.value( QStringLiteral(
"path" ) );
6381 else if ( QString::compare( layerProperty, QStringLiteral(
"type" ), Qt::CaseInsensitive ) == 0 )
6383 switch ( layer->
type() )
6385 case Qgis::LayerType::Vector:
6386 return QCoreApplication::translate(
"expressions",
"Vector" );
6387 case Qgis::LayerType::Raster:
6388 return QCoreApplication::translate(
"expressions",
"Raster" );
6389 case Qgis::LayerType::Mesh:
6390 return QCoreApplication::translate(
"expressions",
"Mesh" );
6391 case Qgis::LayerType::VectorTile:
6392 return QCoreApplication::translate(
"expressions",
"Vector Tile" );
6393 case Qgis::LayerType::Plugin:
6394 return QCoreApplication::translate(
"expressions",
"Plugin" );
6395 case Qgis::LayerType::Annotation:
6396 return QCoreApplication::translate(
"expressions",
"Annotation" );
6397 case Qgis::LayerType::PointCloud:
6398 return QCoreApplication::translate(
"expressions",
"Point Cloud" );
6399 case Qgis::LayerType::Group:
6400 return QCoreApplication::translate(
"expressions",
"Group" );
6406 QgsVectorLayer *vLayer = qobject_cast< QgsVectorLayer * >( layer );
6409 if ( QString::compare( layerProperty, QStringLiteral(
"storage_type" ), Qt::CaseInsensitive ) == 0 )
6411 else if ( QString::compare( layerProperty, QStringLiteral(
"geometry_type" ), Qt::CaseInsensitive ) == 0 )
6413 else if ( QString::compare( layerProperty, QStringLiteral(
"feature_count" ), Qt::CaseInsensitive ) == 0 )
6429 const QString uriPart = values.at( 1 ).toString();
6431 bool foundLayer =
false;
6433 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, uriPart](
QgsMapLayer * layer )-> QVariant
6435 if ( !layer->dataProvider() )
6437 parent->setEvalErrorString( QObject::tr(
"Layer %1 has invalid data provider" ).arg( layer->name() ) );
6443 if ( !uriPart.isNull() )
6445 return decodedUri.value( uriPart );
6455 parent->
setEvalErrorString( QObject::tr(
"Function `decode_uri` requires a valid layer." ) );
6466 const int band = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6467 const QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6469 bool foundLayer =
false;
6470 const QVariant res = QgsExpressionUtils::runMapLayerFunctionThreadSafe( values.at( 0 ), context, parent, [parent, band, layerProperty](
QgsMapLayer * layer )-> QVariant
6472 QgsRasterLayer *rl = qobject_cast< QgsRasterLayer * >( layer );
6476 if ( band < 1 || band > rl->bandCount() )
6478 parent->setEvalErrorString( QObject::tr(
"Invalid band number %1 for layer" ).arg( band ) );
6484 if ( QString::compare( layerProperty, QStringLiteral(
"avg" ), Qt::CaseInsensitive ) == 0 )
6486 else if ( QString::compare( layerProperty, QStringLiteral(
"stdev" ), Qt::CaseInsensitive ) == 0 )
6488 else if ( QString::compare( layerProperty, QStringLiteral(
"min" ), Qt::CaseInsensitive ) == 0 )
6490 else if ( QString::compare( layerProperty, QStringLiteral(
"max" ), Qt::CaseInsensitive ) == 0 )
6492 else if ( QString::compare( layerProperty, QStringLiteral(
"range" ), Qt::CaseInsensitive ) == 0 )
6494 else if ( QString::compare( layerProperty, QStringLiteral(
"sum" ), Qt::CaseInsensitive ) == 0 )
6498 parent->
setEvalErrorString( QObject::tr(
"Invalid raster statistic: '%1'" ).arg( layerProperty ) );
6524 parent->
setEvalErrorString( QObject::tr(
"Function `raster_statistic` requires a valid raster layer." ) );
6541 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6542 bool ascending = values.value( 1 ).toBool();
6543 std::sort( list.begin(), list.end(), [ascending]( QVariant a, QVariant b ) ->
bool { return ( !ascending ? qgsVariantLessThan( b, a ) : qgsVariantLessThan( a, b ) ); } );
6549 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).length();
6554 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).contains( values.at( 1 ) ) );
6559 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).count( values.at( 1 ) ) );
6564 QVariantList listA = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6565 QVariantList listB = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
6567 for (
const auto &item : listB )
6569 if ( listA.contains( item ) )
6573 return QVariant( match == listB.count() );
6578 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).indexOf( values.at( 1 ) );
6583 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6584 const int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6585 if ( pos < list.length() && pos >= 0 )
return list.at( pos );
6586 else if ( pos < 0 && ( list.length() + pos ) >= 0 )
6587 return list.at( list.length() + pos );
6593 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6594 return list.value( 0 );
6599 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6600 return list.value( list.size() - 1 );
6605 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6606 return list.isEmpty() ? QVariant() : *std::min_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
6611 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6612 return list.isEmpty() ? QVariant() : *std::max_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
6617 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6620 for (
const QVariant &item : list )
6622 switch ( item.userType() )
6624 case QMetaType::Int:
6625 case QMetaType::UInt:
6626 case QMetaType::LongLong:
6627 case QMetaType::ULongLong:
6628 case QMetaType::Float:
6629 case QMetaType::Double:
6630 total += item.toDouble();
6635 return i == 0 ? QVariant() : total / i;
6640 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6641 QVariantList numbers;
6642 for (
const auto &item : list )
6644 switch ( item.userType() )
6646 case QMetaType::Int:
6647 case QMetaType::UInt:
6648 case QMetaType::LongLong:
6649 case QMetaType::ULongLong:
6650 case QMetaType::Float:
6651 case QMetaType::Double:
6652 numbers.append( item );
6656 std::sort( numbers.begin(), numbers.end(), []( QVariant a, QVariant b ) ->
bool { return ( qgsVariantLessThan( a, b ) ); } );
6657 const int count = numbers.count();
6662 else if ( count % 2 )
6664 return numbers.at( count / 2 );
6668 return ( numbers.at( count / 2 - 1 ).toDouble() + numbers.at( count / 2 ).toDouble() ) / 2;
6674 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6677 for (
const QVariant &item : list )
6679 switch ( item.userType() )
6681 case QMetaType::Int:
6682 case QMetaType::UInt:
6683 case QMetaType::LongLong:
6684 case QMetaType::ULongLong:
6685 case QMetaType::Float:
6686 case QMetaType::Double:
6687 total += item.toDouble();
6692 return i == 0 ? QVariant() : total;
6695static QVariant convertToSameType(
const QVariant &value, QVariant::Type type )
6697 QVariant result = value;
6698 result.convert(
static_cast<int>( type ) );
6704 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6705 QHash< QVariant, int > hash;
6706 for (
const auto &item : list )
6710 const QList< int > occurrences = hash.values();
6711 if ( occurrences.empty() )
6712 return QVariantList();
6714 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
6716 const QString option = values.at( 1 ).toString();
6717 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
6719 return convertToSameType( hash.keys( maxValue ), values.at( 0 ).type() );
6721 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
6723 if ( hash.isEmpty() )
6726 return QVariant( hash.key( maxValue ) );
6728 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
6730 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( maxValue ), values.at( 0 ).type() ), context, parent, node );
6732 else if ( option.compare( QLatin1String(
"real_majority" ), Qt::CaseInsensitive ) == 0 )
6734 if ( maxValue * 2 <= list.size() )
6737 return QVariant( hash.key( maxValue ) );
6748 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6749 QHash< QVariant, int > hash;
6750 for (
const auto &item : list )
6754 const QList< int > occurrences = hash.values();
6755 if ( occurrences.empty() )
6756 return QVariantList();
6758 const int minValue = *std::min_element( occurrences.constBegin(), occurrences.constEnd() );
6760 const QString option = values.at( 1 ).toString();
6761 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
6763 return convertToSameType( hash.keys( minValue ), values.at( 0 ).type() );
6765 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
6767 if ( hash.isEmpty() )
6770 return QVariant( hash.key( minValue ) );
6772 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
6774 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( minValue ), values.at( 0 ).type() ), context, parent, node );
6776 else if ( option.compare( QLatin1String(
"real_minority" ), Qt::CaseInsensitive ) == 0 )
6778 if ( hash.isEmpty() )
6782 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
6783 if ( maxValue * 2 > list.size() )
6784 hash.remove( hash.key( maxValue ) );
6786 return convertToSameType( hash.keys(), values.at( 0 ).type() );
6797 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6798 list.append( values.at( 1 ) );
6799 return convertToSameType( list, values.at( 0 ).type() );
6804 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6805 list.prepend( values.at( 1 ) );
6806 return convertToSameType( list, values.at( 0 ).type() );
6811 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6812 list.insert( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), values.at( 2 ) );
6813 return convertToSameType( list, values.at( 0 ).type() );
6818 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6819 int position = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6821 position = position + list.length();
6822 if ( position >= 0 && position < list.length() )
6823 list.removeAt( position );
6824 return convertToSameType( list, values.at( 0 ).type() );
6832 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6834 const QVariant toRemove = values.at( 1 );
6837 list.erase( std::remove_if( list.begin(), list.end(), [](
const QVariant & element )
6839 return QgsVariantUtils::isNull( element );
6844 list.removeAll( toRemove );
6846 return convertToSameType( list, values.at( 0 ).type() );
6851 if ( values.count() == 2 && values.at( 1 ).type() == QVariant::Map )
6853 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
6855 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6856 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
6858 int index = list.indexOf( it.key() );
6859 while ( index >= 0 )
6861 list.replace( index, it.value() );
6862 index = list.indexOf( it.key() );
6866 return convertToSameType( list, values.at( 0 ).type() );
6868 else if ( values.count() == 3 )
6870 QVariantList before;
6872 bool isSingleReplacement =
false;
6874 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).type() != QVariant::StringList )
6876 before = QVariantList() << values.at( 1 );
6880 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
6883 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
6885 after = QVariantList() << values.at( 2 );
6886 isSingleReplacement =
true;
6890 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
6893 if ( !isSingleReplacement && before.length() != after.length() )
6895 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
6899 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6900 for (
int i = 0; i < before.length(); i++ )
6902 int index = list.indexOf( before.at( i ) );
6903 while ( index >= 0 )
6905 list.replace( index, after.at( isSingleReplacement ? 0 : i ) );
6906 index = list.indexOf( before.at( i ) );
6910 return convertToSameType( list, values.at( 0 ).type() );
6914 parent->
setEvalErrorString( QObject::tr(
"Function array_replace requires 2 or 3 arguments" ) );
6921 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6922 QVariantList list_new;
6924 for (
const QVariant &cur : QgsExpressionUtils::getListValue( values.at( 1 ), parent ) )
6926 while ( list.removeOne( cur ) )
6928 list_new.append( cur );
6932 list_new.append( list );
6934 return convertToSameType( list_new, values.at( 0 ).type() );
6940 for (
const QVariant &cur : values )
6942 list += QgsExpressionUtils::getListValue( cur, parent );
6944 return convertToSameType( list, values.at( 0 ).type() );
6949 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6950 int start_pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6951 const int end_pos = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6952 int slice_length = 0;
6954 if ( start_pos < 0 )
6956 start_pos = list.length() + start_pos;
6960 slice_length = end_pos - start_pos + 1;
6964 slice_length = list.length() + end_pos - start_pos + 1;
6967 if ( slice_length < 0 )
6971 list = list.mid( start_pos, slice_length );
6977 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6978 std::reverse( list.begin(), list.end() );
6984 const QVariantList array1 = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6985 const QVariantList array2 = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
6986 for (
const QVariant &cur : array2 )
6988 if ( array1.contains( cur ) )
6989 return QVariant(
true );
6991 return QVariant(
false );
6996 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6998 QVariantList distinct;
7000 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7002 if ( !distinct.contains( *it ) )
7004 distinct += ( *it );
7013 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
7014 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7015 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7019 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
7021 str += ( !( *it ).toString().isEmpty() ) ? ( *it ).toString() : empty;
7022 if ( it != ( array.constEnd() - 1 ) )
7028 return QVariant(
str );
7033 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7034 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7035 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
7037 QStringList list =
str.split( delimiter );
7040 for ( QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
7042 array += ( !( *it ).isEmpty() ) ? *it : empty;
7050 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7051 QJsonDocument document = QJsonDocument::fromJson(
str.toUtf8() );
7052 if ( document.isNull() )
7055 return document.toVariant();
7061 QJsonDocument document = QJsonDocument::fromVariant( values.at( 0 ) );
7062 return QString( document.toJson( QJsonDocument::Compact ) );
7067 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7068 if (
str.isEmpty() )
7069 return QVariantMap();
7077 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7084 for (
int i = 0; i + 1 < values.length(); i += 2 )
7086 result.insert( QgsExpressionUtils::getStringValue( values.at( i ), parent ), values.at( i + 1 ) );
7093 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7094 const QString prefix = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
7095 QVariantMap resultMap;
7097 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7099 resultMap.insert( QString( it.key() ).prepend( prefix ), it.value() );
7107 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).value( values.at( 1 ).toString() );
7112 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).contains( values.at( 1 ).toString() );
7117 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7118 map.remove( values.at( 1 ).toString() );
7124 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7125 map.insert( values.at( 1 ).toString(), values.at( 2 ) );
7132 for (
const QVariant &cur : values )
7134 const QVariantMap curMap = QgsExpressionUtils::getMapValue( cur, parent );
7135 for ( QVariantMap::const_iterator it = curMap.constBegin(); it != curMap.constEnd(); ++it )
7136 result.insert( it.key(), it.value() );
7143 return QStringList( QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).keys() );
7148 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).values();
7153 const QString envVarName = values.at( 0 ).toString();
7154 if ( !QProcessEnvironment::systemEnvironment().contains( envVarName ) )
7157 return QProcessEnvironment::systemEnvironment().value( envVarName );
7162 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7165 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"base_file_name" ) ) );
7168 return QFileInfo( file ).completeBaseName();
7173 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7176 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_suffix" ) ) );
7179 return QFileInfo( file ).completeSuffix();
7184 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7187 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_exists" ) ) );
7190 return QFileInfo::exists( file );
7195 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7198 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_name" ) ) );
7201 return QFileInfo( file ).fileName();
7206 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7209 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_file" ) ) );
7212 return QFileInfo( file ).isFile();
7217 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7220 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_directory" ) ) );
7223 return QFileInfo( file ).isDir();
7228 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7231 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_path" ) ) );
7234 return QDir::toNativeSeparators( QFileInfo( file ).path() );
7239 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), context, parent );
7242 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_size" ) ) );
7245 return QFileInfo( file ).size();
7248static QVariant fcnHash(
const QString &
str,
const QCryptographicHash::Algorithm
algorithm )
7250 return QString( QCryptographicHash::hash(
str.toUtf8(),
algorithm ).toHex() );
7256 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7257 QString method = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).toLower();
7259 if ( method == QLatin1String(
"md4" ) )
7261 hash = fcnHash(
str, QCryptographicHash::Md4 );
7263 else if ( method == QLatin1String(
"md5" ) )
7265 hash = fcnHash(
str, QCryptographicHash::Md5 );
7267 else if ( method == QLatin1String(
"sha1" ) )
7269 hash = fcnHash(
str, QCryptographicHash::Sha1 );
7271 else if ( method == QLatin1String(
"sha224" ) )
7273 hash = fcnHash(
str, QCryptographicHash::Sha224 );
7275 else if ( method == QLatin1String(
"sha256" ) )
7277 hash = fcnHash(
str, QCryptographicHash::Sha256 );
7279 else if ( method == QLatin1String(
"sha384" ) )
7281 hash = fcnHash(
str, QCryptographicHash::Sha384 );
7283 else if ( method == QLatin1String(
"sha512" ) )
7285 hash = fcnHash(
str, QCryptographicHash::Sha512 );
7287 else if ( method == QLatin1String(
"sha3_224" ) )
7289 hash = fcnHash(
str, QCryptographicHash::Sha3_224 );
7291 else if ( method == QLatin1String(
"sha3_256" ) )
7293 hash = fcnHash(
str, QCryptographicHash::Sha3_256 );
7295 else if ( method == QLatin1String(
"sha3_384" ) )
7297 hash = fcnHash(
str, QCryptographicHash::Sha3_384 );
7299 else if ( method == QLatin1String(
"sha3_512" ) )
7301 hash = fcnHash(
str, QCryptographicHash::Sha3_512 );
7303 else if ( method == QLatin1String(
"keccak_224" ) )
7305 hash = fcnHash(
str, QCryptographicHash::Keccak_224 );
7307 else if ( method == QLatin1String(
"keccak_256" ) )
7309 hash = fcnHash(
str, QCryptographicHash::Keccak_256 );
7311 else if ( method == QLatin1String(
"keccak_384" ) )
7313 hash = fcnHash(
str, QCryptographicHash::Keccak_384 );
7315 else if ( method == QLatin1String(
"keccak_512" ) )
7317 hash = fcnHash(
str, QCryptographicHash::Keccak_512 );
7321 parent->
setEvalErrorString( QObject::tr(
"Hash method %1 is not available on this system." ).arg(
str ) );
7328 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Md5 );
7333 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Sha256 );
7338 const QByteArray input = values.at( 0 ).toByteArray();
7339 return QVariant( QString( input.toBase64() ) );
7344 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
7346 for (
auto it = map.cbegin(); it != map.cend(); it++ )
7348 query.addQueryItem( it.key(), it.value().toString() );
7350 return query.toString( QUrl::ComponentFormattingOption::FullyEncoded );
7355 const QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
7356 const QByteArray base64 = value.toLocal8Bit();
7357 const QByteArray decoded = QByteArray::fromBase64( base64 );
7358 return QVariant( decoded );
7363static 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 )
7366 const QVariant sourceLayerRef = context->
variable( QStringLiteral(
"layer" ) );
7369 QgsVectorLayer *sourceLayer = QgsExpressionUtils::getVectorLayer( sourceLayerRef, context, parent );
7378 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
7381 const bool layerCanBeCached = node->
isStatic( parent, context );
7382 QVariant targetLayerValue = node->
eval( parent, context );
7386 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
7388 QString subExpString = node->dump();
7390 bool testOnly = ( subExpString ==
"NULL" );
7393 QgsVectorLayer *targetLayer = QgsExpressionUtils::getVectorLayer( targetLayerValue, context, parent );
7397 parent->
setEvalErrorString( QObject::tr(
"Layer '%1' could not be loaded." ).arg( targetLayerValue.toString() ) );
7402 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
7404 QString filterString = node->dump();
7405 if ( filterString !=
"NULL" )
7407 request.setFilterExpression( filterString );
7411 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
7413 QVariant limitValue = node->eval( parent, context );
7415 qlonglong limit = QgsExpressionUtils::getIntValue( limitValue, parent );
7418 double max_distance = 0;
7419 if ( isNearestFunc )
7421 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
7423 QVariant distanceValue = node->eval( parent, context );
7425 max_distance = QgsExpressionUtils::getDoubleValue( distanceValue, parent );
7429 node = QgsExpressionUtils::getNode( values.at( isNearestFunc ? 5 : 4 ), parent );
7431 QVariant cacheValue = node->eval( parent, context );
7433 bool cacheEnabled = cacheValue.toBool();
7439 double minOverlap { -1 };
7440 double minInscribedCircleRadius { -1 };
7441 bool returnDetails =
false;
7442 bool sortByMeasure =
false;
7443 bool sortAscending =
false;
7444 bool requireMeasures =
false;
7445 bool overlapOrRadiusFilter =
false;
7446 if ( isIntersectsFunc )
7449 node = QgsExpressionUtils::getNode( values.at( 5 ), parent );
7451 const QVariant minOverlapValue = node->eval( parent, context );
7453 minOverlap = QgsExpressionUtils::getDoubleValue( minOverlapValue, parent );
7454 node = QgsExpressionUtils::getNode( values.at( 6 ), parent );
7456 const QVariant minInscribedCircleRadiusValue = node->eval( parent, context );
7458 minInscribedCircleRadius = QgsExpressionUtils::getDoubleValue( minInscribedCircleRadiusValue, parent );
7459 node = QgsExpressionUtils::getNode( values.at( 7 ), parent );
7461 returnDetails = !testOnly && node->eval( parent, context ).toBool();
7462 node = QgsExpressionUtils::getNode( values.at( 8 ), parent );
7464 const QString sorting { node->eval( parent, context ).toString().toLower() };
7465 sortByMeasure = !testOnly && ( sorting.startsWith(
"asc" ) || sorting.startsWith(
"des" ) );
7466 sortAscending = sorting.startsWith(
"asc" );
7467 requireMeasures = sortByMeasure || returnDetails;
7468 overlapOrRadiusFilter = minInscribedCircleRadius != -1 || minOverlap != -1;
7475 if ( sourceLayer && targetLayer->crs() != sourceLayer->crs() )
7478 request.setDestinationCrs( sourceLayer->crs(), TransformContext );
7481 bool sameLayers = ( sourceLayer && sourceLayer->id() == targetLayer->id() );
7484 if ( bboxGrow != 0 )
7486 intDomain.
grow( bboxGrow );
7489 const QString cacheBase { QStringLiteral(
"%1:%2:%3" ).arg( targetLayer->id(), subExpString, filterString ) };
7495 QList<QgsFeature> features;
7496 if ( isNearestFunc || ( layerCanBeCached && cacheEnabled ) )
7500 const QString cacheLayer { QStringLiteral(
"ovrlaylyr:%1" ).arg( cacheBase ) };
7501 const QString cacheIndex { QStringLiteral(
"ovrlayidx:%1" ).arg( cacheBase ) };
7505 cachedTarget = targetLayer->
materialize( request );
7506 if ( layerCanBeCached )
7507 context->
setCachedValue( cacheLayer, QVariant::fromValue( cachedTarget ) );
7517 if ( layerCanBeCached )
7518 context->
setCachedValue( cacheIndex, QVariant::fromValue( spatialIndex ) );
7525 QList<QgsFeatureId> fidsList;
7526 if ( isNearestFunc )
7528 fidsList = spatialIndex.
nearestNeighbor( geometry, sameLayers ? limit + 1 : limit, max_distance );
7532 fidsList = spatialIndex.
intersects( intDomain );
7535 QListIterator<QgsFeatureId> i( fidsList );
7536 while ( i.hasNext() )
7539 if ( sameLayers && feat.
id() == fId2 )
7541 features.append( cachedTarget->
getFeature( fId2 ) );
7549 request.setFilterRect( intDomain );
7554 if ( sameLayers && feat.
id() == feat2.
id() )
7556 features.append( feat2 );
7564 const QString expCacheKey { QStringLiteral(
"exp:%1" ).arg( cacheBase ) };
7565 const QString ctxCacheKey { QStringLiteral(
"ctx:%1" ).arg( cacheBase ) };
7571 subExpression.
prepare( &subContext );
7584 auto testLinestring = [ = ](
const QgsGeometry intersection,
double & overlapValue ) ->
bool
7586 bool testResult {
false };
7588 QVector<double> overlapValues;
7591 const QgsCurve *geom = qgsgeometry_cast< const QgsCurve * >( *it );
7593 if ( minOverlap != -1 || requireMeasures )
7595 overlapValue = geom->
length();
7596 overlapValues.append( overlapValue );
7597 if ( minOverlap != -1 )
7599 if ( overlapValue >= minOverlap )
7611 if ( ! overlapValues.isEmpty() )
7613 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
7620 auto testPolygon = [ = ](
const QgsGeometry intersection,
double & radiusValue,
double & overlapValue ) ->
bool
7623 bool testResult {
false };
7625 QVector<double> overlapValues;
7626 QVector<double> radiusValues;
7629 const QgsCurvePolygon *geom = qgsgeometry_cast< const QgsCurvePolygon * >( *it );
7631 if ( minOverlap != -1 || requireMeasures )
7633 overlapValue = geom->
area();
7634 overlapValues.append( geom->
area() );
7635 if ( minOverlap != - 1 )
7637 if ( overlapValue >= minOverlap )
7649 if ( minInscribedCircleRadius != -1 || requireMeasures )
7652 const double width = bbox.
width();
7653 const double height = bbox.
height();
7654 const double size = width > height ? width : height;
7655 const double tolerance = size / 100.0;
7657 testResult = radiusValue >= minInscribedCircleRadius;
7658 radiusValues.append( radiusValues );
7663 if ( !radiusValues.isEmpty() )
7665 radiusValue = *std::max_element( radiusValues.cbegin(), radiusValues.cend() );
7668 if ( ! overlapValues.isEmpty() )
7670 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
7680 QVariantList results;
7682 QListIterator<QgsFeature> i( features );
7683 while ( i.hasNext() && ( sortByMeasure || limit == -1 || foundCount < limit ) )
7689 if ( ! relationFunction || ( geometry.*relationFunction )( feat2.
geometry() ) )
7692 double overlapValue = -1;
7693 double radiusValue = -1;
7695 if ( isIntersectsFunc && ( requireMeasures || overlapOrRadiusFilter ) )
7702 switch ( intersection.
type() )
7705 case Qgis::GeometryType::Polygon:
7709 bool testResult { testPolygon( intersection, radiusValue, overlapValue ) };
7711 if ( ! testResult && overlapOrRadiusFilter )
7719 case Qgis::GeometryType::Line:
7724 if ( minInscribedCircleRadius != -1 )
7730 const bool testResult { testLinestring( intersection, overlapValue ) };
7732 if ( ! testResult && overlapOrRadiusFilter )
7740 case Qgis::GeometryType::Point:
7745 if ( minInscribedCircleRadius != -1 )
7750 bool testResult {
false };
7751 if ( minOverlap != -1 || requireMeasures )
7759 if ( geometry.
type() == Qgis::GeometryType::Point )
7763 case Qgis::GeometryType::Unknown:
7764 case Qgis::GeometryType::Null:
7765 case Qgis::GeometryType::Point:
7769 case Qgis::GeometryType::Line:
7771 testResult = testLinestring( feat2.
geometry(), overlapValue );
7774 case Qgis::GeometryType::Polygon:
7776 testResult = testPolygon( feat2.
geometry(), radiusValue, overlapValue );
7782 if ( ! testResult && overlapOrRadiusFilter )
7791 case Qgis::GeometryType::Null:
7792 case Qgis::GeometryType::Unknown:
7810 const QVariant expResult = subExpression.
evaluate( &subContext );
7812 if ( requireMeasures )
7814 QVariantMap resultRecord;
7815 resultRecord.insert( QStringLiteral(
"id" ), feat2.
id() );
7816 resultRecord.insert( QStringLiteral(
"result" ), expResult );
7818 resultRecord.insert( QStringLiteral(
"overlap" ), overlapValue );
7820 if ( radiusValue != -1 )
7822 resultRecord.insert( QStringLiteral(
"radius" ), radiusValue );
7824 results.append( resultRecord );
7828 results.append( expResult );
7834 results.append( feat2.
id() );
7848 if ( requireMeasures )
7850 if ( sortByMeasure )
7852 std::sort( results.begin(), results.end(), [ sortAscending ](
const QVariant & recordA,
const QVariant & recordB ) ->
bool
7854 return sortAscending ?
7855 recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble()
7856 : recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble();
7860 if ( limit > 0 && results.size() > limit )
7862 results.erase( results.begin() + limit );
7865 if ( ! returnDetails )
7867 QVariantList expResults;
7868 for (
auto it = results.constBegin(); it != results.constEnd(); ++it )
7870 expResults.append( it->toMap().value( QStringLiteral(
"result" ) ) );
7880 QVariantList disjoint_results;
7889 if ( !results.contains( feat2.
id() ) )
7892 disjoint_results.append( subExpression.
evaluate( &subContext ) );
7895 return disjoint_results;
7938 return executeGeomOverlay( values, context, parent,
nullptr,
false, 0,
true );
7947 static QRecursiveMutex sFunctionsMutex;
7948 QMutexLocker locker( &sFunctionsMutex );
7950 QList<QgsExpressionFunction *> &functions = *sFunctions();
7952 if ( functions.isEmpty() )
7989 functions << randFunc;
7993 functions << randfFunc;
7996 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max" ), -1, fcnMax, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
7997 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min" ), -1, fcnMin, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8003 <<
new QgsStaticExpressionFunction( QStringLiteral(
"pi" ), 0, fcnPi, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$pi" ) )
8007 <<
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" ) )
8008 <<
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" ) )
8009 <<
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" ) )
8014 <<
new QgsStaticExpressionFunction( QStringLiteral(
"coalesce" ), -1, fcnCoalesce, QStringLiteral(
"Conditionals" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8028 QStringLiteral(
"Aggregates" ),
8037 if ( !node->
args() )
8040 QSet<QString> referencedVars;
8043 QgsExpressionNode *subExpressionNode = node->args()->at( 2 );
8044 referencedVars = subExpressionNode->referencedVariables();
8049 QgsExpressionNode *filterNode = node->args()->at( 3 );
8050 referencedVars.unite( filterNode->referencedVariables() );
8052 return referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() );
8061 if ( !node->
args() )
8062 return QSet<QString>();
8064 QSet<QString> referencedCols;
8065 QSet<QString> referencedVars;
8080 if ( referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() ) )
8083 return referencedCols;
8096 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count" ), aggParams, fcnAggregateCount, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8097 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_distinct" ), aggParams, fcnAggregateCountDistinct, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8098 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_missing" ), aggParams, fcnAggregateCountMissing, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8099 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minimum" ), aggParams, fcnAggregateMin, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8100 <<
new QgsStaticExpressionFunction( QStringLiteral(
"maximum" ), aggParams, fcnAggregateMax, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8101 <<
new QgsStaticExpressionFunction( QStringLiteral(
"sum" ), aggParams, fcnAggregateSum, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8102 <<
new QgsStaticExpressionFunction( QStringLiteral(
"mean" ), aggParams, fcnAggregateMean, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8103 <<
new QgsStaticExpressionFunction( QStringLiteral(
"median" ), aggParams, fcnAggregateMedian, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8104 <<
new QgsStaticExpressionFunction( QStringLiteral(
"stdev" ), aggParams, fcnAggregateStdev, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8105 <<
new QgsStaticExpressionFunction( QStringLiteral(
"range" ), aggParams, fcnAggregateRange, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8106 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minority" ), aggParams, fcnAggregateMinority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8107 <<
new QgsStaticExpressionFunction( QStringLiteral(
"majority" ), aggParams, fcnAggregateMajority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8108 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q1" ), aggParams, fcnAggregateQ1, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8109 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q3" ), aggParams, fcnAggregateQ3, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8110 <<
new QgsStaticExpressionFunction( QStringLiteral(
"iqr" ), aggParams, fcnAggregateIQR, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8111 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min_length" ), aggParams, fcnAggregateMinLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8112 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max_length" ), aggParams, fcnAggregateMaxLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8113 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect" ), aggParams, fcnAggregateCollectGeometry, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8114 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate" ), aggParamsConcat, fcnAggregateStringConcat, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8115 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate_unique" ), aggParamsConcat, fcnAggregateStringConcatUnique, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8116 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array_agg" ), aggParamsArray, fcnAggregateArray, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
8121 <<
new QgsStaticExpressionFunction( QStringLiteral(
"now" ), 0, fcnNow, QStringLiteral(
"Date and Time" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$now" ) )
8124 fcnAge, QStringLiteral(
"Date and Time" ) )
8138 fcnMakeDate, QStringLiteral(
"Date and Time" ) )
8142 fcnMakeTime, QStringLiteral(
"Date and Time" ) )
8149 fcnMakeDateTime, QStringLiteral(
"Date and Time" ) )
8157 fcnMakeInterval, QStringLiteral(
"Date and Time" ) )
8176 false, QSet< QString >(),
false, QStringList(), true )
8177 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concat" ), -1, fcnConcat, QStringLiteral(
"String" ), QString(),
false, QSet<QString>(),
false, QStringList(), true )
8195 fcnColorMixRgb, QStringLiteral(
"Color" ) )
8199 fcnColorRgb, QStringLiteral(
"Color" ) )
8204 fncColorRgba, QStringLiteral(
"Color" ) )
8210 fcnCreateRamp, QStringLiteral(
"Color" ) )
8214 fcnColorHsl, QStringLiteral(
"Color" ) )
8219 fncColorHsla, QStringLiteral(
"Color" ) )
8223 fcnColorHsv, QStringLiteral(
"Color" ) )
8228 fncColorHsva, QStringLiteral(
"Color" ) )
8233 fcnColorCmyk, QStringLiteral(
"Color" ) )
8239 fncColorCmyka, QStringLiteral(
"Color" ) )
8242 fncColorPart, QStringLiteral(
"Color" ) )
8245 fncDarker, QStringLiteral(
"Color" ) )
8248 fncLighter, QStringLiteral(
"Color" ) )
8253 fcnBaseFileName, QStringLiteral(
"Files and Paths" ) )
8255 fcnFileSuffix, QStringLiteral(
"Files and Paths" ) )
8257 fcnFileExists, QStringLiteral(
"Files and Paths" ) )
8259 fcnFileName, QStringLiteral(
"Files and Paths" ) )
8261 fcnPathIsFile, QStringLiteral(
"Files and Paths" ) )
8263 fcnPathIsDir, QStringLiteral(
"Files and Paths" ) )
8265 fcnFilePath, QStringLiteral(
"Files and Paths" ) )
8267 fcnFileSize, QStringLiteral(
"Files and Paths" ) )
8270 fcnExif, QStringLiteral(
"Files and Paths" ) )
8272 fcnExifGeoTag, QStringLiteral(
"GeometryGroup" ) )
8276 fcnGenericHash, QStringLiteral(
"Conversions" ) )
8278 fcnHashMd5, QStringLiteral(
"Conversions" ) )
8280 fcnHashSha256, QStringLiteral(
"Conversions" ) )
8284 fcnToBase64, QStringLiteral(
"Conversions" ) )
8286 fcnFromBase64, QStringLiteral(
"Conversions" ) )
8292 geomFunc->setIsStatic(
false );
8293 functions << geomFunc;
8297 functions << areaFunc;
8303 functions << lengthFunc;
8307 functions << perimeterFunc;
8313 fcnRoundness, QStringLiteral(
"GeometryGroup" ) );
8327 QMap< QString, QgsExpressionFunction::FcnEval > geometry_overlay_definitions
8329 { QStringLiteral(
"overlay_intersects" ), fcnGeomOverlayIntersects },
8330 { QStringLiteral(
"overlay_contains" ), fcnGeomOverlayContains },
8331 { QStringLiteral(
"overlay_crosses" ), fcnGeomOverlayCrosses },
8332 { QStringLiteral(
"overlay_equals" ), fcnGeomOverlayEquals },
8333 { QStringLiteral(
"overlay_touches" ), fcnGeomOverlayTouches },
8334 { QStringLiteral(
"overlay_disjoint" ), fcnGeomOverlayDisjoint },
8335 { QStringLiteral(
"overlay_within" ), fcnGeomOverlayWithin },
8337 QMapIterator< QString, QgsExpressionFunction::FcnEval > i( geometry_overlay_definitions );
8338 while ( i.hasNext() )
8355 functions << fcnGeomOverlayFunc;
8368 functions << fcnGeomOverlayNearestFunc;
8381 fcnNodesToPoints, QStringLiteral(
"GeometryGroup" ) )
8383 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect_geometries" ), -1, fcnCollectGeometries, QStringLiteral(
"GeometryGroup" ) )
8388 fcnMakePointM, QStringLiteral(
"GeometryGroup" ) )
8394 fcnMakeTriangle, QStringLiteral(
"GeometryGroup" ) )
8399 fcnMakeCircle, QStringLiteral(
"GeometryGroup" ) )
8406 fcnMakeEllipse, QStringLiteral(
"GeometryGroup" ) )
8412 fcnMakeRegularPolygon, QStringLiteral(
"GeometryGroup" ) )
8416 fcnMakeSquare, QStringLiteral(
"GeometryGroup" ) )
8422 fcnMakeRectangleFrom3Points, QStringLiteral(
"GeometryGroup" ) )
8426#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
8432 }, fcnGeomMakeValid, QStringLiteral(
"GeometryGroup" ) );
8441 functions << xAtFunc;
8446 functions << yAtFunc;
8462 fcnDisjoint, QStringLiteral(
"GeometryGroup" ) )
8465 fcnIntersects, QStringLiteral(
"GeometryGroup" ) )
8468 fcnTouches, QStringLiteral(
"GeometryGroup" ) )
8471 fcnCrosses, QStringLiteral(
"GeometryGroup" ) )
8474 fcnContains, QStringLiteral(
"GeometryGroup" ) )
8477 fcnOverlaps, QStringLiteral(
"GeometryGroup" ) )
8480 fcnWithin, QStringLiteral(
"GeometryGroup" ) )
8484 fcnTranslate, QStringLiteral(
"GeometryGroup" ) )
8489 fcnRotate, QStringLiteral(
"GeometryGroup" ) )
8494 fcnScale, QStringLiteral(
"GeometryGroup" ) )
8505 fcnAffineTransform, QStringLiteral(
"GeometryGroup" ) )
8512 fcnBuffer, QStringLiteral(
"GeometryGroup" ) )
8514 fcnForceRHR, QStringLiteral(
"GeometryGroup" ) )
8516 fcnForcePolygonCW, QStringLiteral(
"GeometryGroup" ) )
8518 fcnForcePolygonCCW, QStringLiteral(
"GeometryGroup" ) )
8528 , fcnTaperedBuffer, QStringLiteral(
"GeometryGroup" ) )
8531 , fcnBufferByM, QStringLiteral(
"GeometryGroup" ) )
8537 fcnOffsetCurve, QStringLiteral(
"GeometryGroup" ) )
8543 fcnSingleSidedBuffer, QStringLiteral(
"GeometryGroup" ) )
8547 fcnExtend, QStringLiteral(
"GeometryGroup" ) )
8556 fcnInteriorRingN, QStringLiteral(
"GeometryGroup" ) )
8559 fcnGeometryN, QStringLiteral(
"GeometryGroup" ) )
8566 }, fcnSharedPaths, QStringLiteral(
"GeometryGroup" ) )
8580 }, fcnTriangularWave, QStringLiteral(
"GeometryGroup" ) )
8589 }, fcnTriangularWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
8596 }, fcnSquareWave, QStringLiteral(
"GeometryGroup" ) )
8605 }, fcnSquareWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
8612 }, fcnRoundWave, QStringLiteral(
"GeometryGroup" ) )
8621 }, fcnRoundWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
8630 }, fcnApplyDashPattern, QStringLiteral(
"GeometryGroup" ) )
8635 }, fcnDensifyByCount, QStringLiteral(
"GeometryGroup" ) )
8640 }, fcnDensifyByDistance, QStringLiteral(
"GeometryGroup" ) )
8652#
if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
8659 fcnOrientedBBox, QStringLiteral(
"GeometryGroup" ) )
8662 fcnMainAngle, QStringLiteral(
"GeometryGroup" ) )
8666 fcnMinimalCircle, QStringLiteral(
"GeometryGroup" ) )
8669 fcnDifference, QStringLiteral(
"GeometryGroup" ) )
8672 fcnDistance, QStringLiteral(
"GeometryGroup" ) )
8675 fcnHausdorffDistance, QStringLiteral(
"GeometryGroup" ) )
8678 fcnIntersection, QStringLiteral(
"GeometryGroup" ) )
8681 fcnSymDifference, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"symDifference" ) )
8684 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
8687 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
8690 fcnGeomToWKT, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"geomToWKT" ) )
8692 fcnGeomToWKB, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false )
8697 fcnTransformGeometry, QStringLiteral(
"GeometryGroup" ) )
8701 fcnExtrude, QStringLiteral(
"GeometryGroup" ), QString() )
8703 fcnGeomIsMultipart, QStringLiteral(
"GeometryGroup" ) )
8705 fcnZMax, QStringLiteral(
"GeometryGroup" ) )
8707 fcnZMin, QStringLiteral(
"GeometryGroup" ) )
8709 fcnMMax, QStringLiteral(
"GeometryGroup" ) )
8711 fcnMMin, QStringLiteral(
"GeometryGroup" ) )
8713 fcnSinuosity, QStringLiteral(
"GeometryGroup" ) )
8715 fcnStraightDistance2d, QStringLiteral(
"GeometryGroup" ) );
8721 fcnOrderParts, QStringLiteral(
"GeometryGroup" ), QString() );
8726 const QList< QgsExpressionNode *> argList = node->
args()->list();
8729 if ( !argNode->isStatic( parent, context ) )
8735 QgsExpressionNode *argNode = node->args()->at( 1 );
8737 QString expString = argNode->eval( parent, context ).toString();
8739 QgsExpression e( expString );
8741 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
8752 QgsExpressionNode *argNode = node->args()->at( 1 );
8753 QString expression = argNode->eval( parent, context ).toString();
8754 QgsExpression e( expression );
8755 e.prepare( context );
8756 context->setCachedValue( expression, QVariant::fromValue( e ) );
8761 functions << orderPartsFunc;
8766 fcnClosestPoint, QStringLiteral(
"GeometryGroup" ) )
8769 fcnShortestLine, QStringLiteral(
"GeometryGroup" ) )
8788 functions << idFunc;
8792 functions << currentFeatureFunc;
8794 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" ) );
8796 functions << uuidFunc;
8803 fcnGetFeature, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"QgsExpressionUtils::getFeature" ) )
8806 fcnGetFeatureById, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false );
8811 functions << attributesFunc;
8815 functions << representAttributesFunc;
8823 functions << validateFeature;
8832 functions << validateAttribute;
8835 QStringLiteral(
"maptip" ),
8838 QStringLiteral(
"Record and Attributes" ),
8844 functions << maptipFunc;
8847 QStringLiteral(
"display_expression" ),
8849 fcnFeatureDisplayExpression,
8850 QStringLiteral(
"Record and Attributes" ),
8856 functions << displayFunc;
8859 QStringLiteral(
"is_selected" ),
8862 QStringLiteral(
"Record and Attributes" ),
8868 functions << isSelectedFunc;
8872 QStringLiteral(
"num_selected" ),
8875 QStringLiteral(
"Record and Attributes" ),
8883 QStringLiteral(
"sqlite_fetch_and_increment" ),
8891 fcnSqliteFetchAndIncrement,
8892 QStringLiteral(
"Record and Attributes" )
8910 parent->
setEvalErrorString( tr(
"If represent_value is called with 1 parameter, it must be an attribute." ) );
8920 parent->
setEvalErrorString( tr(
"represent_value must be called with exactly 1 or 2 parameters." ) );
8926 functions << representValueFunc;
8932 fcnGetLayerProperty, QStringLiteral(
"Map Layers" ) )
8937 fcnDecodeUri, QStringLiteral(
"Map Layers" ) )
8941 fcnMimeType, QStringLiteral(
"General" ) )
8958 QgsExpressionNode *argNode = node->args()->at( 0 );
8960 if ( !argNode->isStatic( parent, context ) )
8963 const QString varName = argNode->eval( parent, context ).toString();
8964 if ( varName == QLatin1String(
"feature" ) || varName == QLatin1String(
"id" ) || varName == QLatin1String(
"geometry" ) )
8967 const QgsExpressionContextScope *scope = context->activeScopeForVariable( varName );
8968 return scope ? scope->isStatic( varName ) : false;
8976 if ( node && node->
args()->
count() > 0 )
8978 QgsExpressionNode *argNode = node->args()->at( 0 );
8979 if ( QgsExpressionNodeLiteral *literal = dynamic_cast<QgsExpressionNodeLiteral *>( argNode ) )
8981 if ( literal->value() == QLatin1String(
"geometry" ) || literal->value() == QLatin1String(
"feature" ) )
9000 QgsExpressionNode *argNode = node->args()->at( 0 );
9002 if ( argNode->isStatic( parent, context ) )
9004 QString expString = argNode->eval( parent, context ).toString();
9006 QgsExpression e( expString );
9008 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
9016 functions << evalFunc;
9022 const QList< QgsExpressionNode *> argList = node->
args()->list();
9025 if ( !argNode->isStatic( parent, context ) )
9037 functions << attributeFunc;
9048 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array" ), -1, fcnArray, QStringLiteral(
"Arrays" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
9097 fcnMapPrefixKeys, QStringLiteral(
"Maps" ) )
9099 fcnMapToHtmlTable, QStringLiteral(
"Maps" ) )
9101 fcnMapToHtmlDefinitionList, QStringLiteral(
"Maps" ) )
9103 fcnToFormUrlEncode, QStringLiteral(
"Maps" ) )
9112 *sOwnedFunctions() << func;
9113 *sBuiltinFunctions() << func->name();
9114 sBuiltinFunctions()->append( func->aliases() );
9127 sFunctions()->append( function );
9128 if ( transferOwnership )
9129 sOwnedFunctions()->append( function );
9143 sFunctions()->removeAt( fnIdx );
9151 qDeleteAll( *sOwnedFunctions() );
9152 sOwnedFunctions()->clear();
9157 if ( sBuiltinFunctions()->isEmpty() )
9161 return *sBuiltinFunctions();
9169 QStringLiteral(
"Arrays" ) )
9180 if ( args->
count() < 2 )
9183 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9193 QVariantList result;
9195 if ( args->
count() < 2 )
9199 QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9202 std::unique_ptr< QgsExpressionContext > tempContext;
9205 tempContext = std::make_unique< QgsExpressionContext >();
9206 subContext = tempContext.get();
9212 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
9215 result << args->
at( 1 )->
eval( parent, subContext );
9240 if ( args->
count() < 2 )
9244 args->
at( 0 )->
prepare( parent, context );
9248 subContext = *context;
9254 args->
at( 1 )->
prepare( parent, &subContext );
9264 QStringLiteral(
"Arrays" ) )
9275 if ( args->
count() < 2 )
9278 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9288 QVariantList result;
9290 if ( args->
count() < 2 )
9294 const QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
9297 std::unique_ptr< QgsExpressionContext > tempContext;
9300 tempContext = std::make_unique< QgsExpressionContext >();
9301 subContext = tempContext.get();
9308 if ( args->
count() >= 3 )
9310 const QVariant limitVar = args->
at( 2 )->
eval( parent, context );
9312 if ( QgsExpressionUtils::isIntSafe( limitVar ) )
9314 limit = limitVar.toInt();
9322 for (
const QVariant &value : array )
9325 if ( args->
at( 1 )->
eval( parent, subContext ).toBool() )
9329 if ( limit > 0 && limit == result.size() )
9356 if ( args->
count() < 2 )
9360 args->
at( 0 )->
prepare( parent, context );
9364 subContext = *context;
9370 args->
at( 1 )->
prepare( parent, &subContext );
9379 QStringLiteral(
"General" ) )
9390 if ( args->
count() < 3 )
9394 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
9396 QVariant
name = args->
at( 0 )->
eval( parent, context );
9397 QVariant value = args->
at( 1 )->
eval( parent, context );
9400 appendTemporaryVariable( context,
name.toString(), value );
9401 if ( args->
at( 2 )->
isStatic( parent, context ) )
9403 popTemporaryVariable( context );
9414 if ( args->
count() < 3 )
9418 QVariant
name = args->
at( 0 )->
eval( parent, context );
9419 QVariant value = args->
at( 1 )->
eval( parent, context );
9422 std::unique_ptr< QgsExpressionContext > tempContext;
9423 if ( !updatedContext )
9425 tempContext = std::make_unique< QgsExpressionContext >();
9426 updatedContext = tempContext.get();
9429 appendTemporaryVariable( updatedContext,
name.toString(), value );
9430 result = args->
at( 2 )->
eval( parent, updatedContext );
9433 popTemporaryVariable( updatedContext );
9454 if ( args->
count() < 3 )
9459 QVariant value = args->
at( 1 )->
prepare( parent, context );
9462 std::unique_ptr< QgsExpressionContext > tempContext;
9463 if ( !updatedContext )
9465 tempContext = std::make_unique< QgsExpressionContext >();
9466 updatedContext = tempContext.get();
9469 appendTemporaryVariable( updatedContext,
name.toString(), value );
9470 args->
at( 2 )->
prepare( parent, updatedContext );
9473 popTemporaryVariable( updatedContext );
9478void QgsWithVariableExpressionFunction::popTemporaryVariable(
const QgsExpressionContext *context )
const
9484void 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 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.