Skip to content

Commit

Permalink
[Expression] radians and degrees
Browse files Browse the repository at this point in the history
  • Loading branch information
m-kuhn committed Dec 9, 2015
1 parent 9d67849 commit 28cabbe
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 16 deletions.
10 changes: 10 additions & 0 deletions resources/function_help/json/degrees
@@ -0,0 +1,10 @@
{
"name": "degrees",
"type": "function",
"description": "Converts from radians to degrees.",
"arguments": [ {"arg":"radians","description":"numeric value"}],
"examples": [
{ "expression":"degrees(3.14159)", "returns":"180"},
{ "expression":"degrees(1)", "returns":"57.2958"}
]
}
10 changes: 10 additions & 0 deletions resources/function_help/json/radians
@@ -0,0 +1,10 @@
{
"name": "radians",
"type": "function",
"description": "Converts from degrees to radians.",
"arguments": [ {"arg":"degrees","description":"numeric value"}],
"examples": [
{ "expression":"radians(180)", "returns":"3.14159"},
{ "expression":"radians(57.2958)", "returns":"1"}
]
}
12 changes: 12 additions & 0 deletions src/core/qgsexpression.cpp
Expand Up @@ -431,6 +431,16 @@ static QVariant fcnAbs( const QVariantList& values, const QgsExpressionContext*,
return QVariant( fabs( val ) );
}

static QVariant fcnRadians( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
double deg = getDoubleValue( values.at( 0 ), parent );
return ( deg * M_PI ) / 180;
}
static QVariant fcnDegrees( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
double rad = getDoubleValue( values.at( 0 ), parent );
return ( 180 * rad ) / M_PI;
}
static QVariant fcnSin( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
double x = getDoubleValue( values.at( 0 ), parent );
Expand Down Expand Up @@ -2418,6 +2428,8 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
{
gmFunctions
<< new StaticFunction( "sqrt", 1, fcnSqrt, "Math" )
<< new StaticFunction( "radians", 1, fcnRadians, "Math" )
<< new StaticFunction( "degrees", 1, fcnDegrees, "Math" )
<< new StaticFunction( "abs", 1, fcnAbs, "Math" )
<< new StaticFunction( "cos", 1, fcnCos, "Math" )
<< new StaticFunction( "sin", 1, fcnSin, "Math" )
Expand Down
34 changes: 18 additions & 16 deletions tests/src/core/testqgsexpression.cpp
Expand Up @@ -357,6 +357,8 @@ class TestQgsExpression: public QObject
QTest::newRow( "abs(0)" ) << "abs(0)" << false << QVariant( 0. );
QTest::newRow( "abs(-0.1)" ) << "abs(-0.1)" << false << QVariant( 0.1 );
QTest::newRow( "invalid sqrt value" ) << "sqrt('a')" << true << QVariant();
QTest::newRow( "degrees to radians" ) << "toint(radians(45)*1000000)" << false << QVariant( 785398 ); // sorry for the nasty hack to work around floating point comparison problems
QTest::newRow( "radians to degrees" ) << "toint(degrees(2)*1000)" << false << QVariant( 114592 );
QTest::newRow( "sin 0" ) << "sin(0)" << false << QVariant( 0. );
QTest::newRow( "cos 0" ) << "cos(0)" << false << QVariant( 1. );
QTest::newRow( "tan 0" ) << "tan(0)" << false << QVariant( 0. );
Expand Down Expand Up @@ -648,55 +650,55 @@ class TestQgsExpression: public QObject
QTest::newRow( "geometry to bool true" ) << QString( "case when geom_from_wkt('Point(3 4)') then true else false end" ) << false << QVariant( true );
}

void run_evaluation_test( QgsExpression& exp, bool evalError, QVariant& result )
void run_evaluation_test( QgsExpression& exp, bool evalError, QVariant& expected )
{
QCOMPARE( exp.hasParserError(), false );
if ( exp.hasParserError() )
qDebug() << exp.parserErrorString();

QVariant res = exp.evaluate();
QVariant result = exp.evaluate();
if ( exp.hasEvalError() )
qDebug() << exp.evalErrorString();
if ( res.type() != result.type() )
if ( result.type() != expected.type() )
{
qDebug() << "got " << res.typeName() << " instead of " << result.typeName();
qDebug() << "got " << result.typeName() << " instead of " << expected.typeName();
}
//qDebug() << res.type() << " " << result.type();
//qDebug() << "type " << res.typeName();
QCOMPARE( exp.hasEvalError(), evalError );

QCOMPARE( res.type(), result.type() );
switch ( res.type() )
QCOMPARE( result.type(), expected.type() );
switch ( result.type() )
{
case QVariant::Invalid:
break; // nothing more to check
case QVariant::Int:
QCOMPARE( res.toInt(), result.toInt() );
QCOMPARE( result.toInt(), expected.toInt() );
break;
case QVariant::Double:
QCOMPARE( res.toDouble(), result.toDouble() );
QCOMPARE( result.toDouble(), expected.toDouble() );
break;
case QVariant::Bool:
QCOMPARE( res.toBool(), result.toBool() );
QCOMPARE( result.toBool(), expected.toBool() );
break;
case QVariant::String:
QCOMPARE( res.toString(), result.toString() );
QCOMPARE( result.toString(), expected.toString() );
break;
case QVariant::Date:
QCOMPARE( res.toDate(), result.toDate() );
QCOMPARE( result.toDate(), expected.toDate() );
break;
case QVariant::DateTime:
QCOMPARE( res.toDateTime(), result.toDateTime() );
QCOMPARE( result.toDateTime(), expected.toDateTime() );
break;
case QVariant::Time:
QCOMPARE( res.toTime(), result.toTime() );
QCOMPARE( result.toTime(), expected.toTime() );
break;
case QVariant::UserType:
{
if ( res.userType() == qMetaTypeId<QgsExpression::Interval>() )
if ( result.userType() == qMetaTypeId<QgsExpression::Interval>() )
{
QgsExpression::Interval inter = res.value<QgsExpression::Interval>();
QgsExpression::Interval gotinter = result.value<QgsExpression::Interval>();
QgsExpression::Interval inter = result.value<QgsExpression::Interval>();
QgsExpression::Interval gotinter = expected.value<QgsExpression::Interval>();
QCOMPARE( inter.seconds(), gotinter.seconds() );
}
else
Expand Down

1 comment on commit 28cabbe

@NathanW2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Please sign in to comment.