mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-04 00:06:46 -05:00
[expressions][feature] Add bearing function
This commit is contained in:
parent
44e9942e22
commit
b98c758539
27
resources/function_help/json/bearing
Normal file
27
resources/function_help/json/bearing
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "bearing",
|
||||
"type": "function",
|
||||
"groups": ["GeometryGroup"],
|
||||
"description": "Returns the north-based bearing as the angle in radians measured clockwise on the ellipsoid from the vertical on point_a to point_b.",
|
||||
"arguments": [{
|
||||
"arg": "point_a",
|
||||
"description": "point geometry"
|
||||
}, {
|
||||
"arg": "point_b",
|
||||
"description": "point geometry"
|
||||
}, {
|
||||
"arg": "source_auth_id",
|
||||
"description": "the source auth CRS ID of the points"
|
||||
}, {
|
||||
"arg": "ellipsoid",
|
||||
"description": "the acronym or the auth ID of the ellipsoid"
|
||||
}],
|
||||
"examples": [{
|
||||
"expression": "degrees( bearing( make_point(16198544, -4534850), make_point(18736872, -1877769), 'EPSG:3857', 'EPSG:7030') )",
|
||||
"returns": "49.980071"
|
||||
}, {
|
||||
"expression": "degrees( bearing( make_point(18736872, -1877769), make_point(16198544, -4534850), 'EPSG:3857', 'EPSG:7030') )",
|
||||
"returns": "219.282386"
|
||||
}],
|
||||
"tags": ["measured", "clockwise", "points", "angle", "vertical", "north", "azimuth", "bearing", "radians"]
|
||||
}
|
||||
@ -5387,6 +5387,76 @@ static QVariant fcnAzimuth( const QVariantList &values, const QgsExpressionConte
|
||||
}
|
||||
}
|
||||
|
||||
static QVariant fcnBearing( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
const QgsGeometry geom1 = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
|
||||
const QgsGeometry geom2 = QgsExpressionUtils::getGeometry( values.at( 1 ), parent );
|
||||
const QString sAuthId = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
|
||||
const QString ellipsoid = QgsExpressionUtils::getStringValue( values.at( 3 ), parent );
|
||||
|
||||
if ( geom1.isNull() || geom2.isNull() || geom1.type() != Qgis::GeometryType::Point || geom2.type() != Qgis::GeometryType::Point )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Function `bearing` requires two valid point geometries." ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QgsPointXY point1 = geom1.asPoint();
|
||||
if ( geom1.isMultipart() )
|
||||
{
|
||||
QgsMultiPointXY multiPoint = geom1.asMultiPoint();
|
||||
if ( multiPoint.count() == 1 )
|
||||
{
|
||||
point1 = multiPoint[0];
|
||||
}
|
||||
}
|
||||
QgsPointXY point2 = geom2.asPoint();
|
||||
if ( geom2.isMultipart() )
|
||||
{
|
||||
QgsMultiPointXY multiPoint = geom2.asMultiPoint();
|
||||
if ( multiPoint.count() == 1 )
|
||||
{
|
||||
point2 = multiPoint[0];
|
||||
}
|
||||
}
|
||||
if ( point1.isEmpty() || point2.isEmpty() )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Function `bearing` requires point geometries or multi point geometries with a single part." ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const QgsCoordinateReferenceSystem sCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( sAuthId );
|
||||
if ( !sCrs.isValid() )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Function `bearing` requires a valid source auth CRS ID." ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QgsCoordinateTransformContext tContext;
|
||||
if ( context )
|
||||
{
|
||||
tContext = context->variable( QStringLiteral( "_project_transform_context" ) ).value<QgsCoordinateTransformContext>();
|
||||
}
|
||||
|
||||
QgsDistanceArea da;
|
||||
da.setSourceCrs( sCrs, tContext );
|
||||
if ( !da.setEllipsoid( ellipsoid ) )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Function `bearing` requires a valid ellipsoid acronym or ellipsoid auth ID." ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
const double bearing = std::fmod( da.bearing( point1, point2 ) + 2 * M_PI, 2 * M_PI );
|
||||
return bearing;
|
||||
}
|
||||
catch ( QgsCsException &cse )
|
||||
{
|
||||
QgsMessageLog::logMessage( QObject::tr( "Error caught in bearing() function: %1" ).arg( cse.what() ) );
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
static QVariant fcnProject( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
|
||||
@ -8029,6 +8099,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "radians" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "degrees" ) ), fcnRadians, QStringLiteral( "Math" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "degrees" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "radians" ) ), fcnDegrees, QStringLiteral( "Math" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "azimuth" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "point_a" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "point_b" ) ), fcnAzimuth, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "bearing" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "point_a" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "point_b" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "source_auth_id" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "ellipsoid" ) ), fcnBearing, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "inclination" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "point_a" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "point_b" ) ), fcnInclination, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "project" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "point" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "distance" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "azimuth" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "elevation" ), true, M_PI_2 ), fcnProject, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "abs" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "value" ) ), fcnAbs, QStringLiteral( "Math" ) )
|
||||
|
||||
@ -1395,6 +1395,10 @@ class TestQgsExpression: public QObject
|
||||
QTest::newRow( "relate pattern false" ) << "relate( geom_from_wkt( 'LINESTRING(40 40,120 120)' ), geom_from_wkt( 'LINESTRING(40 40,60 120)' ), '**1F002**' )" << false << QVariant( false );
|
||||
QTest::newRow( "azimuth" ) << "toint(degrees(azimuth( point_a := make_point(25, 45), point_b := make_point(75, 100)))*1000000)" << false << QVariant( 42273689 );
|
||||
QTest::newRow( "azimuth" ) << "toint(degrees( azimuth( make_point(75, 100), make_point(25,45) ) )*1000000)" << false << QVariant( 222273689 );
|
||||
QTest::newRow( "bearing 1" ) << "to_int(bearing( make_point(16198544, -4534850), make_point(18736872, -1877769), 'EPSG:3857', 'EPSG:7030')*1000000)" << false << QVariant( 872317 );
|
||||
QTest::newRow( "bearing 2" ) << "to_int(bearing( make_point(-2074453, 9559553), make_point(-55665, 6828252), 'EPSG:3857', 'EPSG:7030')*1000000)" << false << QVariant( 2356910 );
|
||||
QTest::newRow( "bearing 3" ) << "to_int(degrees( bearing( make_point(16198544, -4534850), make_point(18736872, -1877769), 'EPSG:3857', 'EPSG:7030'))*1000000)" << false << QVariant( 49980071 );
|
||||
QTest::newRow( "bearing 4" ) << "to_int(degrees( bearing( make_point(18736872, -1877769), make_point(16198544, -4534850), 'EPSG:3857', 'EPSG:7030'))*1000000)" << false << QVariant( 219282386 );
|
||||
QTest::newRow( "project not geom" ) << "project( 'asd', 1, 2 )" << true << QVariant();
|
||||
QTest::newRow( "project not point" ) << "project( geom_from_wkt('LINESTRING(2 0,2 2, 3 2, 3 0)'), 1, 2 )" << true << QVariant();
|
||||
QTest::newRow( "project x" ) << "toint(x(project( make_point( 1, 2 ), 3, radians(270)))*1000000)" << false << QVariant( -2 * 1000000 );
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user