Skip to content

Commit b7170b8

Browse files
committedJan 13, 2016
Add azimuth function
1 parent f8de083 commit b7170b8

File tree

3 files changed

+87
-0
lines changed

3 files changed

+87
-0
lines changed
 

‎resources/function_help/json/azimuth

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "azimuth",
3+
"type": "function",
4+
"description": "Returns the north-based azimuth as the angle in radians measured clockwise from the vertical on pointA to pointB.",
5+
"arguments": [
6+
{"arg":"pointA","description":"point geometry"},
7+
{"arg":"pointB","description":"point geometry"}
8+
],
9+
"examples": [
10+
{ "expression":"degrees( azimuth( make_point(25, 45), make_point(75, 100) ) )", "returns":"42.273689"},
11+
{ "expression":"degrees( azimuth( make_point(75, 100), make_point(25,45) ) )", "returns":"222.273689"}
12+
]
13+
}

‎src/core/qgsexpression.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2082,6 +2082,77 @@ static QVariant fcnGeomToWKT( const QVariantList& values, const QgsExpressionCon
20822082
return QVariant( wkt );
20832083
}
20842084

2085+
static QVariant fcnAzimuth( const QVariantList& values, const QgsExpressionContext *, QgsExpression* parent )
2086+
{
2087+
if ( values.length() != 2 )
2088+
{
2089+
parent->setEvalErrorString( QObject::tr( "Function `azimuth` requires exactly two parameters. %1 given." ).arg( values.length() ) );
2090+
return QVariant();
2091+
}
2092+
2093+
QgsGeometry fGeom1 = getGeometry( values.at( 0 ), parent );
2094+
QgsGeometry fGeom2 = getGeometry( values.at( 1 ), parent );
2095+
2096+
const QgsPointV2* pt1 = dynamic_cast<const QgsPointV2*>( fGeom1.geometry() );
2097+
const QgsPointV2* pt2 = dynamic_cast<const QgsPointV2*>( fGeom2.geometry() );
2098+
2099+
if ( !pt1 || !pt2 )
2100+
{
2101+
parent->setEvalErrorString( QObject::tr( "Function `azimuth` requires two points as arguments." ) );
2102+
return QVariant();
2103+
}
2104+
2105+
// Code from postgis
2106+
if ( pt1->x() == pt2->x() )
2107+
{
2108+
if ( pt1->y() < pt2->y() )
2109+
return 0.0;
2110+
else if ( pt1->y() > pt2->y() )
2111+
return M_PI;
2112+
else return 0;
2113+
return 1;
2114+
}
2115+
2116+
if ( pt1->y() == pt2->y() )
2117+
{
2118+
if ( pt1->x() < pt2->x() )
2119+
return M_PI / 2;
2120+
else if ( pt1->x() > pt2->x() )
2121+
return M_PI + ( M_PI / 2 );
2122+
else return 0;
2123+
return 1;
2124+
}
2125+
2126+
if ( pt1->x() < pt2->x() )
2127+
{
2128+
if ( pt1->y() < pt2->y() )
2129+
{
2130+
return atan( fabs( pt1->x() - pt2->x() ) / fabs( pt1->y() - pt2->y() ) );
2131+
}
2132+
else /* ( pt1->y() > pt2->y() ) - equality case handled above */
2133+
{
2134+
return atan( fabs( pt1->y() - pt2->y() ) / fabs( pt1->x() - pt2->x() ) )
2135+
+ ( M_PI / 2 );
2136+
}
2137+
}
2138+
2139+
else /* ( pt1->x() > pt2->x() ) - equality case handled above */
2140+
{
2141+
if ( pt1->y() > pt2->y() )
2142+
{
2143+
return atan( fabs( pt1->x() - pt2->x() ) / fabs( pt1->y() - pt2->y() ) )
2144+
+ M_PI;
2145+
}
2146+
else /* ( pt1->y() < pt2->y() ) - equality case handled above */
2147+
{
2148+
return atan( fabs( pt1->y() - pt2->y() ) / fabs( pt1->x() - pt2->x() ) )
2149+
+ ( M_PI + ( M_PI / 2 ) );
2150+
}
2151+
}
2152+
2153+
return QVariant();
2154+
}
2155+
20852156
static QVariant fcnRound( const QVariantList& values, const QgsExpressionContext *, QgsExpression* parent )
20862157
{
20872158
if ( values.length() == 2 )
@@ -2700,6 +2771,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
27002771
<< new StaticFunction( "sqrt", 1, fcnSqrt, "Math" )
27012772
<< new StaticFunction( "radians", 1, fcnRadians, "Math" )
27022773
<< new StaticFunction( "degrees", 1, fcnDegrees, "Math" )
2774+
<< new StaticFunction( "azimuth", 2, fcnAzimuth, "Math" )
27032775
<< new StaticFunction( "abs", 1, fcnAbs, "Math" )
27042776
<< new StaticFunction( "cos", 1, fcnCos, "Math" )
27052777
<< new StaticFunction( "sin", 1, fcnSin, "Math" )

‎tests/src/core/testqgsexpression.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,8 @@ class TestQgsExpression: public QObject
581581
QTest::newRow( "relate bad 2" ) << "relate(geom_from_wkt('POINT(110 120)'),geom_from_wkt(''))" << false << QVariant();
582582
QTest::newRow( "relate pattern true" ) << "relate( geom_from_wkt( 'LINESTRING(40 40,120 120)' ), geom_from_wkt( 'LINESTRING(40 40,60 120)' ), '**1F001**' )" << false << QVariant( true );
583583
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 );
584+
QTest::newRow( "azimuth" ) << "toint(degrees(azimuth( make_point(25, 45), make_point(75, 100)))*1000000)" << false << QVariant( 42273689 );
585+
QTest::newRow( "azimuth" ) << "toint(degrees( azimuth( make_point(75, 100), make_point(25,45) ) )*1000000)" << false << QVariant( 222273689 );
584586

585587
// string functions
586588
QTest::newRow( "lower" ) << "lower('HeLLo')" << false << QVariant( "hello" );

0 commit comments

Comments
 (0)
Please sign in to comment.