67#include <QMimeDatabase>
68#include <QProcessEnvironment>
69#include <QCryptographicHash>
70#include <QRegularExpression>
93 QVariantList argValues;
97 const QList< QgsExpressionNode * > argList = args->
list();
104 v = QVariant::fromValue( n );
108 v = n->eval( parent, context );
110 bool defaultParamIsNull = mParameterList.count() > arg && mParameterList.at( arg ).optional() && !mParameterList.at( arg ).defaultValue().isValid();
111 if ( QgsExpressionUtils::isNull( v ) && !defaultParamIsNull && !
handlesNull() )
114 argValues.append( v );
119 return func( argValues, context, parent, node );
130 return QStringList();
157 return mGroups.isEmpty() ? false : mGroups.contains( QStringLiteral(
"deprecated" ) );
162 return ( QString::compare( mName, other.mName, Qt::CaseInsensitive ) == 0 );
174 const QString &group,
175 const QString &helpText,
179 const QStringList &aliases,
183 , mAliases( aliases )
184 , mUsesGeometry( false )
185 , mUsesGeometryFunc( usesGeometry )
186 , mReferencedColumnsFunc( referencedColumns )
198 if ( mUsesGeometryFunc )
199 return mUsesGeometryFunc( node );
201 return mUsesGeometry;
211 if ( mReferencedColumnsFunc )
212 return mReferencedColumnsFunc( node );
214 return mReferencedColumns;
220 return mIsStaticFunc( node, parent, context );
228 return mPrepareFunc( node, parent, context );
240 mIsStaticFunc =
nullptr;
246 mPrepareFunc = prepareFunc;
251 if ( node && node->
args() )
253 const QList< QgsExpressionNode * > argList = node->
args()->
list();
256 if ( !argNode->isStatic( parent, context ) )
266 double start = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
267 double stop = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
268 double step = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
270 if ( step == 0.0 || ( step > 0.0 && start > stop ) || ( step < 0.0 && start < stop ) )
277 double current = start + step;
278 while ( ( ( step > 0.0 && current <= stop ) || ( step < 0.0 && current >= stop ) ) && length <= 1000000 )
293 const QString name = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
295 if ( name == QLatin1String(
"feature" ) )
297 return context->
hasFeature() ? QVariant::fromValue( context->
feature() ) : QVariant();
299 else if ( name == QLatin1String(
"id" ) )
301 return context->
hasFeature() ? QVariant::fromValue( context->
feature().
id() ) : QVariant();
303 else if ( name == QLatin1String(
"geometry" ) )
319 QString templateString = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
328 QString expString = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
330 return expression.evaluate( context );
335 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
336 return QVariant( std::sqrt( x ) );
341 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
342 return QVariant( std::fabs( val ) );
347 double deg = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
348 return ( deg * M_PI ) / 180;
352 double rad = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
353 return ( 180 * rad ) / M_PI;
357 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
358 return QVariant( std::sin( x ) );
362 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
363 return QVariant( std::cos( x ) );
367 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
368 return QVariant( std::tan( x ) );
372 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
373 return QVariant( std::asin( x ) );
377 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
378 return QVariant( std::acos( x ) );
382 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
383 return QVariant( std::atan( x ) );
387 double y = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
388 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
389 return QVariant( std::atan2( y, x ) );
393 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
394 return QVariant( std::exp( x ) );
398 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
401 return QVariant( std::log( x ) );
405 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
408 return QVariant( log10( x ) );
412 double b = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
413 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
414 if ( x <= 0 || b <= 0 )
416 return QVariant( std::log( x ) / std::log( b ) );
420 double min = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
421 double max = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
425 std::random_device rd;
426 std::mt19937_64 generator( rd() );
428 if ( !QgsExpressionUtils::isNull( values.at( 2 ) ) )
431 if ( QgsExpressionUtils::isIntSafe( values.at( 2 ) ) )
434 seed = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
439 QString seedStr = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
440 std::hash<std::string> hasher;
441 seed = hasher( seedStr.toStdString() );
443 generator.seed( seed );
447 double f =
static_cast< double >( generator() ) /
static_cast< double >( std::mt19937_64::max() );
448 return QVariant( min + f * ( max - min ) );
452 qlonglong min = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
453 qlonglong max = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
457 std::random_device rd;
458 std::mt19937_64 generator( rd() );
460 if ( !QgsExpressionUtils::isNull( values.at( 2 ) ) )
463 if ( QgsExpressionUtils::isIntSafe( values.at( 2 ) ) )
466 seed = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
471 QString seedStr = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
472 std::hash<std::string> hasher;
473 seed = hasher( seedStr.toStdString() );
475 generator.seed( seed );
478 qint64 randomInteger = min + ( generator() % ( max - min + 1 ) );
479 if ( randomInteger > std::numeric_limits<int>::max() || randomInteger < -std::numeric_limits<int>::max() )
480 return QVariant( randomInteger );
483 return QVariant(
int( randomInteger ) );
488 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
489 double domainMin = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
490 double domainMax = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
491 double rangeMin = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
492 double rangeMax = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
494 if ( domainMin >= domainMax )
496 parent->
setEvalErrorString( QObject::tr(
"Domain max must be greater than domain min" ) );
501 if ( val >= domainMax )
505 else if ( val <= domainMin )
511 double m = ( rangeMax - rangeMin ) / ( domainMax - domainMin );
512 double c = rangeMin - ( domainMin * m );
515 return QVariant( m * val +
c );
520 double val = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
521 double domainMin = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
522 double domainMax = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
523 double rangeMin = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
524 double rangeMax = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
525 double exponent = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
527 if ( domainMin >= domainMax )
529 parent->
setEvalErrorString( QObject::tr(
"Domain max must be greater than domain min" ) );
539 if ( val >= domainMax )
543 else if ( val <= domainMin )
549 return QVariant( ( ( rangeMax - rangeMin ) / std::pow( domainMax - domainMin, exponent ) ) * std::pow( val - domainMin, exponent ) + rangeMin );
554 QVariant result( QVariant::Double );
555 double maxVal = std::numeric_limits<double>::quiet_NaN();
556 for (
const QVariant &val : values )
559 if ( std::isnan( maxVal ) )
563 else if ( !std::isnan( testVal ) )
565 maxVal = std::max( maxVal, testVal );
569 if ( !std::isnan( maxVal ) )
571 result = QVariant( maxVal );
578 QVariant result( QVariant::Double );
579 double minVal = std::numeric_limits<double>::quiet_NaN();
580 for (
const QVariant &val : values )
583 if ( std::isnan( minVal ) )
587 else if ( !std::isnan( testVal ) )
589 minVal = std::min( minVal, testVal );
593 if ( !std::isnan( minVal ) )
595 result = QVariant( minVal );
607 QVariant value = node->
eval( parent, context );
609 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( value, parent );
612 parent->
setEvalErrorString( QObject::tr(
"Cannot find layer with name or ID '%1'" ).arg( value.toString() ) );
617 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
619 value = node->
eval( parent, context );
625 parent->
setEvalErrorString( QObject::tr(
"No such aggregate '%1'" ).arg( value.toString() ) );
630 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
632 QString subExpression = node->
dump();
636 if ( values.count() > 3 )
638 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
641 if ( !nl || nl->value().isValid() )
646 if ( values.count() > 4 )
648 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
650 value = node->
eval( parent, context );
657 if ( values.count() > 5 )
659 node = QgsExpressionUtils::getNode( values.at( 5 ), parent );
662 if ( !nl || nl->value().isValid() )
664 orderBy = node->
dump();
669 QString aggregateError;
677 bool isStatic =
true;
678 if ( filterExp.referencedVariables().contains( QStringLiteral(
"parent" ) )
679 || filterExp.referencedVariables().contains( QString() )
680 || subExp.referencedVariables().contains( QStringLiteral(
"parent" ) )
681 || subExp.referencedVariables().contains( QString() ) )
687 const QSet<QString> refVars = filterExp.referencedVariables() + subExp.referencedVariables();
688 for (
const QString &varName : refVars )
691 if ( scope && !scope->
isStatic( varName ) )
701 cacheKey = QStringLiteral(
"aggfcn:%1:%2:%3:%4:%5%6:%7" ).arg( vl->id(), QString::number( aggregate ), subExpression, parameters.
filter,
702 QString::number( context->
feature().
id() ), QString::number(
qHash( context->
feature() ) ), orderBy );
706 cacheKey = QStringLiteral(
"aggfcn:%1:%2:%3:%4:%5" ).arg( vl->id(), QString::number( aggregate ), subExpression, parameters.
filter, orderBy );
717 subContext.appendScope( subScope );
718 result = vl->aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &aggregateError );
730 result = vl->aggregate( aggregate, subExpression, parameters,
nullptr, &ok,
nullptr,
nullptr, &aggregateError );
734 if ( !aggregateError.isEmpty() )
735 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, aggregateError ) );
737 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
748 parent->
setEvalErrorString( QObject::tr(
"Cannot use relation aggregate function in this context" ) );
753 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), parent );
756 parent->
setEvalErrorString( QObject::tr(
"Cannot use relation aggregate function in this context" ) );
765 QVariant value = node->
eval( parent, context );
767 QString relationId = value.toString();
774 if ( relations.isEmpty() || relations.at( 0 ).referencedLayer() != vl )
776 parent->
setEvalErrorString( QObject::tr(
"Cannot find relation with id '%1'" ).arg( relationId ) );
781 relation = relations.at( 0 );
788 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
790 value = node->
eval( parent, context );
796 parent->
setEvalErrorString( QObject::tr(
"No such aggregate '%1'" ).arg( value.toString() ) );
801 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
803 QString subExpression = node->
dump();
807 if ( values.count() > 3 )
809 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
811 value = node->
eval( parent, context );
818 if ( values.count() > 4 )
820 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
823 if ( !nl || nl->value().isValid() )
825 orderBy = node->
dump();
836 QString cacheKey = QStringLiteral(
"relagg:%1:%2:%3:%4:%5" ).arg( vl->
id(),
837 QString::number(
static_cast< int >( aggregate ) ),
850 result = childLayer->
aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &error );
854 if ( !error.isEmpty() )
855 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, error ) );
857 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
871 parent->
setEvalErrorString( QObject::tr(
"Cannot use aggregate function in this context" ) );
876 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), parent );
879 parent->
setEvalErrorString( QObject::tr(
"Cannot use aggregate function in this context" ) );
888 QString subExpression = node->
dump();
892 if ( values.count() > 1 )
894 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
897 if ( !nl || nl->value().isValid() )
898 groupBy = node->
dump();
902 if ( values.count() > 2 )
904 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
907 if ( !nl || nl->value().isValid() )
913 if ( orderByPos >= 0 && values.count() > orderByPos )
915 node = QgsExpressionUtils::getNode( values.at( orderByPos ), parent );
918 if ( !nl || nl->value().isValid() )
920 orderBy = node->
dump();
928 if ( !groupBy.isEmpty() )
931 QVariant groupByValue = groupByExp.evaluate( context );
932 QString groupByClause = QStringLiteral(
"%1 %2 %3" ).arg( groupBy,
935 if ( !parameters.
filter.isEmpty() )
936 parameters.
filter = QStringLiteral(
"(%1) AND (%2)" ).arg( parameters.
filter, groupByClause );
938 parameters.
filter = groupByClause;
944 bool isStatic =
true;
945 const QSet<QString> refVars = filterExp.referencedVariables() + subExp.referencedVariables();
946 for (
const QString &varName : refVars )
949 if ( scope && !scope->
isStatic( varName ) )
959 cacheKey = QStringLiteral(
"agg:%1:%2:%3:%4:%5%6:%7" ).arg( vl->
id(), QString::number( aggregate ), subExpression, parameters.
filter,
960 QString::number( context->
feature().
id() ), QString::number(
qHash( context->
feature() ) ), orderBy );
964 cacheKey = QStringLiteral(
"agg:%1:%2:%3:%4:%5" ).arg( vl->
id(), QString::number( aggregate ), subExpression, parameters.
filter, orderBy );
976 subContext.appendScope( subScope );
978 result = vl->
aggregate( aggregate, subExpression, parameters, &subContext, &ok,
nullptr, context->
feedback(), &error );
982 if ( !error.isEmpty() )
983 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1 (%2)" ).arg( subExpression, error ) );
985 parent->
setEvalErrorString( QObject::tr(
"Could not calculate aggregate for: %1" ).arg( subExpression ) );
1090 if ( values.count() > 3 )
1092 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
1094 QVariant value = node->
eval( parent, context );
1096 parameters.
delimiter = value.toString();
1107 if ( values.count() > 3 )
1109 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
1111 QVariant value = node->
eval( parent, context );
1113 parameters.
delimiter = value.toString();
1129 QVariant scale = context->
variable( QStringLiteral(
"map_scale" ) );
1134 const double v = scale.toDouble( &ok );
1142 double minValue = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1143 double testValue = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1144 double maxValue = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1147 if ( testValue <= minValue )
1149 return QVariant( minValue );
1151 else if ( testValue >= maxValue )
1153 return QVariant( maxValue );
1157 return QVariant( testValue );
1163 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1164 return QVariant( std::floor( x ) );
1169 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1170 return QVariant( std::ceil( x ) );
1175 return QVariant( QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) );
1179 return QVariant( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) );
1183 return QVariant( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ) );
1188 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1189 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1190 if ( format.isEmpty() && !language.isEmpty() )
1192 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to DateTime when the language is specified" ) );
1193 return QVariant( QDateTime() );
1196 if ( format.isEmpty() && language.isEmpty() )
1197 return QVariant( QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent ) );
1199 QString datetimestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1200 QLocale locale = QLocale();
1201 if ( !language.isEmpty() )
1203 locale = QLocale( language );
1206 QDateTime datetime = locale.toDateTime( datetimestring, format );
1207 if ( !datetime.isValid() )
1209 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to DateTime" ).arg( datetimestring ) );
1210 datetime = QDateTime();
1212 return QVariant( datetime );
1217 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1218 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1219 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1221 const QDate date( year, month, day );
1222 if ( !date.isValid() )
1224 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1227 return QVariant( date );
1232 const int hours = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1233 const int minutes = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1234 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1236 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1237 if ( !time.isValid() )
1239 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1242 return QVariant( time );
1247 const int year = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
1248 const int month = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1249 const int day = QgsExpressionUtils::getIntValue( values.at( 2 ), parent );
1250 const int hours = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
1251 const int minutes = QgsExpressionUtils::getIntValue( values.at( 4 ), parent );
1252 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1254 const QDate date( year, month, day );
1255 if ( !date.isValid() )
1257 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid date" ).arg( year ).arg( month ).arg( day ) );
1260 const QTime time( hours, minutes, std::floor( seconds ), ( seconds - std::floor( seconds ) ) * 1000 );
1261 if ( !time.isValid() )
1263 parent->
setEvalErrorString( QObject::tr(
"'%1-%2-%3' is not a valid time" ).arg( hours ).arg( minutes ).arg( seconds ) );
1266 return QVariant( QDateTime( date, time ) );
1271 const double years = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
1272 const double months = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
1273 const double weeks = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
1274 const double days = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
1275 const double hours = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
1276 const double minutes = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
1277 const double seconds = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
1279 return QVariant::fromValue(
QgsInterval( years, months, weeks, days, hours, minutes, seconds ) );
1284 for (
const QVariant &value : values )
1295 const QVariant val1 = values.at( 0 );
1296 const QVariant val2 = values.at( 1 );
1306 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1307 return QVariant(
str.toLower() );
1311 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1312 return QVariant(
str.toUpper() );
1316 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1317 QStringList elems =
str.split(
' ' );
1318 for (
int i = 0; i < elems.size(); i++ )
1320 if ( elems[i].size() > 1 )
1321 elems[i] = elems[i].at( 0 ).toUpper() + elems[i].mid( 1 ).toLower();
1323 return QVariant( elems.join( QLatin1Char(
' ' ) ) );
1328 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1329 return QVariant(
str.trimmed() );
1334 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1335 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1341 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1342 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1348 QString string1 = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1349 QString string2 = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1351 return ( dist < 0 ? QVariant() : QVariant(
QgsStringUtils::hammingDistance( string1, string2, true ) ) );
1356 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1362 QChar character = QChar( QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent ) );
1363 return QVariant( QString( character ) );
1368 QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1370 if ( value.isEmpty() )
1375 int res = value.at( 0 ).unicode();
1376 return QVariant( res );
1381 if ( values.length() == 2 || values.length() == 3 )
1383 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1384 qlonglong wrap = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1386 QString customdelimiter = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1397 if ( values.at( 0 ).userType() == QMetaType::type(
"QgsGeometry" ) )
1400 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
1404 return QVariant( geom.
length() );
1408 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1409 return QVariant(
str.length() );
1414 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
1419 double totalLength = 0;
1422 if (
const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( *it ) )
1424 totalLength += line->length3D();
1428 std::unique_ptr< QgsLineString > segmentized( qgsgeometry_cast< const QgsCurve * >( *it )->curveToLine() );
1429 totalLength += segmentized->length3D();
1438 if ( values.count() == 2 && values.at( 1 ).type() == QVariant::Map )
1440 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1441 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
1442 QVector< QPair< QString, QString > > mapItems;
1444 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
1446 mapItems.append( qMakePair( it.key(), it.value().toString() ) );
1450 std::sort( mapItems.begin(),
1452 [](
const QPair< QString, QString > &pair1,
1453 const QPair< QString, QString > &pair2 )
1455 return ( pair1.first.length() > pair2.first.length() );
1458 for (
auto it = mapItems.constBegin(); it != mapItems.constEnd(); ++it )
1460 str =
str.replace( it->first, it->second );
1463 return QVariant(
str );
1465 else if ( values.count() == 3 )
1467 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1468 QVariantList before;
1470 bool isSingleReplacement =
false;
1472 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).type() != QVariant::StringList )
1474 before = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1478 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
1481 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
1483 after = QVariantList() << QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1484 isSingleReplacement =
true;
1488 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
1491 if ( !isSingleReplacement && before.length() != after.length() )
1493 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
1497 for (
int i = 0; i < before.length(); i++ )
1499 str =
str.replace( before.at( i ).toString(), after.at( isSingleReplacement ? 0 : i ).toString() );
1502 return QVariant(
str );
1506 parent->
setEvalErrorString( QObject::tr(
"Function replace requires 2 or 3 arguments" ) );
1513 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1514 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1515 QString after = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1517 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1518 if ( !re.isValid() )
1520 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1523 return QVariant(
str.replace( re, after ) );
1528 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1529 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1531 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1532 if ( !re.isValid() )
1534 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1537 return QVariant( (
str.indexOf( re ) + 1 ) );
1542 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1543 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1544 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
1546 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1547 if ( !re.isValid() )
1549 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1553 QRegularExpressionMatch matches = re.match(
str );
1554 if ( matches.hasMatch() )
1557 QStringList list = matches.capturedTexts();
1560 for ( QStringList::const_iterator it = ++list.constBegin(); it != list.constEnd(); ++it )
1562 array += ( !( *it ).isEmpty() ) ? *it : empty;
1565 return QVariant( array );
1575 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1576 QString regexp = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1578 QRegularExpression re( regexp, QRegularExpression::UseUnicodePropertiesOption );
1579 if ( !re.isValid() )
1581 parent->
setEvalErrorString( QObject::tr(
"Invalid regular expression '%1': %2" ).arg( regexp, re.errorString() ) );
1586 QRegularExpressionMatch match = re.match(
str );
1587 if ( match.hasMatch() )
1590 if ( match.lastCapturedIndex() > 0 )
1593 return QVariant( match.captured( 1 ) );
1598 return QVariant( match.captured( 0 ) );
1603 return QVariant(
"" );
1609 QString uuid = QUuid::createUuid().toString();
1610 if ( values.at( 0 ).toString().compare( QStringLiteral(
"WithoutBraces" ), Qt::CaseInsensitive ) == 0 )
1611 uuid = QUuid::createUuid().toString( QUuid::StringFormat::WithoutBraces );
1612 else if ( values.at( 0 ).toString().compare( QStringLiteral(
"Id128" ), Qt::CaseInsensitive ) == 0 )
1613 uuid = QUuid::createUuid().toString( QUuid::StringFormat::Id128 );
1619 if ( !values.at( 0 ).isValid() || !values.at( 1 ).isValid() )
1622 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1623 int from = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1626 if ( values.at( 2 ).isValid() )
1627 len = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
1633 from =
str.size() + from;
1639 else if ( from > 0 )
1647 len =
str.size() + len - from;
1654 return QVariant(
str.mid( from, len ) );
1660 return QVariant(
static_cast< int >( f.
id() ) );
1665 QgsRasterLayer *layer = QgsExpressionUtils::getRasterLayer( values.at( 0 ), parent );
1668 parent->
setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster layer." ) );
1672 int bandNb = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
1673 if ( bandNb < 1 || bandNb > layer->
bandCount() )
1675 parent->
setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid raster band number." ) );
1679 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
1682 parent->
setEvalErrorString( QObject::tr(
"Function `raster_value` requires a valid point geometry." ) );
1690 if ( multiPoint.count() == 1 )
1692 point = multiPoint[0];
1702 return std::isnan( value ) ? QVariant() : value;
1717 if ( values.size() == 1 )
1719 attr = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
1722 else if ( values.size() == 2 )
1724 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
1725 attr = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
1729 parent->
setEvalErrorString( QObject::tr(
"Function `attribute` requires one or two parameters. %n given.",
nullptr, values.length() ) );
1745 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
1750 for (
int i = 0; i < fields.
count(); ++i )
1762 if ( values.isEmpty() )
1765 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), parent );
1767 else if ( values.size() == 1 )
1769 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), parent );
1770 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
1772 else if ( values.size() == 2 )
1774 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), parent );
1775 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
1779 parent->
setEvalErrorString( QObject::tr(
"Function `represent_attributes` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
1785 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: layer could not be resolved." ) );
1791 parent->
setEvalErrorString( QObject::tr(
"Cannot use represent attributes function: feature could not be resolved." ) );
1797 for (
int fieldIndex = 0; fieldIndex < fields.
count(); ++fieldIndex )
1799 const QString fieldName { fields.
at( fieldIndex ).
name() };
1800 const QVariant attributeVal = feature.
attribute( fieldIndex );
1801 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer->
id(), fieldName, attributeVal.toString() );
1804 result.insert( fieldName, context->
cachedValue( cacheValueKey ) );
1813 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer->
id(), fieldName );
1825 QString value( fieldFormatter->
representValue( layer, fieldIndex, setup.
config(), cache, attributeVal ) );
1827 result.insert( fields.
at( fieldIndex ).
name(), value );
1843 bool evaluate =
true;
1845 if ( values.isEmpty() )
1848 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), parent );
1850 else if ( values.size() == 1 )
1852 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), parent );
1853 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
1855 else if ( values.size() == 2 )
1857 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), parent );
1858 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
1860 else if ( values.size() == 3 )
1862 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), parent );
1863 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
1864 evaluate = values.value( 2 ).toBool();
1870 parent->
setEvalErrorString( QObject::tr(
"Function `maptip` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
1874 parent->
setEvalErrorString( QObject::tr(
"Function `display` requires no more than three parameters. %n given.",
nullptr, values.length() ) );
1905 subContext.setFeature( feature );
1914 exp.prepare( &subContext );
1915 return exp.evaluate( &subContext ).toString();
1921 return fcnCoreFeatureMaptipDisplay( values, context, parent,
false );
1926 return fcnCoreFeatureMaptipDisplay( values, context, parent,
true );
1934 if ( values.isEmpty() )
1937 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), parent );
1939 else if ( values.size() == 1 )
1941 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), parent );
1942 feature = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
1944 else if ( values.size() == 2 )
1946 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), parent );
1947 feature = QgsExpressionUtils::getFeature( values.at( 1 ), parent );
1951 parent->
setEvalErrorString( QObject::tr(
"Function `is_selected` requires no more than two parameters. %n given.",
nullptr, values.length() ) );
1955 if ( !layer || !feature.
isValid() )
1957 return QVariant( QVariant::Bool );
1967 if ( values.isEmpty() )
1968 layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), parent );
1969 else if ( values.count() == 1 )
1970 layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), parent );
1973 parent->
setEvalErrorString( QObject::tr(
"Function `num_selected` requires no more than one parameter. %n given.",
nullptr, values.length() ) );
1979 return QVariant( QVariant::LongLong );
1987 static QMap<QString, qlonglong> counterCache;
1988 QVariant functionResult;
1990 std::function<void()> fetchAndIncrementFunc = [ =, &functionResult ]()
1993 const QgsVectorLayer *layer = QgsExpressionUtils::getVectorLayer( values.at( 0 ), parent );
1998 database = decodedUri.value( QStringLiteral(
"path" ) ).toString();
1999 if ( database.isEmpty() )
2001 parent->
setEvalErrorString( QObject::tr(
"Could not extract file path from layer `%1`." ).arg( layer->
name() ) );
2006 database = values.at( 0 ).toString();
2009 const QString table = values.at( 1 ).toString();
2010 const QString idColumn = values.at( 2 ).toString();
2011 const QString filterAttribute = values.at( 3 ).toString();
2012 const QVariant filterValue = values.at( 4 ).toString();
2013 const QVariantMap defaultValues = values.at( 5 ).toMap();
2019 if ( sqliteDb.
open_v2( database, SQLITE_OPEN_READWRITE,
nullptr ) != SQLITE_OK )
2022 functionResult = QVariant();
2026 QString errorMessage;
2027 QString currentValSql;
2029 qlonglong nextId = 0;
2030 bool cachedMode =
false;
2031 bool valueRetrieved =
false;
2033 QString cacheString = QStringLiteral(
"%1:%2:%3:%4:%5" ).arg( database, table, idColumn, filterAttribute, filterValue.toString() );
2040 auto cachedCounter = counterCache.find( cacheString );
2042 if ( cachedCounter != counterCache.end() )
2044 qlonglong &cachedValue = cachedCounter.value();
2045 nextId = cachedValue;
2047 cachedValue = nextId;
2048 valueRetrieved =
true;
2053 if ( !cachedMode || !valueRetrieved )
2055 int result = SQLITE_ERROR;
2058 if ( !filterAttribute.isNull() )
2063 sqliteStatement = sqliteDb.
prepare( currentValSql, result );
2065 if ( result == SQLITE_OK )
2068 if ( sqliteStatement.
step() == SQLITE_ROW )
2074 if ( cachedMode && result == SQLITE_OK )
2076 counterCache.insert( cacheString, nextId );
2080 counterCache.remove( cacheString );
2083 valueRetrieved =
true;
2087 if ( valueRetrieved )
2096 if ( !filterAttribute.isNull() )
2102 for ( QVariantMap::const_iterator iter = defaultValues.constBegin(); iter != defaultValues.constEnd(); ++iter )
2105 vals << iter.value().toString();
2108 upsertSql += QLatin1String(
" (" ) + cols.join(
',' ) +
')';
2109 upsertSql += QLatin1String(
" VALUES " );
2110 upsertSql +=
'(' + vals.join(
',' ) +
')';
2112 int result = SQLITE_ERROR;
2116 if ( transaction->
executeSql( upsertSql, errorMessage ) )
2123 result = sqliteDb.
exec( upsertSql, errorMessage );
2125 if ( result == SQLITE_OK )
2127 functionResult = QVariant( nextId );
2132 parent->
setEvalErrorString( QStringLiteral(
"Could not increment value: SQLite error: \"%1\" (%2)." ).arg( errorMessage, QString::number( result ) ) );
2133 functionResult = QVariant();
2138 functionResult = QVariant();
2143 return functionResult;
2149 for (
const QVariant &value : values )
2152 concat += QgsExpressionUtils::getStringValue( value, parent );
2159 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2160 return string.indexOf( QgsExpressionUtils::getStringValue( values.at( 1 ), parent ) ) + 1;
2165 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2166 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2167 return string.right( pos );
2172 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2173 int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2174 return string.left( pos );
2179 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2180 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2181 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2182 return string.leftJustified( length, fill.at( 0 ),
true );
2187 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2188 int length = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2189 QString fill = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2190 return string.rightJustified( length, fill.at( 0 ),
true );
2195 if ( values.size() < 1 )
2197 parent->
setEvalErrorString( QObject::tr(
"Function format requires at least 1 argument" ) );
2201 QString
string = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2202 for (
int n = 1; n < values.length(); n++ )
2204 string =
string.arg( QgsExpressionUtils::getStringValue( values.at( n ), parent ) );
2212 return QVariant( QDateTime::currentDateTime() );
2217 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2218 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2219 if ( format.isEmpty() && !language.isEmpty() )
2221 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Date when the language is specified" ) );
2222 return QVariant( QDate() );
2225 if ( format.isEmpty() && language.isEmpty() )
2226 return QVariant( QgsExpressionUtils::getDateValue( values.at( 0 ), parent ) );
2228 QString datestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2229 QLocale locale = QLocale();
2230 if ( !language.isEmpty() )
2232 locale = QLocale( language );
2235 QDate date = locale.toDate( datestring, format );
2236 if ( !date.isValid() )
2238 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Date" ).arg( datestring ) );
2241 return QVariant( date );
2246 QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2247 QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
2248 if ( format.isEmpty() && !language.isEmpty() )
2250 parent->
setEvalErrorString( QObject::tr(
"A format is required to convert to Time when the language is specified" ) );
2251 return QVariant( QTime() );
2254 if ( format.isEmpty() && language.isEmpty() )
2255 return QVariant( QgsExpressionUtils::getTimeValue( values.at( 0 ), parent ) );
2257 QString timestring = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
2258 QLocale locale = QLocale();
2259 if ( !language.isEmpty() )
2261 locale = QLocale( language );
2264 QTime time = locale.toTime( timestring, format );
2265 if ( !time.isValid() )
2267 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to Time" ).arg( timestring ) );
2270 return QVariant( time );
2275 return QVariant::fromValue( QgsExpressionUtils::getInterval( values.at( 0 ), parent ) );
2284 double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
2285 QString axis = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2286 int precision = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
2288 QString formatString;
2289 if ( values.count() > 3 )
2290 formatString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
2292 QgsCoordinateFormatter::FormatFlags flags = QgsCoordinateFormatter::FormatFlags();
2293 if ( formatString.compare( QLatin1String(
"suffix" ), Qt::CaseInsensitive ) == 0 )
2297 else if ( formatString.compare( QLatin1String(
"aligned" ), Qt::CaseInsensitive ) == 0 )
2301 else if ( ! formatString.isEmpty() )
2303 parent->
setEvalErrorString( QObject::tr(
"Invalid formatting parameter: '%1'. It must be empty, or 'suffix' or 'aligned'." ).arg( formatString ) );
2307 if ( axis.compare( QLatin1String(
"x" ), Qt::CaseInsensitive ) == 0 )
2311 else if ( axis.compare( QLatin1String(
"y" ), Qt::CaseInsensitive ) == 0 )
2317 parent->
setEvalErrorString( QObject::tr(
"Invalid axis name: '%1'. It must be either 'x' or 'y'." ).arg( axis ) );
2325 return floatToDegreeFormat( format, values, context, parent, node );
2332 value = QgsCoordinateUtils::dmsToDecimal( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), &ok );
2334 return ok ? QVariant( value ) : QVariant();
2340 return floatToDegreeFormat( format, values, context, parent, node );
2345 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2346 QDateTime d2 = QgsExpressionUtils::getDateTimeValue( values.at( 1 ), parent );
2347 qint64 seconds = d2.secsTo( d1 );
2348 return QVariant::fromValue(
QgsInterval( seconds ) );
2353 if ( !values.at( 0 ).canConvert<QDate>() )
2356 QDate date = QgsExpressionUtils::getDateValue( values.at( 0 ), parent );
2357 if ( !date.isValid() )
2362 return date.dayOfWeek() % 7;
2367 QVariant value = values.at( 0 );
2368 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2371 return QVariant( inter.
days() );
2375 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2376 return QVariant( d1.date().day() );
2382 QVariant value = values.at( 0 );
2383 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2386 return QVariant( inter.
years() );
2390 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2391 return QVariant( d1.date().year() );
2397 QVariant value = values.at( 0 );
2398 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2401 return QVariant( inter.
months() );
2405 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2406 return QVariant( d1.date().month() );
2412 QVariant value = values.at( 0 );
2413 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2416 return QVariant( inter.
weeks() );
2420 QDateTime d1 = QgsExpressionUtils::getDateTimeValue( value, parent );
2421 return QVariant( d1.date().weekNumber() );
2427 QVariant value = values.at( 0 );
2428 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2431 return QVariant( inter.
hours() );
2435 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2436 return QVariant( t1.hour() );
2442 QVariant value = values.at( 0 );
2443 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2446 return QVariant( inter.
minutes() );
2450 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2451 return QVariant( t1.minute() );
2457 QVariant value = values.at( 0 );
2458 QgsInterval inter = QgsExpressionUtils::getInterval( value, parent,
false );
2461 return QVariant( inter.
seconds() );
2465 QTime t1 = QgsExpressionUtils::getTimeValue( value, parent );
2466 return QVariant( t1.second() );
2472 QDateTime dt = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
2475 return QVariant( dt.toMSecsSinceEpoch() );
2485 long long millisecs_since_epoch = QgsExpressionUtils::getIntValue( values.at( 0 ), parent );
2487 return QVariant( QDateTime::fromMSecsSinceEpoch( millisecs_since_epoch ) );
2492 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), parent );
2495 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif" ) ) );
2498 QString tag = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
2504 const QString filepath = QgsExpressionUtils::getFilePathValue( values.at( 0 ), parent );
2507 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"exif_geotag" ) ) );
2514#define ENSURE_GEOM_TYPE(f, g, geomtype) \
2515 if ( !(f).hasGeometry() ) \
2516 return QVariant(); \
2517 QgsGeometry g = (f).geometry(); \
2518 if ( (g).type() != (geomtype) ) \
2525 if ( g.isMultipart() )
2527 return g.asMultiPoint().at( 0 ).x();
2531 return g.asPoint().x();
2539 if ( g.isMultipart() )
2541 return g.asMultiPoint().at( 0 ).y();
2545 return g.asPoint().y();
2559 if ( g.isEmpty() || !abGeom->
is3D() )
2564 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( g.constGet() );
2570 if (
const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( g.constGet() ) )
2572 if ( collection->numGeometries() > 0 )
2574 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
2585 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2591 return QVariant( isValid );
2596 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2600 const QString methodString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).trimmed();
2601#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
2606 if ( methodString.compare( QLatin1String(
"linework" ), Qt::CaseInsensitive ) == 0 )
2608 else if ( methodString.compare( QLatin1String(
"structure" ), Qt::CaseInsensitive ) == 0 )
2611 const bool keepCollapsed = values.value( 2 ).toBool();
2616 valid = geom.
makeValid( method, keepCollapsed );
2620 parent->
setEvalErrorString( QObject::tr(
"The make_valid parameters require a newer GEOS library version" ) );
2624 return QVariant::fromValue( valid );
2629 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2635 for (
int i = 0; i < multiGeom.size(); ++i )
2637 array += QVariant::fromValue( multiGeom.at( i ) );
2645 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2657 QVariant result( centroid.asPoint().
x() );
2663 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2675 QVariant result( centroid.asPoint().
y() );
2681 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2691 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
2699 if ( collection->numGeometries() == 1 )
2701 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
2712 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2722 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
2730 if ( collection->numGeometries() == 1 )
2732 if (
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
2743 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2748 int idx = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
2775 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2792 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2809 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2814 bool ignoreClosing =
false;
2815 if ( values.length() > 1 )
2817 ignoreClosing = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
2827 bool skipLast =
false;
2828 if ( ignoreClosing && ring.count() > 2 && ring.first() == ring.last() )
2833 for (
int i = 0; i < ( skipLast ? ring.count() - 1 : ring.count() ); ++ i )
2845 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2856 for (
int i = 0; i < line->numPoints() - 1; ++i )
2860 << line->pointN( i )
2861 << line->pointN( i + 1 ) );
2872 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2882 if ( collection->numGeometries() == 1 )
2884 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->geometryN( 0 ) );
2889 if ( !curvePolygon )
2893 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
2899 QVariant result = curve ? QVariant::fromValue(
QgsGeometry( curve ) ) : QVariant();
2905 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2915 qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
2921 QVariant result = part ? QVariant::fromValue(
QgsGeometry( part ) ) : QVariant();
2927 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2936 return QVariant::fromValue(
QgsGeometry( boundary ) );
2941 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2950 return QVariant::fromValue( merged );
2955 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2959 const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
2964 if ( sharedPaths.
isNull() )
2967 return QVariant::fromValue( sharedPaths );
2973 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2978 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
2981 if ( simplified.
isNull() )
2989 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
2994 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
2999 if ( simplified.
isNull() )
3007 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3012 int iterations = std::min( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), 10 );
3013 double offset = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0.0, 0.5 );
3014 double minLength = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3015 double maxAngle = std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ), 0.0, 180.0 );
3017 QgsGeometry smoothed = geom.
smooth(
static_cast<unsigned int>( iterations ), offset, minLength, maxAngle );
3026 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3031 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3032 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3033 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3044 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3049 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3050 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3051 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3052 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3053 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3056 minAmplitude, maxAmplitude, seed );
3065 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3070 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3071 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3072 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3083 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3088 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3089 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3090 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3091 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3092 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3095 minAmplitude, maxAmplitude, seed );
3104 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3109 const double wavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3110 const double amplitude = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3111 const bool strict = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
3122 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3127 const double minWavelength = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3128 const double maxWavelength = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3129 const double minAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3130 const double maxAmplitude = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
3131 const long long seed = QgsExpressionUtils::getIntValue( values.at( 5 ), parent );
3134 minAmplitude, maxAmplitude, seed );
3143 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3148 const QVariantList pattern = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
3149 QVector< double > dashPattern;
3150 dashPattern.reserve( pattern.size() );
3151 for (
const QVariant &value : std::as_const( pattern ) )
3154 double v = value.toDouble( &ok );
3161 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must be an array of numbers" ) );
3166 if ( dashPattern.size() % 2 != 0 )
3168 parent->
setEvalErrorString( QStringLiteral(
"Dash pattern must contain an even number of elements" ) );
3172 const QString startRuleString = QgsExpressionUtils::getStringValue( values.at( 2 ), parent ).trimmed();
3174 if ( startRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3176 else if ( startRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3178 else if ( startRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3180 else if ( startRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3182 else if ( startRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3186 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( startRuleString ) );
3190 const QString endRuleString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
3192 if ( endRuleString.compare( QLatin1String(
"no_rule" ), Qt::CaseInsensitive ) == 0 )
3194 else if ( endRuleString.compare( QLatin1String(
"full_dash" ), Qt::CaseInsensitive ) == 0 )
3196 else if ( endRuleString.compare( QLatin1String(
"half_dash" ), Qt::CaseInsensitive ) == 0 )
3198 else if ( endRuleString.compare( QLatin1String(
"full_gap" ), Qt::CaseInsensitive ) == 0 )
3200 else if ( endRuleString.compare( QLatin1String(
"half_gap" ), Qt::CaseInsensitive ) == 0 )
3204 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern rule" ).arg( endRuleString ) );
3208 const QString adjustString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
3210 if ( adjustString.compare( QLatin1String(
"both" ), Qt::CaseInsensitive ) == 0 )
3212 else if ( adjustString.compare( QLatin1String(
"dash" ), Qt::CaseInsensitive ) == 0 )
3214 else if ( adjustString.compare( QLatin1String(
"gap" ), Qt::CaseInsensitive ) == 0 )
3218 parent->
setEvalErrorString( QStringLiteral(
"'%1' is not a valid dash pattern size adjustment" ).arg( adjustString ) );
3222 const double patternOffset = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
3233 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3238 const long long count = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3240 if ( densified.
isNull() )
3248 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3253 const double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3255 if ( densified.
isNull() )
3264 if ( values.size() == 1 && QgsExpressionUtils::isList( values.at( 0 ) ) )
3266 list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
3273 QVector< QgsGeometry > parts;
3274 parts.reserve( list.size() );
3275 for (
const QVariant &value : std::as_const( list ) )
3277 if ( value.userType() == QMetaType::type(
"QgsGeometry" ) )
3293 if ( values.count() < 2 || values.count() > 4 )
3295 parent->
setEvalErrorString( QObject::tr(
"Function make_point requires 2-4 arguments" ) );
3299 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3300 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3301 double z = values.count() >= 3 ? QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) : 0.0;
3302 double m = values.count() >= 4 ? QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) : 0.0;
3303 switch ( values.count() )
3317 double x = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
3318 double y = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3319 double m = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3325 if ( values.empty() )
3330 QVector<QgsPoint> points;
3331 points.reserve( values.count() );
3333 auto addPoint = [&points](
const QgsGeometry & geom )
3341 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3348 for (
const QVariant &value : values )
3350 if ( value.type() == QVariant::List )
3352 const QVariantList list = value.toList();
3353 for (
const QVariant &v : list )
3355 addPoint( QgsExpressionUtils::getGeometry( v, parent ) );
3360 addPoint( QgsExpressionUtils::getGeometry( value, parent ) );
3364 if ( points.count() < 2 )
3372 if ( values.count() < 1 )
3374 parent->
setEvalErrorString( QObject::tr(
"Function make_polygon requires an argument" ) );
3378 QgsGeometry outerRing = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3386 std::unique_ptr< QgsPolygon > polygon = std::make_unique< QgsPolygon >();
3388 const QgsCurve *exteriorRing = qgsgeometry_cast< QgsCurve * >( outerRing.
constGet() );
3395 exteriorRing = qgsgeometry_cast< QgsCurve * >( collection->
geometryN( 0 ) );
3400 if ( !exteriorRing )
3403 polygon->setExteriorRing( exteriorRing->
segmentize() );
3406 for (
int i = 1; i < values.count(); ++i )
3408 QgsGeometry ringGeom = QgsExpressionUtils::getGeometry( values.at( i ), parent );
3415 const QgsCurve *ring = qgsgeometry_cast< QgsCurve * >( ringGeom.
constGet() );
3422 ring = qgsgeometry_cast< QgsCurve * >( collection->
geometryN( 0 ) );
3430 polygon->addInteriorRing( ring->
segmentize() );
3433 return QVariant::fromValue(
QgsGeometry( std::move( polygon ) ) );
3438 std::unique_ptr<QgsTriangle> tr(
new QgsTriangle() );
3439 std::unique_ptr<QgsLineString> lineString(
new QgsLineString() );
3440 lineString->clear();
3442 for (
const QVariant &value : values )
3444 QgsGeometry geom = QgsExpressionUtils::getGeometry( value, parent );
3451 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3458 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3466 lineString->addVertex( *point );
3469 tr->setExteriorRing( lineString.release() );
3471 return QVariant::fromValue(
QgsGeometry( tr.release() ) );
3476 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3483 double radius = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3484 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
3491 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3498 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3506 return QVariant::fromValue(
QgsGeometry( circ.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
3511 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3518 double majorAxis = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
3519 double minorAxis = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
3520 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
3521 int segment = QgsExpressionUtils::getNativeIntValue( values.at( 4 ), parent );
3527 const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( geom.
constGet() );
3534 point = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3541 QgsEllipse elp( *point, majorAxis, minorAxis, azimuth );
3542 return QVariant::fromValue(
QgsGeometry( elp.toPolygon(
static_cast<unsigned int>(
segment ) ) ) );
3548 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3555 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3562 unsigned int nbEdges =
static_cast<unsigned int>( QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) );
3565 parent->
setEvalErrorString( QObject::tr(
"Number of edges/sides must be greater than 2" ) );
3572 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (inscribed) or 1 (circumscribed)" ) );
3576 const QgsPoint *center = qgsgeometry_cast< const QgsPoint * >( pt1.
constGet() );
3583 center = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3590 const QgsPoint *corner = qgsgeometry_cast< const QgsPoint * >( pt2.
constGet() );
3597 corner = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
3612 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3618 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3624 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
3625 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
3633 QgsGeometry pt1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3639 QgsGeometry pt2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
3645 QgsGeometry pt3 = QgsExpressionUtils::getGeometry( values.at( 2 ), parent );
3654 parent->
setEvalErrorString( QObject::tr(
"Option can be 0 (distance) or 1 (projected)" ) );
3657 const QgsPoint *point1 = qgsgeometry_cast< const QgsPoint *>( pt1.
constGet() );
3658 const QgsPoint *point2 = qgsgeometry_cast< const QgsPoint *>( pt2.
constGet() );
3659 const QgsPoint *point3 = qgsgeometry_cast< const QgsPoint *>( pt3.
constGet() );
3667 int idx = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
3683 return QVariant( QPointF( p.
x(), p.
y() ) );
3688 QVariant v = pointAt( values, f, parent );
3689 if ( v.type() == QVariant::PointF )
3690 return QVariant( v.toPointF().x() );
3696 QVariant v = pointAt( values, f, parent );
3697 if ( v.type() == QVariant::PointF )
3698 return QVariant( v.toPointF().y() );
3715 return QVariant::fromValue( geom );
3723 QString wkt = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
3725 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
3731 const QByteArray wkb = QgsExpressionUtils::getBinaryValue( values.at( 0 ), parent );
3737 return !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
3742 QString gml = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
3749 ogcContext.
layer = mapLayerPtr.data();
3750 ogcContext.
transformContext = context->
variable( QStringLiteral(
"_project_transform_context" ) ).value<QgsCoordinateTransformContext>();
3754 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
3767 return QVariant( area );
3777 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3782 return QVariant( geom.
area() );
3794 return QVariant( len );
3811 return QVariant( len );
3815 return f.
geometry().
isNull() ? QVariant( 0 ) : QVariant( f.geometry().constGet()->perimeter() );
3821 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3827 return QVariant( geom.
length() );
3832 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3833 return QVariant( geom.
isNull() ? 0 : geom.constGet()->nCoordinates() );
3838 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3847 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3856 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3871 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon *>( collection->
geometryN( i ) );
3872 if ( !curvePolygon )
3875 return QVariant( curvePolygon->
isEmpty() ? 0 : curvePolygon->numInteriorRings() );
3884 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3891 return QVariant( curvePolygon->
ringCount() );
3893 bool foundPoly =
false;
3901 curvePolygon = qgsgeometry_cast< QgsCurvePolygon *>( collection->
geometryN( i ) );
3902 if ( !curvePolygon )
3913 return QVariant( ringCount );
3918 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3920 QVariant result = !geomBounds.
isNull() ? QVariant::fromValue( geomBounds ) : QVariant();
3926 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3932 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3938 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3947 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3953 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3959 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3965 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3971 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
3979 double max = std::numeric_limits< double >::lowest();
3983 double z = ( *it ).z();
3989 if ( max == std::numeric_limits< double >::lowest() )
3990 return QVariant( QVariant::Double );
3992 return QVariant( max );
3997 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4005 double min = std::numeric_limits< double >::max();
4009 double z = ( *it ).z();
4015 if ( min == std::numeric_limits< double >::max() )
4016 return QVariant( QVariant::Double );
4018 return QVariant( min );
4023 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4031 double min = std::numeric_limits< double >::max();
4035 double m = ( *it ).m();
4041 if ( min == std::numeric_limits< double >::max() )
4042 return QVariant( QVariant::Double );
4044 return QVariant( min );
4049 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4057 double max = std::numeric_limits< double >::lowest();
4061 double m = ( *it ).m();
4067 if ( max == std::numeric_limits< double >::lowest() )
4068 return QVariant( QVariant::Double );
4070 return QVariant( max );
4075 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4076 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom.
constGet() );
4079 parent->
setEvalErrorString( QObject::tr(
"Function `sinuosity` requires a line geometry." ) );
4088 const QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4092 parent->
setEvalErrorString( QObject::tr(
"Function `straight_distance_2d` requires a line geometry or a multi line geometry with a single part." ) );
4101 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4106 parent->
setEvalErrorString( QObject::tr(
"Function `roundness` requires a polygon geometry or a multi polygon geometry with a single part." ) );
4117 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4121 std::unique_ptr< QgsAbstractGeometry > flipped( geom.
constGet()->
clone() );
4123 return QVariant::fromValue(
QgsGeometry( std::move( flipped ) ) );
4128 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4132 const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( fGeom.
constGet() );
4139 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
4147 return QVariant::fromValue( curve->
isClosed() );
4152 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4165 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4166 closedLine->close();
4168 result = QVariant::fromValue(
QgsGeometry( std::move( closedLine ) ) );
4178 if (
const QgsLineString *line = qgsgeometry_cast<const QgsLineString * >( collection->
geometryN( i ) ) )
4180 std::unique_ptr< QgsLineString > closedLine( line->
clone() );
4181 closedLine->close();
4183 closed->addGeometry( closedLine.release() );
4186 result = QVariant::fromValue(
QgsGeometry( std::move( closed ) ) );
4194 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4198 return QVariant::fromValue( fGeom.
isEmpty() );
4204 return QVariant::fromValue(
true );
4206 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4207 return QVariant::fromValue( fGeom.
isNull() || fGeom.
isEmpty() );
4212 if ( values.length() < 2 || values.length() > 3 )
4215 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4216 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4223 if ( values.length() == 2 )
4226 QString result = engine->relate( sGeom.
constGet() );
4227 return QVariant::fromValue( result );
4232 QString pattern = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
4233 bool result = engine->relatePattern( sGeom.
constGet(), pattern );
4234 return QVariant::fromValue( result );
4240 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4241 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4246 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4247 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4248 return fGeom.
disjoint( sGeom ) ? TVL_True : TVL_False;
4252 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4253 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4254 return fGeom.
intersects( sGeom ) ? TVL_True : TVL_False;
4258 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4259 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4260 return fGeom.
touches( sGeom ) ? TVL_True : TVL_False;
4264 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4265 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4266 return fGeom.
crosses( sGeom ) ? TVL_True : TVL_False;
4270 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4271 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4272 return fGeom.
contains( sGeom ) ? TVL_True : TVL_False;
4276 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4277 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4278 return fGeom.
overlaps( sGeom ) ? TVL_True : TVL_False;
4282 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4283 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4284 return fGeom.
within( sGeom ) ? TVL_True : TVL_False;
4289 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4290 const double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4291 const int seg = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4292 const QString endCapString = QgsExpressionUtils::getStringValue( values.at( 3 ), parent ).trimmed();
4293 const QString joinString = QgsExpressionUtils::getStringValue( values.at( 4 ), parent ).trimmed();
4294 const double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
4297 if ( endCapString.compare( QLatin1String(
"flat" ), Qt::CaseInsensitive ) == 0 )
4299 else if ( endCapString.compare( QLatin1String(
"square" ), Qt::CaseInsensitive ) == 0 )
4303 if ( joinString.compare( QLatin1String(
"miter" ), Qt::CaseInsensitive ) == 0 )
4305 else if ( joinString.compare( QLatin1String(
"bevel" ), Qt::CaseInsensitive ) == 0 )
4309 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4315 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4317 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4322 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4324 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4329 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4331 return !reoriented.
isNull() ? QVariant::fromValue( reoriented ) : QVariant();
4336 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4337 const QgsPoint *pt = qgsgeometry_cast<const QgsPoint *>( fGeom.
constGet() );
4344 pt = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4351 parent->
setEvalErrorString( QObject::tr(
"Function `wedge_buffer` requires a point value for the center." ) );
4355 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4356 double width = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4357 double outerRadius = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4358 double innerRadius = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
4361 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4367 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4370 parent->
setEvalErrorString( QObject::tr(
"Function `tapered_buffer` requires a line geometry." ) );
4374 double startWidth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4375 double endWidth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4376 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) );
4379 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4385 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4388 parent->
setEvalErrorString( QObject::tr(
"Function `buffer_by_m` requires a line geometry." ) );
4392 int segments =
static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) );
4395 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4401 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4402 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4403 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4404 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4405 if ( joinInt < 1 || joinInt > 3 )
4409 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4412 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4418 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4419 double dist = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4420 int segments = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
4422 const int joinInt = QgsExpressionUtils::getIntValue( values.at( 3 ), parent );
4423 if ( joinInt < 1 || joinInt > 3 )
4427 double miterLimit = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4430 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4436 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4437 double distStart = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4438 double distEnd = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4441 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4447 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4448 double dx = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4449 double dy = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4451 return QVariant::fromValue( fGeom );
4456 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4457 const double rotation = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4458 const QgsGeometry center = values.at( 2 ).
isValid() ? QgsExpressionUtils::getGeometry( values.at( 2 ), parent )
4460 const bool perPart = values.value( 3 ).toBool();
4467 std::unique_ptr< QgsGeometryCollection > collection( qgsgeometry_cast< QgsGeometryCollection * >( fGeom.
constGet()->
clone() ) );
4470 const QgsPointXY partCenter = ( *it )->boundingBox().center();
4471 QTransform t = QTransform::fromTranslate( partCenter.
x(), partCenter.
y() );
4472 t.rotate( -rotation );
4473 t.translate( -partCenter.
x(), -partCenter.
y() );
4474 ( *it )->transform( t );
4476 return QVariant::fromValue(
QgsGeometry( std::move( collection ) ) );
4488 parent->
setEvalErrorString( QObject::tr(
"Function 'rotate' requires a point value for the center" ) );
4496 fGeom.
rotate( rotation, pt );
4497 return QVariant::fromValue( fGeom );
4503 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4504 const double xScale = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4505 const double yScale = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4506 const QgsGeometry center = values.at( 3 ).isValid() ? QgsExpressionUtils::getGeometry( values.at( 3 ), parent )
4517 parent->
setEvalErrorString( QObject::tr(
"Function 'scale' requires a point value for the center" ) );
4525 QTransform t = QTransform::fromTranslate( pt.
x(), pt.
y() );
4526 t.scale( xScale, yScale );
4527 t.translate( -pt.
x(), -pt.
y() );
4529 return QVariant::fromValue( fGeom );
4534 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4540 const double deltaX = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4541 const double deltaY = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4543 const double rotationZ = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4545 const double scaleX = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
4546 const double scaleY = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
4548 const double deltaZ = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
4549 const double deltaM = QgsExpressionUtils::getDoubleValue( values.at( 7 ), parent );
4550 const double scaleZ = QgsExpressionUtils::getDoubleValue( values.at( 8 ), parent );
4551 const double scaleM = QgsExpressionUtils::getDoubleValue( values.at( 9 ), parent );
4562 QTransform transform;
4563 transform.translate( deltaX, deltaY );
4564 transform.rotate( rotationZ );
4565 transform.scale( scaleX, scaleY );
4566 fGeom.
transform( transform, deltaZ, scaleZ, deltaM, scaleM );
4568 return QVariant::fromValue( fGeom );
4574 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4576 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4581 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4583 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4589 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4590 double tolerance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4592 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4598 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4600 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4604#if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
4609 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4610 const double targetPercent = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4611 const bool allowHoles = values.value( 2 ).toBool();
4613 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4626 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4628 if ( values.length() == 2 )
4629 segments = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4637 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4643 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4645 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4651 const QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4657 double area,
angle, width, height;
4670 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4671 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4673 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4679 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4686 const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( fGeom.
constGet() );
4691 result = reversed ? QVariant::fromValue(
QgsGeometry( reversed ) ) : QVariant();
4699 if (
const QgsCurve *curve = qgsgeometry_cast<const QgsCurve * >( collection->
geometryN( i ) ) )
4701 reversed->addGeometry( curve->
reversed() );
4708 result = reversed ? QVariant::fromValue(
QgsGeometry( std::move( reversed ) ) ) : QVariant();
4715 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4726 curvePolygon = qgsgeometry_cast< const QgsCurvePolygon * >( collection->
geometryN( 0 ) );
4735 QVariant result = exterior ? QVariant::fromValue(
QgsGeometry( exterior ) ) : QVariant();
4741 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4742 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4743 return QVariant( fGeom.
distance( sGeom ) );
4748 QgsGeometry g1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4749 QgsGeometry g2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4752 if ( values.length() == 3 && values.at( 2 ).isValid() )
4754 double densify = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4755 densify = std::clamp( densify, 0.0, 1.0 );
4763 return res > -1 ? QVariant( res ) : QVariant();
4768 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4769 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4771 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4776 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4777 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4779 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4784 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4785 QgsGeometry sGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4787 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
4793 if ( values.length() < 1 || values.length() > 2 )
4796 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4798 if ( values.length() == 2 )
4799 prec = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
4800 QString wkt = fGeom.
asWkt( prec );
4801 return QVariant( wkt );
4806 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4807 return fGeom.
isNull() ? QVariant() : QVariant( fGeom.asWkb() );
4812 if ( values.length() != 2 )
4814 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires exactly two parameters. %n given.",
nullptr, values.length() ) );
4818 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4819 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4821 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
4828 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4833 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
4840 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4847 parent->
setEvalErrorString( QObject::tr(
"Function `azimuth` requires two points as arguments." ) );
4854 if ( pt1->
y() < pt2->
y() )
4856 else if ( pt1->
y() > pt2->
y() )
4864 if ( pt1->
x() < pt2->
x() )
4866 else if ( pt1->
x() > pt2->
x() )
4867 return M_PI + ( M_PI_2 );
4872 if ( pt1->
x() < pt2->
x() )
4874 if ( pt1->
y() < pt2->
y() )
4876 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) );
4880 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
4887 if ( pt1->
y() > pt2->
y() )
4889 return std::atan( std::fabs( pt1->
x() - pt2->
x() ) / std::fabs( pt1->
y() - pt2->
y() ) )
4894 return std::atan( std::fabs( pt1->
y() - pt2->
y() ) / std::fabs( pt1->
x() - pt2->
x() ) )
4895 + ( M_PI + ( M_PI_2 ) );
4902 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4906 parent->
setEvalErrorString( QStringLiteral(
"'project' requires a point geometry" ) );
4910 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4911 double azimuth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4912 double inclination = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
4915 QgsPoint newPoint = p->
project( distance, 180.0 * azimuth / M_PI, 180.0 * inclination / M_PI );
4922 QgsGeometry fGeom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4923 QgsGeometry fGeom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
4925 const QgsPoint *pt1 = qgsgeometry_cast<const QgsPoint *>( fGeom1.
constGet() );
4932 pt1 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4936 const QgsPoint *pt2 = qgsgeometry_cast<const QgsPoint *>( fGeom2.
constGet() );
4943 pt2 = qgsgeometry_cast< const QgsPoint * >( collection->
geometryN( 0 ) );
4951 parent->
setEvalErrorString( QStringLiteral(
"Function 'inclination' requires two points as arguments." ) );
4961 if ( values.length() != 3 )
4964 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4965 double x = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
4966 double y = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
4970 QVariant result = geom.
constGet() ? QVariant::fromValue( geom ) : QVariant();
4976 if ( values.length() < 2 )
4979 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
4982 return values.at( 0 );
4984 QString expString = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
4985 QVariant cachedExpression;
4990 if ( cachedExpression.isValid() )
4997 bool asc = values.value( 2 ).toBool();
5015 Q_ASSERT( collection );
5019 QgsExpressionSorter sorter( orderBy );
5021 QList<QgsFeature> partFeatures;
5022 partFeatures.reserve( collection->
partCount() );
5023 for (
int i = 0; i < collection->
partCount(); ++i )
5029 sorter.sortFeatures( partFeatures, unconstedContext );
5033 Q_ASSERT( orderedGeom );
5038 for (
const QgsFeature &feature : std::as_const( partFeatures ) )
5043 QVariant result = QVariant::fromValue(
QgsGeometry( orderedGeom ) );
5046 delete unconstedContext;
5053 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5054 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5058 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5064 QgsGeometry fromGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5065 QgsGeometry toGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5069 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5075 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5076 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5080 QVariant result = !geom.
isNull() ? QVariant::fromValue( geom ) : QVariant();
5086 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5089 parent->
setEvalErrorString( QObject::tr(
"line_substring requires a curve geometry input" ) );
5095 curve = qgsgeometry_cast< const QgsCurve * >( lineGeom.
constGet() );
5102 curve = qgsgeometry_cast< const QgsCurve * >( collection->
geometryN( 0 ) );
5109 double startDistance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5110 double endDistance = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5112 std::unique_ptr< QgsCurve > substring( curve->
curveSubstring( startDistance, endDistance ) );
5114 return !result.isNull() ? QVariant::fromValue( result ) : QVariant();
5119 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5120 double distance = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5127 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5128 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5133 vertex = count + vertex;
5141 QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5142 int vertex = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5147 vertex = count + vertex;
5155 QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5156 QgsGeometry pointGeom = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
5160 return distance >= 0 ? distance : QVariant();
5165 if ( values.length() == 2 && values.at( 1 ).toInt() != 0 )
5167 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5168 return qgsRound( number, QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
5171 if ( values.length() >= 1 )
5173 double number = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5174 return QVariant( qlonglong( std::round( number ) ) );
5189 const double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
5190 const int places = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5191 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5198 const bool omitGroupSeparator = values.value( 3 ).toBool();
5199 const bool trimTrailingZeros = values.value( 4 ).toBool();
5201 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5202 if ( !omitGroupSeparator )
5203 locale.setNumberOptions( locale.numberOptions() & ~QLocale::NumberOption::OmitGroupSeparator );
5205 locale.setNumberOptions( locale.numberOptions() | QLocale::NumberOption::OmitGroupSeparator );
5207 QString res = locale.toString( value,
'f', places );
5209 if ( trimTrailingZeros )
5211#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
5212 const QChar decimal = locale.decimalPoint();
5213 const QChar zeroDigit = locale.zeroDigit();
5215 const QChar decimal = locale.decimalPoint().at( 0 );
5216 const QChar zeroDigit = locale.zeroDigit().at( 0 );
5219 if ( res.contains( decimal ) )
5221 int trimPoint = res.length() - 1;
5223 while ( res.at( trimPoint ) == zeroDigit )
5226 if ( res.at( trimPoint ) == decimal )
5229 res.truncate( trimPoint + 1 );
5238 const QDateTime datetime = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
5239 const QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5240 const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5242 QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
5243 return locale.toString( datetime, format );
5249 int avg = ( color.red() + color.green() + color.blue() ) / 3;
5250 int alpha = color.alpha();
5252 color.setRgb( avg, avg, avg, alpha );
5261 double ratio = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
5266 else if ( ratio < 0 )
5271 int red =
static_cast<int>( color1.red() * ( 1 - ratio ) + color2.red() * ratio );
5272 int green =
static_cast<int>( color1.green() * ( 1 - ratio ) + color2.green() * ratio );
5273 int blue =
static_cast<int>( color1.blue() * ( 1 - ratio ) + color2.blue() * ratio );
5274 int alpha =
static_cast<int>( color1.alpha() * ( 1 - ratio ) + color2.alpha() * ratio );
5276 QColor newColor( red, green, blue, alpha );
5283 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
5284 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5285 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
5286 QColor color = QColor( red, green, blue );
5287 if ( ! color.isValid() )
5289 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( red ).arg( green ).arg( blue ) );
5290 color = QColor( 0, 0, 0 );
5293 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
5298 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
5299 QVariant value = node->
eval( parent, context );
5303 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
5305 value = node->
eval( parent, context );
5313 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
5315 QVariant value = node->
eval( parent, context );
5317 if ( value.toBool() )
5319 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
5321 value = node->
eval( parent, context );
5326 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
5328 value = node->
eval( parent, context );
5336 int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
5337 int green = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
5338 int blue = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
5339 int alpha = QgsExpressionUtils::getNativeIntValue( values.at( 3 ), parent );
5340 QColor color = QColor( red, green, blue, alpha );
5341 if ( ! color.isValid() )
5343 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( red ).arg( green ).arg( blue ).arg( alpha ) );
5344 color = QColor( 0, 0, 0 );
5353 if ( values.at( 0 ).userType() == QMetaType::type(
"QgsGradientColorRamp" ) )
5355 expRamp = QgsExpressionUtils::getRamp( values.at( 0 ), parent );
5360 QString rampName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
5364 parent->
setEvalErrorString( QObject::tr(
"\"%1\" is not a valid color ramp" ).arg( rampName ) );
5369 double value = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
5370 QColor color = ramp->
color( value );
5377 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
5379 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5381 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5383 QColor color = QColor::fromHslF( hue, saturation, lightness );
5385 if ( ! color.isValid() )
5387 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( lightness ) );
5388 color = QColor( 0, 0, 0 );
5391 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
5397 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
5399 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5401 double lightness = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5403 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
5405 QColor color = QColor::fromHslF( hue, saturation, lightness, alpha );
5406 if ( ! color.isValid() )
5408 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( lightness ).arg( alpha ) );
5409 color = QColor( 0, 0, 0 );
5417 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
5419 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5421 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5423 QColor color = QColor::fromHsvF( hue, saturation, value );
5425 if ( ! color.isValid() )
5427 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3' to color" ).arg( hue ).arg( saturation ).arg( value ) );
5428 color = QColor( 0, 0, 0 );
5431 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
5437 double hue = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 360.0;
5439 double saturation = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5441 double value = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5443 double alpha = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 255.0;
5445 QColor color = QColor::fromHsvF( hue, saturation, value, alpha );
5446 if ( ! color.isValid() )
5448 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( hue ).arg( saturation ).arg( value ).arg( alpha ) );
5449 color = QColor( 0, 0, 0 );
5457 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
5459 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5461 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5463 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
5465 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black );
5467 if ( ! color.isValid() )
5469 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ) );
5470 color = QColor( 0, 0, 0 );
5473 return QStringLiteral(
"%1,%2,%3" ).arg( color.red() ).arg( color.green() ).arg( color.blue() );
5479 double cyan = QgsExpressionUtils::getIntValue( values.at( 0 ), parent ) / 100.0;
5481 double magenta = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) / 100.0;
5483 double yellow = QgsExpressionUtils::getIntValue( values.at( 2 ), parent ) / 100.0;
5485 double black = QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) / 100.0;
5487 double alpha = QgsExpressionUtils::getIntValue( values.at( 4 ), parent ) / 255.0;
5489 QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
5490 if ( ! color.isValid() )
5492 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) );
5493 color = QColor( 0, 0, 0 );
5501 if ( ! color.isValid() )
5503 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( values.at( 0 ).toString() ) );
5507 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5508 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
5510 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
5511 return color.green();
5512 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
5513 return color.blue();
5514 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
5515 return color.alpha();
5516 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
5517 return static_cast< double >( color.hsvHueF() * 360 );
5518 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
5519 return static_cast< double >( color.hsvSaturationF() * 100 );
5520 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
5521 return static_cast< double >( color.valueF() * 100 );
5522 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
5523 return static_cast< double >( color.hslHueF() * 360 );
5524 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
5525 return static_cast< double >( color.hslSaturationF() * 100 );
5526 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
5527 return static_cast< double >( color.lightnessF() * 100 );
5528 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
5529 return static_cast< double >( color.cyanF() * 100 );
5530 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
5531 return static_cast< double >( color.magentaF() * 100 );
5532 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
5533 return static_cast< double >( color.yellowF() * 100 );
5534 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
5535 return static_cast< double >( color.blackF() * 100 );
5537 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
5543 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
5544 if ( map.count() < 1 )
5546 parent->
setEvalErrorString( QObject::tr(
"A minimum of two colors is required to create a ramp" ) );
5550 QList< QColor > colors;
5552 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
5555 if ( !colors.last().isValid() )
5557 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( it.value().toString() ) );
5561 double step = it.key().toDouble();
5562 if ( it == map.constBegin() )
5567 else if ( it == map.constEnd() )
5577 bool discrete = values.at( 1 ).toBool();
5579 return QVariant::fromValue(
QgsGradientColorRamp( colors.first(), colors.last(), discrete, stops ) );
5585 if ( ! color.isValid() )
5587 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( values.at( 0 ).toString() ) );
5591 QString part = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5592 int value = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
5593 if ( part.compare( QLatin1String(
"red" ), Qt::CaseInsensitive ) == 0 )
5594 color.setRed( value );
5595 else if ( part.compare( QLatin1String(
"green" ), Qt::CaseInsensitive ) == 0 )
5596 color.setGreen( value );
5597 else if ( part.compare( QLatin1String(
"blue" ), Qt::CaseInsensitive ) == 0 )
5598 color.setBlue( value );
5599 else if ( part.compare( QLatin1String(
"alpha" ), Qt::CaseInsensitive ) == 0 )
5600 color.setAlpha( value );
5601 else if ( part.compare( QLatin1String(
"hue" ), Qt::CaseInsensitive ) == 0 )
5602 color.setHsv( value, color.hsvSaturation(), color.value(), color.alpha() );
5603 else if ( part.compare( QLatin1String(
"saturation" ), Qt::CaseInsensitive ) == 0 )
5604 color.setHsvF( color.hsvHueF(), value / 100.0, color.valueF(), color.alphaF() );
5605 else if ( part.compare( QLatin1String(
"value" ), Qt::CaseInsensitive ) == 0 )
5606 color.setHsvF( color.hsvHueF(), color.hsvSaturationF(), value / 100.0, color.alphaF() );
5607 else if ( part.compare( QLatin1String(
"hsl_hue" ), Qt::CaseInsensitive ) == 0 )
5608 color.setHsl( value, color.hslSaturation(), color.lightness(), color.alpha() );
5609 else if ( part.compare( QLatin1String(
"hsl_saturation" ), Qt::CaseInsensitive ) == 0 )
5610 color.setHslF( color.hslHueF(), value / 100.0, color.lightnessF(), color.alphaF() );
5611 else if ( part.compare( QLatin1String(
"lightness" ), Qt::CaseInsensitive ) == 0 )
5612 color.setHslF( color.hslHueF(), color.hslSaturationF(), value / 100.0, color.alphaF() );
5613 else if ( part.compare( QLatin1String(
"cyan" ), Qt::CaseInsensitive ) == 0 )
5614 color.setCmykF( value / 100.0, color.magentaF(), color.yellowF(), color.blackF(), color.alphaF() );
5615 else if ( part.compare( QLatin1String(
"magenta" ), Qt::CaseInsensitive ) == 0 )
5616 color.setCmykF( color.cyanF(), value / 100.0, color.yellowF(), color.blackF(), color.alphaF() );
5617 else if ( part.compare( QLatin1String(
"yellow" ), Qt::CaseInsensitive ) == 0 )
5618 color.setCmykF( color.cyanF(), color.magentaF(), value / 100.0, color.blackF(), color.alphaF() );
5619 else if ( part.compare( QLatin1String(
"black" ), Qt::CaseInsensitive ) == 0 )
5620 color.setCmykF( color.cyanF(), color.magentaF(), color.yellowF(), value / 100.0, color.alphaF() );
5623 parent->
setEvalErrorString( QObject::tr(
"Unknown color component '%1'" ).arg( part ) );
5632 if ( ! color.isValid() )
5634 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( values.at( 0 ).toString() ) );
5638 color = color.darker( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
5646 if ( ! color.isValid() )
5648 parent->
setEvalErrorString( QObject::tr(
"Cannot convert '%1' to color" ).arg( values.at( 0 ).toString() ) );
5652 color = color.lighter( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ) );
5659 QgsFeature feat = QgsExpressionUtils::getFeature( values.at( 0 ), parent );
5662 return QVariant::fromValue( geom );
5668 QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
5669 QString sAuthId = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5670 QString dAuthId = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
5674 return QVariant::fromValue( fGeom );
5677 return QVariant::fromValue( fGeom );
5686 return QVariant::fromValue( fGeom );
5700 QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( values.at( 0 ), parent );
5703 QgsFeatureId fid = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
5715 result = QVariant::fromValue( fet );
5725 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), parent );
5728 if ( !featureSource )
5733 QString cacheValueKey;
5734 if ( values.at( 1 ).type() == QVariant::Map )
5736 QVariantMap attributeMap = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
5738 QMap <QString, QVariant>::const_iterator i = attributeMap.constBegin();
5739 QString filterString;
5740 for ( ; i != attributeMap.constEnd(); ++i )
5742 if ( !filterString.isEmpty() )
5744 filterString.append(
" AND " );
5748 cacheValueKey = QStringLiteral(
"getfeature:%1:%2" ).arg( featureSource->id(), filterString );
5757 QString attribute = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5758 int attributeId = featureSource->fields().lookupField( attribute );
5759 if ( attributeId == -1 )
5764 const QVariant &attVal = values.at( 2 );
5766 cacheValueKey = QStringLiteral(
"getfeature:%1:%2:%3" ).arg( featureSource->id(), QString::number( attributeId ), attVal.toString() );
5789 res = QVariant::fromValue( fet );
5804 if ( !values.isEmpty() )
5807 if ( col && ( values.size() == 1 || !values.at( 1 ).isValid() ) )
5808 fieldName = col->
name();
5809 else if ( values.size() == 2 )
5810 fieldName = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5813 QVariant value = values.at( 0 );
5818 if ( fieldIndex == -1 )
5820 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: Field not found %2" ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
5824 QgsVectorLayer *layer = QgsExpressionUtils::getVectorLayer( context->
variable( QStringLiteral(
"layer" ) ), parent );
5826 const QString cacheValueKey = QStringLiteral(
"repvalfcnval:%1:%2:%3" ).arg( layer ? layer->
id() : QStringLiteral(
"[None]" ), fieldName, value.toString() );
5835 const QString cacheKey = QStringLiteral(
"repvalfcn:%1:%2" ).arg( layer ? layer->
id() : QStringLiteral(
"[None]" ), fieldName );
5846 result =
formatter->representValue( layer, fieldIndex, setup.
config(), cache, value );
5853 parent->
setEvalErrorString( QCoreApplication::translate(
"expression",
"%1: function cannot be evaluated without a context." ).arg( QStringLiteral(
"represent_value" ), fieldName ) );
5861 const QVariant data = values.at( 0 );
5862 const QMimeDatabase db;
5863 return db.mimeTypeForData( data.toByteArray() ).name();
5868 QgsMapLayer *layer = QgsExpressionUtils::getMapLayer( values.at( 0 ), parent );
5874 QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
5875 if ( QString::compare( layerProperty, QStringLiteral(
"name" ), Qt::CaseInsensitive ) == 0 )
5876 return layer->
name();
5877 else if ( QString::compare( layerProperty, QStringLiteral(
"id" ), Qt::CaseInsensitive ) == 0 )
5879 else if ( QString::compare( layerProperty, QStringLiteral(
"title" ), Qt::CaseInsensitive ) == 0 )
5881 else if ( QString::compare( layerProperty, QStringLiteral(
"abstract" ), Qt::CaseInsensitive ) == 0 )
5883 else if ( QString::compare( layerProperty, QStringLiteral(
"keywords" ), Qt::CaseInsensitive ) == 0 )
5885 QStringList keywords;
5887 for (
auto it = keywordMap.constBegin(); it != keywordMap.constEnd(); ++it )
5889 keywords.append( it.value() );
5891 if ( !keywords.isEmpty() )
5895 else if ( QString::compare( layerProperty, QStringLiteral(
"data_url" ), Qt::CaseInsensitive ) == 0 )
5897 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution" ), Qt::CaseInsensitive ) == 0 )
5901 else if ( QString::compare( layerProperty, QStringLiteral(
"attribution_url" ), Qt::CaseInsensitive ) == 0 )
5903 else if ( QString::compare( layerProperty, QStringLiteral(
"source" ), Qt::CaseInsensitive ) == 0 )
5905 else if ( QString::compare( layerProperty, QStringLiteral(
"min_scale" ), Qt::CaseInsensitive ) == 0 )
5907 else if ( QString::compare( layerProperty, QStringLiteral(
"max_scale" ), Qt::CaseInsensitive ) == 0 )
5909 else if ( QString::compare( layerProperty, QStringLiteral(
"is_editable" ), Qt::CaseInsensitive ) == 0 )
5911 else if ( QString::compare( layerProperty, QStringLiteral(
"crs" ), Qt::CaseInsensitive ) == 0 )
5913 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_definition" ), Qt::CaseInsensitive ) == 0 )
5915 else if ( QString::compare( layerProperty, QStringLiteral(
"crs_description" ), Qt::CaseInsensitive ) == 0 )
5917 else if ( QString::compare( layerProperty, QStringLiteral(
"extent" ), Qt::CaseInsensitive ) == 0 )
5920 QVariant result = QVariant::fromValue( extentGeom );
5923 else if ( QString::compare( layerProperty, QStringLiteral(
"distance_units" ), Qt::CaseInsensitive ) == 0 )
5925 else if ( QString::compare( layerProperty, QStringLiteral(
"path" ), Qt::CaseInsensitive ) == 0 )
5928 return decodedUri.value( QStringLiteral(
"path" ) );
5930 else if ( QString::compare( layerProperty, QStringLiteral(
"type" ), Qt::CaseInsensitive ) == 0 )
5932 switch ( layer->
type() )
5935 return QCoreApplication::translate(
"expressions",
"Vector" );
5937 return QCoreApplication::translate(
"expressions",
"Raster" );
5939 return QCoreApplication::translate(
"expressions",
"Mesh" );
5941 return QCoreApplication::translate(
"expressions",
"Vector Tile" );
5943 return QCoreApplication::translate(
"expressions",
"Plugin" );
5945 return QCoreApplication::translate(
"expressions",
"Annotation" );
5947 return QCoreApplication::translate(
"expressions",
"Point Cloud" );
5949 return QCoreApplication::translate(
"expressions",
"Group" );
5955 QgsVectorLayer *vLayer = qobject_cast< QgsVectorLayer * >( layer );
5958 if ( QString::compare( layerProperty, QStringLiteral(
"storage_type" ), Qt::CaseInsensitive ) == 0 )
5960 else if ( QString::compare( layerProperty, QStringLiteral(
"geometry_type" ), Qt::CaseInsensitive ) == 0 )
5962 else if ( QString::compare( layerProperty, QStringLiteral(
"feature_count" ), Qt::CaseInsensitive ) == 0 )
5972 QgsMapLayer *layer = QgsExpressionUtils::getMapLayer( values.at( 0 ), parent );
5975 parent->
setEvalErrorString( QObject::tr(
"Cannot find layer %1" ).arg( values.at( 0 ).toString() ) );
5985 const QString uriPart = values.at( 1 ).toString();
5989 if ( !uriPart.isNull() )
5991 return decodedUri.value( values.at( 1 ).toString() );
6001 QString layerIdOrName = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
6008 if ( !layersByName.isEmpty() )
6010 layer = layersByName.at( 0 );
6021 int band = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6022 if ( band < 1 || band > rl->
bandCount() )
6024 parent->
setEvalErrorString( QObject::tr(
"Invalid band number %1 for layer %2" ).arg( band ).arg( layerIdOrName ) );
6028 QString layerProperty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6031 if ( QString::compare( layerProperty, QStringLiteral(
"avg" ), Qt::CaseInsensitive ) == 0 )
6033 else if ( QString::compare( layerProperty, QStringLiteral(
"stdev" ), Qt::CaseInsensitive ) == 0 )
6035 else if ( QString::compare( layerProperty, QStringLiteral(
"min" ), Qt::CaseInsensitive ) == 0 )
6037 else if ( QString::compare( layerProperty, QStringLiteral(
"max" ), Qt::CaseInsensitive ) == 0 )
6039 else if ( QString::compare( layerProperty, QStringLiteral(
"range" ), Qt::CaseInsensitive ) == 0 )
6041 else if ( QString::compare( layerProperty, QStringLiteral(
"sum" ), Qt::CaseInsensitive ) == 0 )
6045 parent->
setEvalErrorString( QObject::tr(
"Invalid raster statistic: '%1'" ).arg( layerProperty ) );
6075 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6076 bool ascending = values.value( 1 ).toBool();
6077 std::sort( list.begin(), list.end(), [ascending]( QVariant a, QVariant b ) ->
bool { return ( !ascending ? qgsVariantLessThan( b, a ) : qgsVariantLessThan( a, b ) ); } );
6083 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).length();
6088 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).contains( values.at( 1 ) ) );
6093 return QVariant( QgsExpressionUtils::getListValue( values.at( 0 ), parent ).count( values.at( 1 ) ) );
6098 QVariantList listA = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6099 QVariantList listB = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
6101 for (
const auto &item : listB )
6103 if ( listA.contains( item ) )
6107 return QVariant( match == listB.count() );
6112 return QgsExpressionUtils::getListValue( values.at( 0 ), parent ).indexOf( values.at( 1 ) );
6117 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6118 const int pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6119 if ( pos < list.length() && pos >= 0 )
return list.at( pos );
6120 else if ( pos < 0 && ( list.length() + pos ) >= 0 )
6121 return list.at( list.length() + pos );
6127 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6128 return list.value( 0 );
6133 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6134 return list.value( list.size() - 1 );
6139 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6140 return list.isEmpty() ? QVariant() : *std::min_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
6145 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6146 return list.isEmpty() ? QVariant() : *std::max_element( list.constBegin(), list.constEnd(), []( QVariant a, QVariant b ) -> bool { return (
qgsVariantLessThan( a, b ) ); } );
6151 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6154 for (
const QVariant &item : list )
6156 switch ( item.userType() )
6158 case QMetaType::Int:
6159 case QMetaType::UInt:
6160 case QMetaType::LongLong:
6161 case QMetaType::ULongLong:
6162 case QMetaType::Float:
6163 case QMetaType::Double:
6164 total += item.toDouble();
6169 return i == 0 ? QVariant() : total / i;
6174 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6175 QVariantList numbers;
6176 for (
const auto &item : list )
6178 switch ( item.userType() )
6180 case QMetaType::Int:
6181 case QMetaType::UInt:
6182 case QMetaType::LongLong:
6183 case QMetaType::ULongLong:
6184 case QMetaType::Float:
6185 case QMetaType::Double:
6186 numbers.append( item );
6190 std::sort( numbers.begin(), numbers.end(), []( QVariant a, QVariant b ) ->
bool { return ( qgsVariantLessThan( a, b ) ); } );
6191 const int count = numbers.count();
6196 else if ( count % 2 )
6198 return numbers.at( count / 2 );
6202 return ( numbers.at( count / 2 - 1 ).toDouble() + numbers.at( count / 2 ).toDouble() ) / 2;
6208 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6211 for (
const QVariant &item : list )
6213 switch ( item.userType() )
6215 case QMetaType::Int:
6216 case QMetaType::UInt:
6217 case QMetaType::LongLong:
6218 case QMetaType::ULongLong:
6219 case QMetaType::Float:
6220 case QMetaType::Double:
6221 total += item.toDouble();
6226 return i == 0 ? QVariant() : total;
6229static QVariant convertToSameType(
const QVariant &value, QVariant::Type type )
6231 QVariant result = value;
6232 result.convert(
static_cast<int>( type ) );
6238 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6239 QHash< QVariant, int > hash;
6240 for (
const auto &item : list )
6244 const QList< int > occurrences = hash.values();
6245 if ( occurrences.empty() )
6246 return QVariantList();
6248 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
6250 const QString option = values.at( 1 ).toString();
6251 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
6253 return convertToSameType( hash.keys( maxValue ), values.at( 0 ).type() );
6255 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
6257 if ( hash.isEmpty() )
6260 return QVariant( hash.keys( maxValue ).first() );
6262 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
6264 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( maxValue ), values.at( 0 ).type() ), context, parent, node );
6266 else if ( option.compare( QLatin1String(
"real_majority" ), Qt::CaseInsensitive ) == 0 )
6268 if ( maxValue * 2 <= list.size() )
6271 return QVariant( hash.keys( maxValue ).first() );
6282 const QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6283 QHash< QVariant, int > hash;
6284 for (
const auto &item : list )
6288 const QList< int > occurrences = hash.values();
6289 if ( occurrences.empty() )
6290 return QVariantList();
6292 const int minValue = *std::min_element( occurrences.constBegin(), occurrences.constEnd() );
6294 const QString option = values.at( 1 ).toString();
6295 if ( option.compare( QLatin1String(
"all" ), Qt::CaseInsensitive ) == 0 )
6297 return convertToSameType( hash.keys( minValue ), values.at( 0 ).type() );
6299 else if ( option.compare( QLatin1String(
"any" ), Qt::CaseInsensitive ) == 0 )
6301 if ( hash.isEmpty() )
6304 return QVariant( hash.keys( minValue ).first() );
6306 else if ( option.compare( QLatin1String(
"median" ), Qt::CaseInsensitive ) == 0 )
6308 return fcnArrayMedian( QVariantList() << convertToSameType( hash.keys( minValue ), values.at( 0 ).type() ), context, parent, node );
6310 else if ( option.compare( QLatin1String(
"real_minority" ), Qt::CaseInsensitive ) == 0 )
6312 if ( hash.keys().isEmpty() )
6316 const int maxValue = *std::max_element( occurrences.constBegin(), occurrences.constEnd() );
6317 if ( maxValue * 2 > list.size() )
6318 hash.remove( hash.key( maxValue ) );
6320 return convertToSameType( hash.keys(), values.at( 0 ).type() );
6331 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6332 list.append( values.at( 1 ) );
6333 return convertToSameType( list, values.at( 0 ).type() );
6338 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6339 list.prepend( values.at( 1 ) );
6340 return convertToSameType( list, values.at( 0 ).type() );
6345 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6346 list.insert( QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent ), values.at( 2 ) );
6347 return convertToSameType( list, values.at( 0 ).type() );
6352 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6353 int position = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6355 position = position + list.length();
6356 if ( position >= 0 && position < list.length() )
6357 list.removeAt( position );
6358 return convertToSameType( list, values.at( 0 ).type() );
6366 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6368 const QVariant toRemove = values.at( 1 );
6371 list.erase( std::remove_if( list.begin(), list.end(), [](
const QVariant & element )
6373 return QgsVariantUtils::isNull( element );
6378 list.removeAll( toRemove );
6380 return convertToSameType( list, values.at( 0 ).type() );
6385 if ( values.count() == 2 && values.at( 1 ).type() == QVariant::Map )
6387 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 1 ), parent );
6389 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6390 for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
6392 int index = list.indexOf( it.key() );
6393 while ( index >= 0 )
6395 list.replace( index, it.value() );
6396 index = list.indexOf( it.key() );
6400 return convertToSameType( list, values.at( 0 ).type() );
6402 else if ( values.count() == 3 )
6404 QVariantList before;
6406 bool isSingleReplacement =
false;
6408 if ( !QgsExpressionUtils::isList( values.at( 1 ) ) && values.at( 2 ).type() != QVariant::StringList )
6410 before = QVariantList() << values.at( 1 );
6414 before = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
6417 if ( !QgsExpressionUtils::isList( values.at( 2 ) ) )
6419 after = QVariantList() << values.at( 2 );
6420 isSingleReplacement =
true;
6424 after = QgsExpressionUtils::getListValue( values.at( 2 ), parent );
6427 if ( !isSingleReplacement && before.length() != after.length() )
6429 parent->
setEvalErrorString( QObject::tr(
"Invalid pair of array, length not identical" ) );
6433 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6434 for (
int i = 0; i < before.length(); i++ )
6436 int index = list.indexOf( before.at( i ) );
6437 while ( index >= 0 )
6439 list.replace( index, after.at( isSingleReplacement ? 0 : i ) );
6440 index = list.indexOf( before.at( i ) );
6444 return convertToSameType( list, values.at( 0 ).type() );
6448 parent->
setEvalErrorString( QObject::tr(
"Function array_replace requires 2 or 3 arguments" ) );
6455 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6456 QVariantList list_new;
6458 for (
const QVariant &cur :
QgsExpressionUtils::getListValue( values.at( 1 ), parent ) )
6460 while ( list.removeOne( cur ) )
6462 list_new.append( cur );
6466 list_new.append( list );
6468 return convertToSameType( list_new, values.at( 0 ).type() );
6474 for (
const QVariant &cur : values )
6476 list += QgsExpressionUtils::getListValue( cur, parent );
6478 return convertToSameType( list, values.at( 0 ).type() );
6483 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6484 int start_pos = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
6485 const int end_pos = QgsExpressionUtils::getNativeIntValue( values.at( 2 ), parent );
6486 int slice_length = 0;
6488 if ( start_pos < 0 )
6490 start_pos = list.length() + start_pos;
6494 slice_length = end_pos - start_pos + 1;
6498 slice_length = list.length() + end_pos - start_pos + 1;
6501 if ( slice_length < 0 )
6505 list = list.mid( start_pos, slice_length );
6511 QVariantList list = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6512 std::reverse( list.begin(), list.end() );
6518 const QVariantList array1 = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6519 const QVariantList array2 = QgsExpressionUtils::getListValue( values.at( 1 ), parent );
6520 for (
const QVariant &cur : array2 )
6522 if ( array1.contains( cur ) )
6523 return QVariant(
true );
6525 return QVariant(
false );
6530 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6532 QVariantList distinct;
6534 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
6536 if ( !distinct.contains( *it ) )
6538 distinct += ( *it );
6547 QVariantList array = QgsExpressionUtils::getListValue( values.at( 0 ), parent );
6548 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6549 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6553 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
6555 str += ( !( *it ).toString().isEmpty() ) ? ( *it ).toString() : empty;
6556 if ( it != ( array.constEnd() - 1 ) )
6562 return QVariant(
str );
6567 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
6568 QString delimiter = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6569 QString empty = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
6571 QStringList list =
str.split( delimiter );
6574 for ( QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
6576 array += ( !( *it ).isEmpty() ) ? *it : empty;
6584 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
6585 QJsonDocument document = QJsonDocument::fromJson(
str.toUtf8() );
6586 if ( document.isNull() )
6589 return document.toVariant();
6595 QJsonDocument document = QJsonDocument::fromVariant( values.at( 0 ) );
6596 return QString( document.toJson( QJsonDocument::Compact ) );
6601 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
6602 if (
str.isEmpty() )
6603 return QVariantMap();
6611 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
6618 for (
int i = 0; i + 1 < values.length(); i += 2 )
6620 result.insert( QgsExpressionUtils::getStringValue( values.at( i ), parent ), values.at( i + 1 ) );
6627 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
6628 const QString prefix = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
6629 QVariantMap resultMap;
6631 for (
auto it = map.cbegin(); it != map.cend(); it++ )
6633 resultMap.insert( QString( it.key() ).prepend( prefix ), it.value() );
6641 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).value( values.at( 1 ).toString() );
6646 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).contains( values.at( 1 ).toString() );
6651 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
6652 map.remove( values.at( 1 ).toString() );
6658 QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
6659 map.insert( values.at( 1 ).toString(), values.at( 2 ) );
6666 for (
const QVariant &cur : values )
6668 const QVariantMap curMap = QgsExpressionUtils::getMapValue( cur, parent );
6669 for ( QVariantMap::const_iterator it = curMap.constBegin(); it != curMap.constEnd(); ++it )
6670 result.insert( it.key(), it.value() );
6677 return QStringList( QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).keys() );
6682 return QgsExpressionUtils::getMapValue( values.at( 0 ), parent ).values();
6687 const QString envVarName = values.at( 0 ).toString();
6688 if ( !QProcessEnvironment::systemEnvironment().contains( envVarName ) )
6691 return QProcessEnvironment::systemEnvironment().value( envVarName );
6696 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), parent );
6699 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"base_file_name" ) ) );
6702 return QFileInfo( file ).completeBaseName();
6707 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), parent );
6710 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_suffix" ) ) );
6713 return QFileInfo( file ).completeSuffix();
6718 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), parent );
6721 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_exists" ) ) );
6724 return QFileInfo::exists( file );
6729 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), parent );
6732 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_name" ) ) );
6735 return QFileInfo( file ).fileName();
6740 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), parent );
6743 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_file" ) ) );
6746 return QFileInfo( file ).isFile();
6751 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), parent );
6754 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"is_directory" ) ) );
6757 return QFileInfo( file ).isDir();
6762 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), parent );
6765 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_path" ) ) );
6768 return QDir::toNativeSeparators( QFileInfo( file ).path() );
6773 const QString file = QgsExpressionUtils::getFilePathValue( values.at( 0 ), parent );
6776 parent->
setEvalErrorString( QObject::tr(
"Function `%1` requires a value which represents a possible file path" ).arg( QLatin1String(
"file_size" ) ) );
6779 return QFileInfo( file ).size();
6782static QVariant fcnHash(
const QString &
str,
const QCryptographicHash::Algorithm
algorithm )
6784 return QString( QCryptographicHash::hash(
str.toUtf8(),
algorithm ).toHex() );
6790 QString
str = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
6791 QString method = QgsExpressionUtils::getStringValue( values.at( 1 ), parent ).toLower();
6793 if ( method == QLatin1String(
"md4" ) )
6795 hash = fcnHash(
str, QCryptographicHash::Md4 );
6797 else if ( method == QLatin1String(
"md5" ) )
6799 hash = fcnHash(
str, QCryptographicHash::Md5 );
6801 else if ( method == QLatin1String(
"sha1" ) )
6803 hash = fcnHash(
str, QCryptographicHash::Sha1 );
6805 else if ( method == QLatin1String(
"sha224" ) )
6807 hash = fcnHash(
str, QCryptographicHash::Sha224 );
6809 else if ( method == QLatin1String(
"sha256" ) )
6811 hash = fcnHash(
str, QCryptographicHash::Sha256 );
6813 else if ( method == QLatin1String(
"sha384" ) )
6815 hash = fcnHash(
str, QCryptographicHash::Sha384 );
6817 else if ( method == QLatin1String(
"sha512" ) )
6819 hash = fcnHash(
str, QCryptographicHash::Sha512 );
6821 else if ( method == QLatin1String(
"sha3_224" ) )
6823 hash = fcnHash(
str, QCryptographicHash::Sha3_224 );
6825 else if ( method == QLatin1String(
"sha3_256" ) )
6827 hash = fcnHash(
str, QCryptographicHash::Sha3_256 );
6829 else if ( method == QLatin1String(
"sha3_384" ) )
6831 hash = fcnHash(
str, QCryptographicHash::Sha3_384 );
6833 else if ( method == QLatin1String(
"sha3_512" ) )
6835 hash = fcnHash(
str, QCryptographicHash::Sha3_512 );
6837 else if ( method == QLatin1String(
"keccak_224" ) )
6839 hash = fcnHash(
str, QCryptographicHash::Keccak_224 );
6841 else if ( method == QLatin1String(
"keccak_256" ) )
6843 hash = fcnHash(
str, QCryptographicHash::Keccak_256 );
6845 else if ( method == QLatin1String(
"keccak_384" ) )
6847 hash = fcnHash(
str, QCryptographicHash::Keccak_384 );
6849 else if ( method == QLatin1String(
"keccak_512" ) )
6851 hash = fcnHash(
str, QCryptographicHash::Keccak_512 );
6855 parent->
setEvalErrorString( QObject::tr(
"Hash method %1 is not available on this system." ).arg(
str ) );
6862 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Md5 );
6867 return fcnHash( QgsExpressionUtils::getStringValue( values.at( 0 ), parent ), QCryptographicHash::Sha256 );
6872 const QByteArray input = values.at( 0 ).toByteArray();
6873 return QVariant( QString( input.toBase64() ) );
6878 const QVariantMap map = QgsExpressionUtils::getMapValue( values.at( 0 ), parent );
6880 for (
auto it = map.cbegin(); it != map.cend(); it++ )
6882 query.addQueryItem( it.key(), it.value().toString() );
6884 return query.toString( QUrl::ComponentFormattingOption::FullyEncoded );
6889 const QString value = QgsExpressionUtils::getStringValue( values.at( 0 ), parent );
6890 const QByteArray base64 = value.toLocal8Bit();
6891 const QByteArray decoded = QByteArray::fromBase64( base64 );
6892 return QVariant( decoded );
6897static 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 )
6900 const QVariant sourceLayerRef = context->
variable( QStringLiteral(
"layer" ) );
6901 QgsVectorLayer *sourceLayer = QgsExpressionUtils::getVectorLayer( sourceLayerRef, parent );
6909 QgsExpressionNode *node = QgsExpressionUtils::getNode( values.at( 0 ), parent );
6912 const bool layerCanBeCached = node->
isStatic( parent, context );
6913 QVariant targetLayerValue = node->
eval( parent, context );
6917 node = QgsExpressionUtils::getNode( values.at( 1 ), parent );
6919 QString subExpString = node->
dump();
6921 bool testOnly = ( subExpString ==
"NULL" );
6922 QgsVectorLayer *targetLayer = QgsExpressionUtils::getVectorLayer( targetLayerValue, parent );
6925 parent->
setEvalErrorString( QObject::tr(
"Layer '%1' could not be loaded." ).arg( targetLayerValue.toString() ) );
6930 node = QgsExpressionUtils::getNode( values.at( 2 ), parent );
6932 QString filterString = node->
dump();
6933 if ( filterString !=
"NULL" )
6939 node = QgsExpressionUtils::getNode( values.at( 3 ), parent );
6941 QVariant limitValue = node->
eval( parent, context );
6943 qlonglong limit = QgsExpressionUtils::getIntValue( limitValue, parent );
6946 double max_distance = 0;
6947 if ( isNearestFunc )
6949 node = QgsExpressionUtils::getNode( values.at( 4 ), parent );
6951 QVariant distanceValue = node->
eval( parent, context );
6953 max_distance = QgsExpressionUtils::getDoubleValue( distanceValue, parent );
6957 node = QgsExpressionUtils::getNode( values.at( isNearestFunc ? 5 : 4 ), parent );
6959 QVariant cacheValue = node->
eval( parent, context );
6961 bool cacheEnabled = cacheValue.toBool();
6967 double minOverlap { -1 };
6968 double minInscribedCircleRadius { -1 };
6969 bool returnDetails =
false;
6970 bool sortByMeasure =
false;
6971 bool sortAscending =
false;
6972 bool requireMeasures =
false;
6973 bool overlapOrRadiusFilter =
false;
6974 if ( isIntersectsFunc )
6977 node = QgsExpressionUtils::getNode( values.at( 5 ), parent );
6979 const QVariant minOverlapValue = node->
eval( parent, context );
6981 minOverlap = QgsExpressionUtils::getDoubleValue( minOverlapValue, parent );
6982 node = QgsExpressionUtils::getNode( values.at( 6 ), parent );
6984 const QVariant minInscribedCircleRadiusValue = node->
eval( parent, context );
6986 minInscribedCircleRadius = QgsExpressionUtils::getDoubleValue( minInscribedCircleRadiusValue, parent );
6987 node = QgsExpressionUtils::getNode( values.at( 7 ), parent );
6989 returnDetails = !testOnly && node->
eval( parent, context ).toBool();
6990 node = QgsExpressionUtils::getNode( values.at( 8 ), parent );
6992 const QString sorting { node->
eval( parent, context ).toString().toLower() };
6993 sortByMeasure = !testOnly && ( sorting.startsWith(
"asc" ) || sorting.startsWith(
"des" ) );
6994 sortAscending = sorting.startsWith(
"asc" );
6995 requireMeasures = sortByMeasure || returnDetails;
6996 overlapOrRadiusFilter = minInscribedCircleRadius != -1 || minOverlap != -1;
7003 if ( sourceLayer && targetLayer->
crs() != sourceLayer->
crs() )
7009 bool sameLayers = ( sourceLayer && sourceLayer->
id() == targetLayer->
id() );
7012 if ( bboxGrow != 0 )
7014 intDomain.
grow( bboxGrow );
7017 const QString cacheBase { QStringLiteral(
"%1:%2:%3" ).arg( targetLayer->
id(), subExpString, filterString ) };
7023 QList<QgsFeature> features;
7024 if ( isNearestFunc || ( layerCanBeCached && cacheEnabled ) )
7028 const QString cacheLayer { QStringLiteral(
"ovrlaylyr:%1" ).arg( cacheBase ) };
7029 const QString cacheIndex { QStringLiteral(
"ovrlayidx:%1" ).arg( cacheBase ) };
7033 cachedTarget = targetLayer->
materialize( request );
7034 if ( layerCanBeCached )
7035 context->
setCachedValue( cacheLayer, QVariant::fromValue( cachedTarget ) );
7045 if ( layerCanBeCached )
7046 context->
setCachedValue( cacheIndex, QVariant::fromValue( spatialIndex ) );
7053 QList<QgsFeatureId> fidsList;
7054 if ( isNearestFunc )
7056 fidsList = spatialIndex.
nearestNeighbor( geometry, sameLayers ? limit + 1 : limit, max_distance );
7060 fidsList = spatialIndex.
intersects( intDomain );
7063 QListIterator<QgsFeatureId> i( fidsList );
7064 while ( i.hasNext() )
7067 if ( sameLayers && feat.
id() == fId2 )
7069 features.append( cachedTarget->
getFeature( fId2 ) );
7082 if ( sameLayers && feat.
id() == feat2.
id() )
7084 features.append( feat2 );
7092 const QString expCacheKey { QStringLiteral(
"exp:%1" ).arg( cacheBase ) };
7093 const QString ctxCacheKey { QStringLiteral(
"ctx:%1" ).arg( cacheBase ) };
7099 subExpression.
prepare( &subContext );
7112 auto testLinestring = [ = ](
const QgsGeometry intersection,
double & overlapValue ) ->
bool
7114 bool testResult {
false };
7116 QVector<double> overlapValues;
7119 const QgsCurve *geom = qgsgeometry_cast< const QgsCurve * >( *it );
7121 if ( minOverlap != -1 || requireMeasures )
7123 overlapValue = geom->
length();
7124 overlapValues.append( overlapValue );
7125 if ( minOverlap != -1 )
7127 if ( overlapValue >= minOverlap )
7139 if ( ! overlapValues.isEmpty() )
7141 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
7148 auto testPolygon = [ = ](
const QgsGeometry intersection,
double & radiusValue,
double & overlapValue ) ->
bool
7151 bool testResult {
false };
7153 QVector<double> overlapValues;
7154 QVector<double> radiusValues;
7157 const QgsCurvePolygon *geom = qgsgeometry_cast< const QgsCurvePolygon * >( *it );
7159 if ( minOverlap != -1 || requireMeasures )
7161 overlapValue = geom->
area();
7162 overlapValues.append( geom->
area() );
7163 if ( minOverlap != - 1 )
7165 if ( overlapValue >= minOverlap )
7177 if ( minInscribedCircleRadius != -1 || requireMeasures )
7180 const double width = bbox.
width();
7181 const double height = bbox.
height();
7182 const double size = width > height ? width : height;
7183 const double tolerance = size / 100.0;
7185 testResult = radiusValue >= minInscribedCircleRadius;
7186 radiusValues.append( radiusValues );
7191 if ( !radiusValues.isEmpty() )
7193 radiusValue = *std::max_element( radiusValues.cbegin(), radiusValues.cend() );
7196 if ( ! overlapValues.isEmpty() )
7198 overlapValue = *std::max_element( overlapValues.cbegin(), overlapValues.cend() );
7208 QVariantList results;
7210 QListIterator<QgsFeature> i( features );
7211 while ( i.hasNext() && ( sortByMeasure || limit == -1 || foundCount < limit ) )
7217 if ( ! relationFunction || ( geometry.*relationFunction )( feat2.
geometry() ) )
7220 double overlapValue = -1;
7221 double radiusValue = -1;
7223 if ( isIntersectsFunc && ( requireMeasures || overlapOrRadiusFilter ) )
7230 switch ( intersection.
type() )
7237 bool testResult { testPolygon( intersection, radiusValue, overlapValue ) };
7239 if ( ! testResult && overlapOrRadiusFilter )
7252 if ( minInscribedCircleRadius != -1 )
7258 const bool testResult { testLinestring( intersection, overlapValue ) };
7260 if ( ! testResult && overlapOrRadiusFilter )
7273 if ( minInscribedCircleRadius != -1 )
7278 bool testResult {
false };
7279 if ( minOverlap != -1 || requireMeasures )
7299 testResult = testLinestring( feat2.
geometry(), overlapValue );
7304 testResult = testPolygon( feat2.
geometry(), radiusValue, overlapValue );
7310 if ( ! testResult && overlapOrRadiusFilter )
7338 const QVariant expResult = subExpression.
evaluate( &subContext );
7340 if ( requireMeasures )
7342 QVariantMap resultRecord;
7343 resultRecord.insert( QStringLiteral(
"id" ), feat2.
id() );
7344 resultRecord.insert( QStringLiteral(
"result" ), expResult );
7346 resultRecord.insert( QStringLiteral(
"overlap" ), overlapValue );
7348 if ( radiusValue != -1 )
7350 resultRecord.insert( QStringLiteral(
"radius" ), radiusValue );
7352 results.append( resultRecord );
7356 results.append( expResult );
7362 results.append( feat2.
id() );
7376 if ( requireMeasures )
7378 if ( sortByMeasure )
7380 std::sort( results.begin(), results.end(), [ sortAscending ](
const QVariant & recordA,
const QVariant & recordB ) ->
bool
7382 return sortAscending ?
7383 recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble()
7384 : recordA.toMap().value( QStringLiteral(
"overlap" ) ).toDouble() > recordB.toMap().value( QStringLiteral(
"overlap" ) ).toDouble();
7388 if ( limit > 0 && results.size() > limit )
7390 results.erase( results.begin() + limit );
7393 if ( ! returnDetails )
7395 QVariantList expResults;
7396 for (
auto it = results.constBegin(); it != results.constEnd(); ++it )
7398 expResults.append( it->toMap().value( QStringLiteral(
"result" ) ) );
7408 QVariantList disjoint_results;
7417 if ( !results.contains( feat2.
id() ) )
7420 disjoint_results.append( subExpression.
evaluate( &subContext ) );
7423 return disjoint_results;
7466 return executeGeomOverlay( values, context, parent,
nullptr,
false, 0,
true );
7475 static QRecursiveMutex sFunctionsMutex;
7476 QMutexLocker locker( &sFunctionsMutex );
7478 QList<QgsExpressionFunction *> &functions = *sFunctions();
7480 if ( functions.isEmpty() )
7517 functions << randFunc;
7521 functions << randfFunc;
7524 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max" ), -1, fcnMax, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
7525 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min" ), -1, fcnMin, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
7531 <<
new QgsStaticExpressionFunction( QStringLiteral(
"pi" ), 0, fcnPi, QStringLiteral(
"Math" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$pi" ) )
7535 <<
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" ) )
7536 <<
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" ) )
7537 <<
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" ) )
7542 <<
new QgsStaticExpressionFunction( QStringLiteral(
"coalesce" ), -1, fcnCoalesce, QStringLiteral(
"Conditionals" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
7556 QStringLiteral(
"Aggregates" ),
7565 if ( !node->
args() )
7568 QSet<QString> referencedVars;
7580 return referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() );
7589 if ( !node->
args() )
7590 return QSet<QString>();
7592 QSet<QString> referencedCols;
7593 QSet<QString> referencedVars;
7608 if ( referencedVars.contains( QStringLiteral(
"parent" ) ) || referencedVars.contains( QString() ) )
7611 return referencedCols;
7624 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count" ), aggParams, fcnAggregateCount, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7625 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_distinct" ), aggParams, fcnAggregateCountDistinct, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7626 <<
new QgsStaticExpressionFunction( QStringLiteral(
"count_missing" ), aggParams, fcnAggregateCountMissing, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7627 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minimum" ), aggParams, fcnAggregateMin, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7628 <<
new QgsStaticExpressionFunction( QStringLiteral(
"maximum" ), aggParams, fcnAggregateMax, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7629 <<
new QgsStaticExpressionFunction( QStringLiteral(
"sum" ), aggParams, fcnAggregateSum, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7630 <<
new QgsStaticExpressionFunction( QStringLiteral(
"mean" ), aggParams, fcnAggregateMean, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7631 <<
new QgsStaticExpressionFunction( QStringLiteral(
"median" ), aggParams, fcnAggregateMedian, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7632 <<
new QgsStaticExpressionFunction( QStringLiteral(
"stdev" ), aggParams, fcnAggregateStdev, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7633 <<
new QgsStaticExpressionFunction( QStringLiteral(
"range" ), aggParams, fcnAggregateRange, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7634 <<
new QgsStaticExpressionFunction( QStringLiteral(
"minority" ), aggParams, fcnAggregateMinority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7635 <<
new QgsStaticExpressionFunction( QStringLiteral(
"majority" ), aggParams, fcnAggregateMajority, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7636 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q1" ), aggParams, fcnAggregateQ1, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7637 <<
new QgsStaticExpressionFunction( QStringLiteral(
"q3" ), aggParams, fcnAggregateQ3, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7638 <<
new QgsStaticExpressionFunction( QStringLiteral(
"iqr" ), aggParams, fcnAggregateIQR, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7639 <<
new QgsStaticExpressionFunction( QStringLiteral(
"min_length" ), aggParams, fcnAggregateMinLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7640 <<
new QgsStaticExpressionFunction( QStringLiteral(
"max_length" ), aggParams, fcnAggregateMaxLength, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7641 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect" ), aggParams, fcnAggregateCollectGeometry, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7642 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate" ), aggParamsConcat, fcnAggregateStringConcat, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7643 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concatenate_unique" ), aggParamsConcat, fcnAggregateStringConcatUnique, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7644 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array_agg" ), aggParamsArray, fcnAggregateArray, QStringLiteral(
"Aggregates" ), QString(),
false, QSet<QString>(), true )
7649 <<
new QgsStaticExpressionFunction( QStringLiteral(
"now" ), 0, fcnNow, QStringLiteral(
"Date and Time" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"$now" ) )
7652 fcnAge, QStringLiteral(
"Date and Time" ) )
7666 fcnMakeDate, QStringLiteral(
"Date and Time" ) )
7670 fcnMakeTime, QStringLiteral(
"Date and Time" ) )
7677 fcnMakeDateTime, QStringLiteral(
"Date and Time" ) )
7685 fcnMakeInterval, QStringLiteral(
"Date and Time" ) )
7704 false, QSet< QString >(),
false, QStringList(), true )
7705 <<
new QgsStaticExpressionFunction( QStringLiteral(
"concat" ), -1, fcnConcat, QStringLiteral(
"String" ), QString(),
false, QSet<QString>(),
false, QStringList(), true )
7723 fcnColorMixRgb, QStringLiteral(
"Color" ) )
7727 fcnColorRgb, QStringLiteral(
"Color" ) )
7732 fncColorRgba, QStringLiteral(
"Color" ) )
7738 fcnCreateRamp, QStringLiteral(
"Color" ) )
7742 fcnColorHsl, QStringLiteral(
"Color" ) )
7747 fncColorHsla, QStringLiteral(
"Color" ) )
7751 fcnColorHsv, QStringLiteral(
"Color" ) )
7756 fncColorHsva, QStringLiteral(
"Color" ) )
7761 fcnColorCmyk, QStringLiteral(
"Color" ) )
7767 fncColorCmyka, QStringLiteral(
"Color" ) )
7770 fncColorPart, QStringLiteral(
"Color" ) )
7773 fncDarker, QStringLiteral(
"Color" ) )
7776 fncLighter, QStringLiteral(
"Color" ) )
7781 fcnBaseFileName, QStringLiteral(
"Files and Paths" ) )
7783 fcnFileSuffix, QStringLiteral(
"Files and Paths" ) )
7785 fcnFileExists, QStringLiteral(
"Files and Paths" ) )
7787 fcnFileName, QStringLiteral(
"Files and Paths" ) )
7789 fcnPathIsFile, QStringLiteral(
"Files and Paths" ) )
7791 fcnPathIsDir, QStringLiteral(
"Files and Paths" ) )
7793 fcnFilePath, QStringLiteral(
"Files and Paths" ) )
7795 fcnFileSize, QStringLiteral(
"Files and Paths" ) )
7798 fcnExif, QStringLiteral(
"Files and Paths" ) )
7800 fcnExifGeoTag, QStringLiteral(
"GeometryGroup" ) )
7804 fcnGenericHash, QStringLiteral(
"Conversions" ) )
7806 fcnHashMd5, QStringLiteral(
"Conversions" ) )
7808 fcnHashSha256, QStringLiteral(
"Conversions" ) )
7812 fcnToBase64, QStringLiteral(
"Conversions" ) )
7814 fcnFromBase64, QStringLiteral(
"Conversions" ) )
7820 geomFunc->setIsStatic(
false );
7821 functions << geomFunc;
7825 functions << areaFunc;
7831 functions << lengthFunc;
7835 functions << perimeterFunc;
7841 fcnRoundness, QStringLiteral(
"GeometryGroup" ) );
7855 QMap< QString, QgsExpressionFunction::FcnEval > geometry_overlay_definitions
7857 { QStringLiteral(
"overlay_intersects" ), fcnGeomOverlayIntersects },
7858 { QStringLiteral(
"overlay_contains" ), fcnGeomOverlayContains },
7859 { QStringLiteral(
"overlay_crosses" ), fcnGeomOverlayCrosses },
7860 { QStringLiteral(
"overlay_equals" ), fcnGeomOverlayEquals },
7861 { QStringLiteral(
"overlay_touches" ), fcnGeomOverlayTouches },
7862 { QStringLiteral(
"overlay_disjoint" ), fcnGeomOverlayDisjoint },
7863 { QStringLiteral(
"overlay_within" ), fcnGeomOverlayWithin },
7865 QMapIterator< QString, QgsExpressionFunction::FcnEval > i( geometry_overlay_definitions );
7866 while ( i.hasNext() )
7883 functions << fcnGeomOverlayFunc;
7896 functions << fcnGeomOverlayNearestFunc;
7909 fcnNodesToPoints, QStringLiteral(
"GeometryGroup" ) )
7911 <<
new QgsStaticExpressionFunction( QStringLiteral(
"collect_geometries" ), -1, fcnCollectGeometries, QStringLiteral(
"GeometryGroup" ) )
7916 fcnMakePointM, QStringLiteral(
"GeometryGroup" ) )
7922 fcnMakeTriangle, QStringLiteral(
"GeometryGroup" ) )
7927 fcnMakeCircle, QStringLiteral(
"GeometryGroup" ) )
7934 fcnMakeEllipse, QStringLiteral(
"GeometryGroup" ) )
7940 fcnMakeRegularPolygon, QStringLiteral(
"GeometryGroup" ) )
7944 fcnMakeSquare, QStringLiteral(
"GeometryGroup" ) )
7950 fcnMakeRectangleFrom3Points, QStringLiteral(
"GeometryGroup" ) )
7954#if GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR<10
7960 }, fcnGeomMakeValid, QStringLiteral(
"GeometryGroup" ) );
7962 xAtFunc->setIsStatic(
false );
7963 functions << xAtFunc;
7967 functions << yAtFunc;
7983 fcnDisjoint, QStringLiteral(
"GeometryGroup" ) )
7986 fcnIntersects, QStringLiteral(
"GeometryGroup" ) )
7989 fcnTouches, QStringLiteral(
"GeometryGroup" ) )
7992 fcnCrosses, QStringLiteral(
"GeometryGroup" ) )
7995 fcnContains, QStringLiteral(
"GeometryGroup" ) )
7998 fcnOverlaps, QStringLiteral(
"GeometryGroup" ) )
8001 fcnWithin, QStringLiteral(
"GeometryGroup" ) )
8005 fcnTranslate, QStringLiteral(
"GeometryGroup" ) )
8010 fcnRotate, QStringLiteral(
"GeometryGroup" ) )
8015 fcnScale, QStringLiteral(
"GeometryGroup" ) )
8026 fcnAffineTransform, QStringLiteral(
"GeometryGroup" ) )
8033 fcnBuffer, QStringLiteral(
"GeometryGroup" ) )
8035 fcnForceRHR, QStringLiteral(
"GeometryGroup" ) )
8037 fcnForcePolygonCW, QStringLiteral(
"GeometryGroup" ) )
8039 fcnForcePolygonCCW, QStringLiteral(
"GeometryGroup" ) )
8049 , fcnTaperedBuffer, QStringLiteral(
"GeometryGroup" ) )
8052 , fcnBufferByM, QStringLiteral(
"GeometryGroup" ) )
8058 fcnOffsetCurve, QStringLiteral(
"GeometryGroup" ) )
8064 fcnSingleSidedBuffer, QStringLiteral(
"GeometryGroup" ) )
8068 fcnExtend, QStringLiteral(
"GeometryGroup" ) )
8077 fcnInteriorRingN, QStringLiteral(
"GeometryGroup" ) )
8080 fcnGeometryN, QStringLiteral(
"GeometryGroup" ) )
8087 }, fcnSharedPaths, QStringLiteral(
"GeometryGroup" ) )
8101 }, fcnTriangularWave, QStringLiteral(
"GeometryGroup" ) )
8110 }, fcnTriangularWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
8117 }, fcnSquareWave, QStringLiteral(
"GeometryGroup" ) )
8126 }, fcnSquareWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
8133 }, fcnRoundWave, QStringLiteral(
"GeometryGroup" ) )
8142 }, fcnRoundWaveRandomized, QStringLiteral(
"GeometryGroup" ) )
8151 }, fcnApplyDashPattern, QStringLiteral(
"GeometryGroup" ) )
8156 }, fcnDensifyByCount, QStringLiteral(
"GeometryGroup" ) )
8161 }, fcnDensifyByDistance, QStringLiteral(
"GeometryGroup" ) )
8173#
if GEOS_VERSION_MAJOR>3 || ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR>=11 )
8180 fcnOrientedBBox, QStringLiteral(
"GeometryGroup" ) )
8183 fcnMainAngle, QStringLiteral(
"GeometryGroup" ) )
8187 fcnMinimalCircle, QStringLiteral(
"GeometryGroup" ) )
8190 fcnDifference, QStringLiteral(
"GeometryGroup" ) )
8193 fcnDistance, QStringLiteral(
"GeometryGroup" ) )
8196 fcnHausdorffDistance, QStringLiteral(
"GeometryGroup" ) )
8199 fcnIntersection, QStringLiteral(
"GeometryGroup" ) )
8202 fcnSymDifference, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"symDifference" ) )
8205 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
8208 fcnCombine, QStringLiteral(
"GeometryGroup" ) )
8211 fcnGeomToWKT, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"geomToWKT" ) )
8213 fcnGeomToWKB, QStringLiteral(
"GeometryGroup" ), QString(),
false, QSet<QString>(),
false )
8218 fcnTransformGeometry, QStringLiteral(
"GeometryGroup" ) )
8222 fcnExtrude, QStringLiteral(
"GeometryGroup" ), QString() )
8224 fcnGeomIsMultipart, QStringLiteral(
"GeometryGroup" ) )
8226 fcnZMax, QStringLiteral(
"GeometryGroup" ) )
8228 fcnZMin, QStringLiteral(
"GeometryGroup" ) )
8230 fcnMMax, QStringLiteral(
"GeometryGroup" ) )
8232 fcnMMin, QStringLiteral(
"GeometryGroup" ) )
8234 fcnSinuosity, QStringLiteral(
"GeometryGroup" ) )
8236 fcnStraightDistance2d, QStringLiteral(
"GeometryGroup" ) );
8242 fcnOrderParts, QStringLiteral(
"GeometryGroup" ), QString() );
8247 const QList< QgsExpressionNode *> argList = node->
args()->list();
8250 if ( !argNode->isStatic( parent, context ) )
8258 QString expString = argNode->
eval( parent, context ).toString();
8274 QString
expression = argNode->
eval( parent, context ).toString();
8282 functions << orderPartsFunc;
8287 fcnClosestPoint, QStringLiteral(
"GeometryGroup" ) )
8290 fcnShortestLine, QStringLiteral(
"GeometryGroup" ) )
8309 functions << idFunc;
8313 functions << currentFeatureFunc;
8315 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" ) );
8317 functions << uuidFunc;
8323 fcnGetFeature, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false, QStringList() << QStringLiteral(
"QgsExpressionUtils::getFeature" ) )
8326 fcnGetFeatureById, QStringLiteral(
"Record and Attributes" ), QString(),
false, QSet<QString>(),
false );
8331 functions << attributesFunc;
8335 functions << representAttributesFunc;
8338 QStringLiteral(
"maptip" ),
8341 QStringLiteral(
"Record and Attributes" ),
8347 functions << maptipFunc;
8350 QStringLiteral(
"display_expression" ),
8352 fcnFeatureDisplayExpression,
8353 QStringLiteral(
"Record and Attributes" ),
8359 functions << displayFunc;
8362 QStringLiteral(
"is_selected" ),
8365 QStringLiteral(
"Record and Attributes" ),
8371 functions << isSelectedFunc;
8375 QStringLiteral(
"num_selected" ),
8378 QStringLiteral(
"Record and Attributes" ),
8386 QStringLiteral(
"sqlite_fetch_and_increment" ),
8394 fcnSqliteFetchAndIncrement,
8395 QStringLiteral(
"Record and Attributes" )
8413 parent->
setEvalErrorString( tr(
"If represent_value is called with 1 parameter, it must be an attribute." ) );
8423 parent->
setEvalErrorString( tr(
"represent_value must be called with exactly 1 or 2 parameters." ) );
8429 functions << representValueFunc;
8435 fcnGetLayerProperty, QStringLiteral(
"Map Layers" ) )
8440 fcnDecodeUri, QStringLiteral(
"Map Layers" ) )
8444 fcnMimeType, QStringLiteral(
"General" ) )
8461 QgsExpressionNode *argNode = node->args()->at( 0 );
8463 if ( !argNode->isStatic( parent, context ) )
8466 const QString varName = argNode->eval( parent, context ).toString();
8467 if ( varName == QLatin1String(
"feature" ) || varName == QLatin1String(
"id" ) || varName == QLatin1String(
"geometry" ) )
8470 const QgsExpressionContextScope *scope = context->activeScopeForVariable( varName );
8471 return scope ? scope->isStatic( varName ) : false;
8479 if ( node && node->
args()->
count() > 0 )
8484 if ( literal->value() == QLatin1String(
"geometry" ) || literal->value() == QLatin1String(
"feature" ) )
8503 QgsExpressionNode *argNode = node->args()->at( 0 );
8505 if ( argNode->isStatic( parent, context ) )
8507 QString expString = argNode->eval( parent, context ).toString();
8509 QgsExpression e( expString );
8511 if ( e.rootNode() && e.rootNode()->isStatic( parent, context ) )
8519 functions << evalFunc;
8525 const QList< QgsExpressionNode *> argList = node->
args()->list();
8528 if ( !argNode->isStatic( parent, context ) )
8540 functions << attributeFunc;
8550 <<
new QgsStaticExpressionFunction( QStringLiteral(
"array" ), -1, fcnArray, QStringLiteral(
"Arrays" ), QString(),
false, QSet<QString>(),
false, QStringList(),
true )
8599 fcnMapPrefixKeys, QStringLiteral(
"Maps" ) )
8601 fcnToFormUrlEncode, QStringLiteral(
"Maps" ) )
8610 *sOwnedFunctions() << func;
8611 *sBuiltinFunctions() << func->name();
8612 sBuiltinFunctions()->append( func->aliases() );
8625 sFunctions()->append( function );
8626 if ( transferOwnership )
8627 sOwnedFunctions()->append( function );
8641 sFunctions()->removeAt( fnIdx );
8649 qDeleteAll( *sOwnedFunctions() );
8650 sOwnedFunctions()->clear();
8655 if ( sBuiltinFunctions()->isEmpty() )
8659 return *sBuiltinFunctions();
8667 QStringLiteral(
"Arrays" ) )
8678 if ( args->
count() < 2 )
8681 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
8691 QVariantList result;
8693 if ( args->
count() < 2 )
8697 QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
8700 std::unique_ptr< QgsExpressionContext > tempContext;
8703 tempContext = std::make_unique< QgsExpressionContext >();
8704 subContext = tempContext.get();
8710 for ( QVariantList::const_iterator it = array.constBegin(); it != array.constEnd(); ++it )
8713 result << args->
at( 1 )->
eval( parent, subContext );
8738 if ( args->
count() < 2 )
8742 args->
at( 0 )->
prepare( parent, context );
8746 subContext = *context;
8752 args->
at( 1 )->
prepare( parent, &subContext );
8762 QStringLiteral(
"Arrays" ) )
8773 if ( args->
count() < 2 )
8776 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
8786 QVariantList result;
8788 if ( args->
count() < 2 )
8792 const QVariantList array = args->
at( 0 )->
eval( parent, context ).toList();
8795 std::unique_ptr< QgsExpressionContext > tempContext;
8798 tempContext = std::make_unique< QgsExpressionContext >();
8799 subContext = tempContext.get();
8806 if ( args->
count() >= 3 )
8808 const QVariant limitVar = args->
at( 2 )->
eval( parent, context );
8810 if ( QgsExpressionUtils::isIntSafe( limitVar ) )
8812 limit = limitVar.toInt();
8820 for (
const QVariant &value : array )
8823 if ( args->
at( 1 )->
eval( parent, subContext ).toBool() )
8827 if ( limit > 0 && limit == result.size() )
8854 if ( args->
count() < 2 )
8858 args->
at( 0 )->
prepare( parent, context );
8862 subContext = *context;
8868 args->
at( 1 )->
prepare( parent, &subContext );
8877 QStringLiteral(
"General" ) )
8888 if ( args->
count() < 3 )
8892 if ( args->
at( 0 )->
isStatic( parent, context ) && args->
at( 1 )->
isStatic( parent, context ) )
8894 QVariant
name = args->
at( 0 )->
eval( parent, context );
8895 QVariant value = args->
at( 1 )->
eval( parent, context );
8898 appendTemporaryVariable( context,
name.toString(), value );
8899 if ( args->
at( 2 )->
isStatic( parent, context ) )
8901 popTemporaryVariable( context );
8912 if ( args->
count() < 3 )
8916 QVariant
name = args->
at( 0 )->
eval( parent, context );
8917 QVariant value = args->
at( 1 )->
eval( parent, context );
8920 std::unique_ptr< QgsExpressionContext > tempContext;
8921 if ( !updatedContext )
8923 tempContext = std::make_unique< QgsExpressionContext >();
8924 updatedContext = tempContext.get();
8927 appendTemporaryVariable( updatedContext,
name.toString(), value );
8928 result = args->
at( 2 )->
eval( parent, updatedContext );
8931 popTemporaryVariable( updatedContext );
8952 if ( args->
count() < 3 )
8957 QVariant value = args->
at( 1 )->
prepare( parent, context );
8960 std::unique_ptr< QgsExpressionContext > tempContext;
8961 if ( !updatedContext )
8963 tempContext = std::make_unique< QgsExpressionContext >();
8964 updatedContext = tempContext.get();
8967 appendTemporaryVariable( updatedContext,
name.toString(), value );
8968 args->
at( 2 )->
prepare( parent, updatedContext );
8971 popTemporaryVariable( updatedContext );
8976void QgsWithVariableExpressionFunction::popTemporaryVariable(
const QgsExpressionContext *context )
const
8982void QgsWithVariableExpressionFunction::appendTemporaryVariable(
const QgsExpressionContext *context,
const QString &name,
const QVariant &value )
const
@ Left
Buffer to left of line.
DashPatternSizeAdjustment
Dash pattern size adjustment options.
@ ScaleDashOnly
Only dash lengths are adjusted.
@ ScaleBothDashAndGap
Both the dash and gap lengths are adjusted equally.
@ ScaleGapOnly
Only gap lengths are adjusted.
@ Success
Operation succeeded.
JoinStyle
Join styles for buffers.
@ Bevel
Use beveled joins.
@ Round
Use rounded joins.
@ Miter
Use mitered joins.
EndCapStyle
End cap styles for buffers.
@ Flat
Flat cap (in line with start/end of line)
@ Square
Square cap (extends past start/end of line by buffer distance)
DashPatternLineEndingRule
Dash pattern line ending rules.
@ HalfDash
Start or finish the pattern with a half length dash.
@ HalfGap
Start or finish the pattern with a half length gap.
@ FullGap
Start or finish the pattern with a full gap.
@ FullDash
Start or finish the pattern with a full dash.
MakeValidMethod
Algorithms to use when repairing invalid geometries.
@ Linework
Combines all rings into a set of noded lines and then extracts valid polygons from that linework.
@ Structure
Structured method, first makes all rings valid and then merges shells and subtracts holes from shells...
Abstract base class for all geometries.
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
virtual QgsAbstractGeometry * boundary() const =0
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
virtual const QgsAbstractGeometry * simplifiedTypeRef() const
Returns a reference to the simplest lossless representation of this geometry, e.g.
bool isMeasure() const
Returns true if the geometry contains m values.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
part_iterator parts_end()
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
virtual double length() const
Returns the planar, 2-dimensional length of the geometry.
virtual QgsCoordinateSequence coordinateSequence() const =0
Retrieves the sequence of geometries, rings and nodes.
virtual int partCount() const =0
Returns count of parts contained in the geometry.
part_iterator parts_begin()
Returns STL-style iterator pointing to the first part of the geometry.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
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.
QString toProj() const
Returns a Proj string representation of this CRS.
QgsUnitTypes::DistanceUnit mapUnits
Contains information about the context in which a coordinate transform is executed.
Custom exception class for Coordinate Reference System related exceptions.
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
bool isEmpty() const override
Returns true if the geometry is empty.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
double area() const override
Returns the planar, 2-dimensional area of the geometry.
double roundness() const
Returns the roundness of the curve polygon.
int ringCount(int part=0) const override
Returns the number of rings of which this geometry is built.
Abstract base class for curved geometry type.
double sinuosity() const
Returns the curve sinuosity, which is the ratio of the curve length() to curve straightDistance2d().
QgsCurve * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
virtual QgsCurve * curveSubstring(double startDistance, double endDistance) const =0
Returns a new curve representing a substring of this curve.
virtual bool isClosed() const
Returns true if the curve is closed.
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
double straightDistance2d() const
Returns the straight distance of the curve, i.e.
virtual QgsCurve * reversed() const =0
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
double measureArea(const QgsGeometry &geometry) const
Measures the area of a geometry.
double 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, QgsUnitTypes::AreaUnit toUnits) const
Takes an area measurement calculated by this QgsDistanceArea object and converts it to a different ar...
double convertLengthMeasurement(double length, QgsUnitTypes::DistanceUnit toUnits) const
Takes a length measurement calculated by this QgsDistanceArea object and converts it to a different d...
Single scope for storing variables and functions for use within a QgsExpressionContext.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
bool isStatic(const QString &name) const
Tests whether the variable with the specified name is static and can be cached.
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
static void registerContextFunctions()
Registers all known core functions provided by QgsExpressionContextScope objects.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
void setCachedValue(const QString &key, const QVariant &value) const
Sets a value to cache within the expression context.
QgsGeometry geometry() const
Convenience function for retrieving the geometry for the context, if set.
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
QgsExpressionContextScope * activeScopeForVariable(const QString &name)
Returns the currently active scope from the context for a specified variable name.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
QgsFeedback * feedback() const
Returns the feedback object that can be queried regularly by the expression to check if evaluation sh...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
bool hasGeometry() const
Returns true if the context has a geometry associated with it.
bool hasCachedValue(const QString &key) const
Returns true if the expression context contains a cached value with a matching key.
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
QVariant cachedValue(const QString &key) const
Returns the matching cached value, if set.
bool hasFeature() const
Returns true if the context has a feature associated with it.
QgsFields fields() const
Convenience function for retrieving the fields for the context, if set.
Represents a single parameter passed to a function.
A abstract base class for defining QgsExpression functions.
QList< QgsExpressionFunction::Parameter > ParameterList
List of parameters, used for function definition.
bool operator==(const QgsExpressionFunction &other) const
virtual bool isDeprecated() const
Returns true if the function is deprecated and should not be presented as a valid option to users in ...
virtual bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
Will be called during prepare to determine if the function is static.
virtual QStringList aliases() const
Returns a list of possible aliases for the function.
bool lazyEval() const
true if this function should use lazy evaluation.
static bool allParamsStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context)
This will return true if all the params for the provided function node are static within the constrai...
QString name() const
The name of the function.
virtual QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
Evaluates the function, first evaluating all required arguments before passing them to the function's...
virtual QVariant func(const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)=0
Returns result of evaluating the function.
virtual QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const
Returns a set of field names which are required for this function.
virtual bool handlesNull() const
Returns true if the function handles NULL values in arguments by itself, and the default NULL value h...
virtual bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
This will be called during the prepare step() of an expression if it is not static.
virtual bool usesGeometry(const QgsExpressionNodeFunction *node) const
Does this function use a geometry object.
An expression node which takes it value from a feature's field.
QString name() const
The name of the column.
An expression node for expression functions.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
An expression node for literal values.
A list of expression nodes.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
QgsExpressionNode * at(int i)
Gets the node at position i in the list.
int count() const
Returns the number of nodes in the list.
Abstract base class for all nodes that can appear in an expression.
virtual QString dump() const =0
Dump this node into a serialized (part) of an expression.
QVariant eval(QgsExpression *parent, const QgsExpressionContext *context)
Evaluate this node with the given context and parent.
virtual bool isStatic(QgsExpression *parent, const QgsExpressionContext *context) const =0
Returns true if this node can be evaluated for a static value.
bool prepare(QgsExpression *parent, const QgsExpressionContext *context)
Prepare this node for evaluation.
virtual QSet< QString > referencedColumns() const =0
Abstract virtual method which returns a list of columns required to evaluate this node.
virtual QSet< QString > referencedVariables() const =0
Returns a set of all variables which are used in this expression.
A set of expression-related functions.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
static const QList< QgsExpressionFunction * > & Functions()
QString expression() const
Returns the original, unmodified expression string.
static void cleanRegisteredFunctions()
Deletes all registered functions whose ownership have been transferred to the expression engine.
static bool registerFunction(QgsExpressionFunction *function, bool transferOwnership=false)
Registers a function to the expression engine.
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
static const QStringList & BuiltinFunctions()
static QString 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...
QgsUnitTypes::AreaUnit areaUnits() const
Returns the desired areal units for calculations involving geomCalculator(), e.g.,...
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.
QgsUnitTypes::DistanceUnit distanceUnits() const
Returns the desired distance units for calculations involving geomCalculator(), e....
void setEvalErrorString(const QString &str)
Sets evaluation error (used internally by evaluation functions)
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
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 & setDestinationCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets the destination crs for feature's geometries.
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.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
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.
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Container of fields for a vector layer.
int count() 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.
virtual bool removeGeometry(int nr)
Removes a geometry from the collection.
QgsGeometryCollection * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
int partCount() const override
Returns count of parts contained in the geometry.
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
static QVector< QgsLineString * > extractLineStrings(const QgsAbstractGeometry *geom)
Returns list of linestrings extracted from the passed geometry.
A geometry is the spatial representation of a feature.
double hausdorffDistanceDensify(const QgsGeometry &geom, double densifyFraction) const
Returns the Hausdorff distance between this geometry and geom.
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Returns a copy of the geometry which has been densified by adding the specified number of extra nodes...
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
double lineLocatePoint(const QgsGeometry &point) const
Returns a distance representing the location along this linestring of the closest point on this lines...
QgsGeometry difference(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing the points making up this geometry that do not make up other.
double length() const
Returns the planar, 2-dimensional length of geometry.
QgsGeometry offsetCurve(double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit) const
Returns an offset line at a given distance and side from an input line.
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
QgsGeometry poleOfInaccessibility(double precision, double *distanceToBoundary=nullptr) const
Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal ...
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
QgsGeometry squareWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs square waves along the boundary of the geometry, with the specified wavelength and amplitu...
QgsGeometry triangularWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs triangular waves along the boundary of the geometry, with the specified wavelength and amp...
bool vertexIdFromVertexNr(int number, QgsVertexId &id) const
Calculates the vertex ID from a vertex number.
QgsGeometry pointOnSurface() const
Returns a point guaranteed to lie on the surface of a geometry.
bool touches(const QgsGeometry &geometry) const
Returns true if the geometry touches another geometry.
QgsGeometry applyDashPattern(const QVector< double > &pattern, Qgis::DashPatternLineEndingRule startRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternLineEndingRule endRule=Qgis::DashPatternLineEndingRule::NoRule, Qgis::DashPatternSizeAdjustment adjustment=Qgis::DashPatternSizeAdjustment::ScaleBothDashAndGap, double patternOffset=0) const
Applies a dash pattern to a geometry, returning a MultiLineString geometry which is the input geometr...
QgsGeometry roundWaves(double wavelength, double amplitude, bool strictWavelength=false) const
Constructs rounded (sine-like) waves along the boundary of the geometry, with the specified wavelengt...
QgsGeometry nearestPoint(const QgsGeometry &other) const
Returns the nearest (closest) point on this geometry to another geometry.
static QgsGeometry collectGeometry(const QVector< QgsGeometry > &geometries)
Creates a new multipart geometry from a list of QgsGeometry objects.
QgsGeometry makeValid(Qgis::MakeValidMethod method=Qgis::MakeValidMethod::Linework, bool keepCollapsed=false) const
Attempts to make an invalid geometry valid without losing vertices.
QString lastError() const
Returns an error string referring to the last error encountered either when this geometry was created...
QgsGeometry combine(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing all the points in this geometry and other (a union geometry operation...
QgsGeometry variableWidthBufferByM(int segments) const
Calculates a variable width buffer for a (multi)linestring geometry, where the width at each node is ...
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
QgsMultiPointXY asMultiPoint() const
Returns the contents of the geometry as a multi-point.
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
bool disjoint(const QgsGeometry &geometry) const
Returns true if the geometry is disjoint of another geometry.
QVector< QgsGeometry > asGeometryCollection() const
Returns contents of the geometry as a list of geometries.
QgsGeometry roundWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized rounded (sine-like) waves along the boundary of the geometry,...
double distance(const QgsGeometry &geom) const
Returns the minimum distance between this geometry and another geometry.
QgsGeometry interpolate(double distance) const
Returns an interpolated point on the geometry at the specified distance.
QgsGeometry extrude(double x, double y)
Returns an extruded version of this geometry.
QgsGeometry singleSidedBuffer(double distance, int segments, Qgis::BufferSide side, Qgis::JoinStyle joinStyle=Qgis::JoinStyle::Round, double miterLimit=2.0) const
Returns a single sided buffer for a (multi)line geometry.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
bool contains(const QgsPointXY *p) const
Returns true if the geometry contains the point p.
QgsGeometry forceRHR() const
Forces geometries to respect the Right-Hand-Rule, in which the area that is bounded by a polygon is t...
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
bool equals(const QgsGeometry &geometry) const
Test if this geometry is exactly equal to another geometry.
bool isGeosValid(Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const
Checks validity of the geometry using GEOS.
QgsWkbTypes::GeometryType type
QgsGeometry taperedBuffer(double startWidth, double endWidth, int segments) const
Calculates a variable width buffer ("tapered buffer") for a (multi)curve geometry.
bool within(const QgsGeometry &geometry) const
Returns true if the geometry is completely within another geometry.
QgsGeometry orientedMinimumBoundingBox(double &area, double &angle, double &width, double &height) const
Returns the oriented minimum bounding box for the geometry, which is the smallest (by area) rotated r...
double area() const
Returns the planar, 2-dimensional area of the geometry.
bool isMultipart() const
Returns true if WKB of the geometry is of WKBMulti* type.
QgsGeometry centroid() const
Returns the center of mass of a geometry.
bool crosses(const QgsGeometry &geometry) const
Returns true if the geometry crosses another geometry.
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.
QgsGeometry concaveHull(double targetPercent, bool allowHoles=false) const
Returns a possibly concave polygon that contains all the points in the geometry.
QgsGeometry convexHull() const
Returns the smallest convex polygon that contains all the points in the geometry.
QgsGeometry sharedPaths(const QgsGeometry &other) const
Find paths shared between the two given lineal geometries (this and other).
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
QgsGeometry intersection(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing the points shared by this geometry and other.
QgsGeometry symDifference(const QgsGeometry &geometry, const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Returns a geometry representing the points making up this geometry that do not make up other.
QgsGeometry minimalEnclosingCircle(QgsPointXY ¢er, double &radius, unsigned int segments=36) const
Returns the minimal enclosing circle for the geometry.
QgsGeometry mergeLines() const
Merges any connected lines in a LineString/MultiLineString geometry and converts them to single line ...
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
double distanceToVertex(int vertex) const
Returns the distance along this geometry from its first vertex to the specified vertex.
QgsAbstractGeometry::const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
QgsGeometry forcePolygonClockwise() const
Forces geometries to respect the exterior ring is clockwise, interior rings are counter-clockwise con...
static QgsGeometry createWedgeBuffer(const QgsPoint ¢er, double azimuth, double angularWidth, double outerRadius, double innerRadius=0)
Creates a wedge shaped buffer from a center point.
QgsGeometry extendLine(double startDistance, double endDistance) const
Extends a (multi)line geometry by extrapolating out the start or end of the line by a specified dista...
QgsGeometry triangularWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized triangular waves along the boundary of the geometry, with the specified wavelen...
QgsGeometry squareWavesRandomized(double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed=0) const
Constructs randomized square waves along the boundary of the geometry, with the specified wavelength ...
QgsGeometry simplify(double tolerance) const
Returns a simplified version of this geometry using a specified tolerance value.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Qgis::GeometryOperationResult rotate(double rotation, const QgsPointXY ¢er)
Rotate this geometry around the Z axis.
Qgis::GeometryOperationResult translate(double dx, double dy, double dz=0.0, double dm=0.0)
Translates this geometry by dx, dy, dz and dm.
double interpolateAngle(double distance) const
Returns the angle parallel to the linestring or polygon boundary at the specified distance along the ...
double angleAtVertex(int vertex) const
Returns the bisector angle for this geometry at the specified vertex.
QgsGeometry smooth(unsigned int iterations=1, double offset=0.25, double minimumDistance=-1.0, double maxAngle=180.0) const
Smooths a geometry by rounding off corners using the Chaikin algorithm.
QgsGeometry forcePolygonCounterClockwise() const
Forces geometries to respect the exterior ring is counter-clockwise, interior rings are clockwise con...
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 id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
QgsLayerMetadata metadata
QString abstract() const
Returns the abstract of the layer used by QGIS Server in GetCapabilities request.
virtual bool isEditable() const
Returns true if the layer can be edited.
QString title() const
Returns the title of the layer used by QGIS Server in GetCapabilities request.
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.
QString keywordList() const
Returns the keyword list of the layer used by QGIS Server in GetCapabilities request.
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.
double inclination(const QgsPoint &other) const
Calculates Cartesian inclination between this point and other one (starting from zenith = 0 to nadir ...
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override
Checks validity of the geometry, and returns true if the geometry is valid.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which corresponds to this point projected by a specified distance with specified ...
QgsRelationManager * relationManager
static QgsProject * instance()
Returns the QgsProject singleton instance.
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
QList< QgsMapLayer * > mapLayersByName(const QString &layerName) const
Retrieve a list of matching registered layers by layer name.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
Quadrilateral geometry type.
static QgsQuadrilateral squareFromDiagonal(const QgsPoint &p1, const QgsPoint &p2)
Construct a QgsQuadrilateral as a square from a diagonal.
QgsPolygon * toPolygon(bool force2D=false) const
Returns the quadrilateral as a new polygon.
static QgsQuadrilateral rectangleFrom3Points(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &p3, ConstructionOption mode)
Construct a QgsQuadrilateral as a Rectangle from 3 points.
ConstructionOption
A quadrilateral can be constructed from 3 points where the second distance can be determined by the t...
@ Distance
Second distance is equal to the distance between 2nd and 3rd point.
@ Projected
Second distance is equal to the distance of the perpendicular projection of the 3rd point on the segm...
The 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.
virtual double sample(const QgsPointXY &point, int band, bool *ok=nullptr, const QgsRectangle &boundingBox=QgsRectangle(), int width=0, int height=0, int dpi=96)
Samples a raster value from the specified band found at the point position.
virtual QgsRasterBandStats bandStatistics(int bandNo, int stats=QgsRasterBandStats::All, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
Represents a raster layer.
int bandCount() const
Returns the number of bands in this layer.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
A rectangle specified with double values.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double width() const
Returns the width of the rectangle.
double xMaximum() const
Returns the x maximum value (right side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
QgsPointXY center() const
Returns the center point of the rectangle.
void grow(double delta)
Grows the rectangle in place by the specified amount.
double height() const
Returns the height of the rectangle.
Regular Polygon geometry type.
ConstructionOption
A regular polygon can be constructed inscribed in a circle or circumscribed about a circle.
@ CircumscribedCircle
Circumscribed about a circle (the radius is the distance from the center to the midpoints of the side...
@ InscribedCircle
Inscribed in a circle (the radius is the distance between the center and vertices)
QgsPolygon * toPolygon() const
Returns as a polygon.
QList< QgsRelation > relationsByName(const QString &name) const
Returns a list of relations with matching names.
Q_INVOKABLE QgsRelation relation(const QString &id) const
Gets access to a relation by its id.
QgsVectorLayer * referencedLayer
QgsVectorLayer * referencingLayer
QString getRelatedFeaturesFilter(const QgsFeature &feature) const
Returns a filter expression which returns all the features on the referencing (child) layer which hav...
A spatial index for QgsFeature objects.
@ FlagStoreFeatureGeometries
Indicates that the spatial index should also store feature geometries. This requires more memory,...
QList< QgsFeatureId > nearestNeighbor(const QgsPointXY &point, int neighbors=1, double maxDistance=0) const
Returns nearest neighbors to a point.
QList< QgsFeatureId > intersects(const QgsRectangle &rectangle) const
Returns a list of features with a bounding box which intersects the specified rectangle.
static QString quotedIdentifier(const QString &identifier)
Returns a properly quoted version of identifier.
static QString quotedValue(const QVariant &value)
Returns a properly quoted and escaped version of value for use in SQL strings.
c++ helper class for defining QgsExpression functions.
bool prepare(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
This will be called during the prepare step() of an expression if it is not static.
void setIsStaticFunction(const std::function< bool(const QgsExpressionNodeFunction *, QgsExpression *, const QgsExpressionContext *) > &isStatic)
Set a function that will be called in the prepare step to determine if the function is static or not.
QStringList aliases() const override
Returns a list of possible aliases for the function.
void setPrepareFunction(const std::function< bool(const QgsExpressionNodeFunction *, QgsExpression *, const QgsExpressionContext *)> &prepareFunc)
Set a function that will be called in the prepare step to determine if the function is static or not.
void setUsesGeometryFunction(const std::function< bool(const QgsExpressionNodeFunction *node)> &usesGeometry)
Set a function that will be called when determining if the function requires feature geometry or not.
bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const override
Will be called during prepare to determine if the function is static.
void setIsStatic(bool isStatic)
Tag this function as either static or not static.
QgsStaticExpressionFunction(const QString &fnname, int params, FcnEval fcn, const QString &group, const QString &helpText=QString(), bool usesGeometry=false, const QSet< QString > &referencedColumns=QSet< QString >(), bool lazyEval=false, const QStringList &aliases=QStringList(), bool handlesNull=false)
Static function for evaluation against a QgsExpressionContext, using an unnamed list of parameter val...
QSet< QString > referencedColumns(const QgsExpressionNodeFunction *node) const override
Returns a set of field names which are required for this function.
bool usesGeometry(const QgsExpressionNodeFunction *node) const override
Does this function use a geometry object.
Utility functions for working with strings.
static int hammingDistance(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the Hamming distance between two strings.
static QString soundex(const QString &string)
Returns the Soundex representation of a string.
static int levenshteinDistance(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the Levenshtein edit distance between two strings.
static QString longestCommonSubstring(const QString &string1, const QString &string2, bool caseSensitive=false)
Returns the longest common substring between two strings.
static QString wordWrap(const QString &string, int length, bool useMaxLineLength=true, const QString &customDelimiter=QString())
Automatically wraps a string by inserting new line characters at appropriate locations in the string.
const QgsColorRamp * colorRampRef(const QString &name) const
Returns a const pointer to a symbol (doesn't create new instance)
static QgsStyle * defaultStyle()
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(QgsUnitTypes::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.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
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.
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.
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(GeometryType type)
Returns a display string for a geometry type.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Unique pointer for sqlite3 databases, which automatically closes the database when the pointer goes o...
sqlite3_statement_unique_ptr prepare(const QString &sql, int &resultCode) const
Prepares a sql statement, returning the result.
QString errorMessage() const
Returns the most recent error message encountered by the database.
int open_v2(const QString &path, int flags, const char *zVfs)
Opens the database at the specified file path.
int exec(const QString &sql, QString &errorMessage) const
Executes the sql command in the database.
Unique pointer for sqlite3 prepared statements, which automatically finalizes the statement when the ...
int step()
Steps to the next record in the statement, returning the sqlite3 result code.
qlonglong columnAsInt64(int column) const
Gets column value from the current statement row as a long long integer (64 bits).
@ PointCloudLayer
Point cloud layer. Added in QGIS 3.18.
@ MeshLayer
Mesh layer. Added in QGIS 3.2.
@ VectorLayer
Vector layer.
@ RasterLayer
Raster layer.
@ GroupLayer
Composite group layer. Added in QGIS 3.24.
@ VectorTileLayer
Vector tile layer. Added in QGIS 3.14.
@ AnnotationLayer
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ PluginLayer
Plugin based layer.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
CORE_EXPORT QString build(const QVariantMap &map)
Build a hstore-formatted string from a QVariantMap.
CORE_EXPORT QVariantMap parse(const QString &string)
Returns a QVariantMap object containing the key and values from a hstore-formatted string.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
uint qHash(const QVariant &variant)
Hash for QVariant.
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QVector< QgsRingSequence > QgsCoordinateSequence
QVector< QgsPointSequence > QgsRingSequence
QVector< QgsPoint > QgsPointSequence
QList< QgsGradientStop > QgsGradientStopsList
List of gradient stops.
Q_DECLARE_METATYPE(QgsDatabaseQueryLogEntry)
Q_GLOBAL_STATIC(QReadWriteLock, sDefinitionCacheLock)
QList< QgsExpressionFunction * > ExpressionFunctionList
#define ENSURE_GEOM_TYPE(f, g, geomtype)
QVariant fcnRampColor(const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction *)
bool(QgsGeometry::* RelationFunction)(const QgsGeometry &geometry) const
#define ENSURE_NO_EVAL_ERROR
#define FEAT_FROM_CONTEXT(c, f)
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
QVector< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
QLineF segment(int index, QRectF rect, double radius)
A bundle of parameters controlling aggregate calculation.
QString filter
Optional filter for calculating aggregate over a subset of features, or an empty string to use all fe...
QString delimiter
Delimiter to use for joining values with the StringConcatenate aggregate.
QgsFeatureRequest::OrderBy orderBy
Optional order by clauses.
Single variable definition for use within a QgsExpressionContextScope.
The Context struct stores the current layer and coordinate transform context.
const QgsMapLayer * layer
QgsCoordinateTransformContext transformContext
Utility class for identifying a unique vertex within a geometry.