Commit e252eeac authored by Jasem Mutlaq's avatar Jasem Mutlaq
Browse files

Syncing with master

parents 29f66bff bc118369
......@@ -10,7 +10,7 @@ include_directories(
FIND_PACKAGE(Qt5Test REQUIRED)
SET( TEST_LIBRARIES
SET( TEST_LIBRARIES
Qt5::Core
Qt5::Test
LibKSDataHandlers
......@@ -20,4 +20,4 @@ SET( TEST_LIBRARIES
)
add_subdirectory(auxiliary)
add_subdirectory(skyobjects)
......@@ -11,3 +11,7 @@ ADD_TEST( NAME FixedWidthParserTest COMMAND testfwparser )
ADD_EXECUTABLE( testdms testdms.cpp )
TARGET_LINK_LIBRARIES( testdms ${TEST_LIBRARIES})
ADD_TEST( NAME DMSTest COMMAND testdms )
ADD_EXECUTABLE( testcachingdms testcachingdms.cpp )
TARGET_LINK_LIBRARIES( testcachingdms ${TEST_LIBRARIES})
ADD_TEST( NAME TestCachingDms COMMAND testcachingdms )
/***************************************************************************
testcachingdms.cpp -
-------------------
begin : Sun 25 Sep 2016 03:56:05 CDT
copyright : (c) 2016 by Akarsh Simha
email : akarsh.simha@kdemail.net
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
/* Project Includes */
#include "testcachingdms.h"
#include "nan.h"
/* KDE Includes */
/* Qt Includes */
/* STL Includes */
#include <ctime>
#include <cstdlib>
#include <cstdint>
TestCachingDms::TestCachingDms(): QObject()
{
}
TestCachingDms::~TestCachingDms()
{
}
void TestCachingDms::defaultCtor()
{
/*
* Test 1: Check Default Constructor
*/
// Check default empty constructor
CachingDms d;
QVERIFY(std::isnan(d.Degrees()));
QVERIFY( std::isnan( d.sin() ) );
QVERIFY( std::isnan( d.cos() ) );
}
void TestCachingDms::explicitSexigesimalCtor()
{
/*
* Test 2: Checks Sexigesimal Ctor
*/
// DD:MM:SS
// 14:55:20
CachingDms d(14, 55, 20);
QVERIFY(d.degree() == 14);
QVERIFY(d.arcmin() == 55);
QVERIFY(d.arcsec() == 20);
QVERIFY(d.Degrees() == (14.0+55.0/60.0+20.0/3600.0));
QVERIFY( fabs( d.sin() - .25750758368074941632 ) < 1e-9 );
QVERIFY( fabs( d.cos() - .96627627744186177805 ) < 1e-9 );
}
void TestCachingDms::angleCtor()
{
/*
* Test 3: Checks Angle Ctor
*/
// Angle = -112.56 Degrees ---> HMS (16:29:45)
double angle = -112.56;
CachingDms d(angle);
QVERIFY(d.degree() == (int) angle);
QVERIFY(d.Hours() == (angle+360)/15.0);
QVERIFY(d.hour() == 16);
QVERIFY(d.minute() == 29);
QVERIFY(d.second() == 45);
QVERIFY( fabs( d.sin() + 0.92347828085768229015 ) < 1e-9 );
QVERIFY( fabs( d.cos() + 0.38365070674265630377 ) < 1e-9 );
}
void TestCachingDms::stringCtor()
{
QString hms("14:55:20");
// From Degree
CachingDms d(hms);
QVERIFY(d.degree() == 14);
QVERIFY(d.arcmin() == 55);
QVERIFY(d.arcsec() == 20);
QVERIFY(d.Degrees() == (14.0+55.0/60.0+20.0/3600.0));
QVERIFY( fabs( d.sin() - .25750758368074941632 ) < 1e-9 );
QVERIFY( fabs( d.cos() - .96627627744186177805 ) < 1e-9 );
// From Hours
CachingDms h(hms, false);
QVERIFY(h.Degrees() == d.Degrees()*15.0);
QVERIFY(h.Hours() == d.Degrees());
}
void TestCachingDms::setUsing_asin() {
// Test case in first quadrant: 56.3 degrees
CachingDms d;
d.setUsing_asin( .83195412213048254606 );
QVERIFY( fabs( d.Degrees() - 56.3 ) < 1e-7 );
QVERIFY( fabs( d.cos() - .55484442744799927555 ) < 1e-9 );
// Test case in fourth quadrant: -56.3 degrees
d.setUsing_asin( -.83195412213048254606 );
QVERIFY( fabs( d.Degrees() + 56.3 ) < 1e-7 );
QVERIFY( fabs( d.cos() - .55484442744799927555 ) < 1e-9 );
}
void TestCachingDms::setUsing_acos() {
CachingDms d;
// Test case in first quadrant: 56.3 degrees
d.setUsing_acos( .55484442744799927555 );
QVERIFY( fabs( d.Degrees() - 56.3 ) < 1e-7 );
QVERIFY( fabs( d.sin() - .83195412213048254606 ) < 1e-9 );
// Test case in second quadrant: 123.7 degrees
d.setUsing_acos( -0.55484442744799927555 );
QVERIFY( fabs( d.Degrees() - 123.7 ) < 1e-7 );
QVERIFY( fabs( d.sin() - .83195412213048254606 ) < 1e-9 );
}
void TestCachingDms::setUsing_atan2() {
// Test case in first quadrant: 56.3 degrees
CachingDms d;
d.setUsing_atan2( 2.73701935509448143467, 1.82536500102022632674 );
QVERIFY( fabs( d.Degrees() - 56.3 ) < 1e-7 );
QVERIFY( fabs( d.sin() - .83195412213048254606 ) < 1e-9 );
QVERIFY( fabs( d.cos() - .55484442744799927555 ) < 1e-9 );
// Test case in third quadrant: -123.7 degrees
d.setUsing_atan2( -2.73701935509448143467, -1.82536500102022632674 );
QVERIFY( fabs( d.Degrees() + 123.7 ) < 1e-7 );
QVERIFY( fabs( d.sin() + .83195412213048254606 ) < 1e-9 );
QVERIFY( fabs( d.cos() + .55484442744799927555 ) < 1e-9 );
// Test case in second quadrant: 123.7 degrees
d.setUsing_atan2( 2.73701935509448143467, -1.82536500102022632674 );
QVERIFY( fabs( d.Degrees() - 123.7 ) < 1e-7 );
QVERIFY( fabs( d.sin() - .83195412213048254606 ) < 1e-9 );
QVERIFY( fabs( d.cos() + .55484442744799927555 ) < 1e-9 );
// Test case in fourth quadrant: -56.3 degrees
d.setUsing_atan2( -2.73701935509448143467, +1.82536500102022632674 );
QVERIFY( fabs( d.Degrees() + 56.3 ) < 1e-7 );
QVERIFY( fabs( d.sin() + .83195412213048254606 ) < 1e-9 );
QVERIFY( fabs( d.cos() - .55484442744799927555 ) < 1e-9 );
// Edge case test: angle = 0
d.setUsing_atan2( 0., 1.33 );
QVERIFY( fabs( d.Degrees() - 0. ) < 1e-7 );
QVERIFY( fabs( d.sin() - 0. ) < 1e-9 );
QVERIFY( fabs( d.cos() - 1. ) < 1e-9 );
// Edge case test: angle = 90 degrees
d.setUsing_atan2( 10.12, 0. );
QVERIFY( fabs( d.Degrees() - 90. ) < 1e-7 );
QVERIFY( fabs( d.sin() - 1. ) < 1e-9 );
QVERIFY( fabs( d.cos() - 0. ) < 1e-9 );
// Edge case test: angle = -90 degrees
d.setUsing_atan2( -3.1415, 0. );
QVERIFY( fabs( d.Degrees() + 90. ) < 1e-7 );
QVERIFY( fabs( d.sin() + 1. ) < 1e-9 );
QVERIFY( fabs( d.cos() - 0. ) < 1e-9 );
// Edge case test: angle = 180 degrees
d.setUsing_atan2( 0., -724. );
QVERIFY( fabs( d.Degrees() - 180. ) < 1e-7 );
QVERIFY( fabs( d.sin() - 0. ) < 1e-9 );
QVERIFY( fabs( d.cos() + 1. ) < 1e-9 );
}
void TestCachingDms::unaryMinusOperator() {
CachingDms d( 56.3 );
qDebug() << ( -d ).Degrees();
QVERIFY( ( -d ).Degrees() == -56.3 );
QVERIFY( ( -d ).cos() == d.cos() );
QVERIFY( ( -d ).sin() == -d.sin() );
}
void TestCachingDms::additionOperator() {
const double a = 123.7;
const double b = 89.5;
CachingDms d1( a );
CachingDms d2( b );
CachingDms ds = d1 + d2;
const double sinapb = std::sin( ( a + b ) * dms::DegToRad );
const double cosapb = std::cos( ( a + b ) * dms::DegToRad );
QVERIFY( fabs( ds.sin() - sinapb ) < 1e-9 );
QVERIFY( fabs( ds.cos() - cosapb ) < 1e-9 );
const double c = -34.7;
const double d = 233.6;
CachingDms d3( c );
CachingDms d4( d );
CachingDms ds2 = d3 + d4;
const double sincpd = std::sin( ( c + d ) * dms::DegToRad );
const double coscpd = std::cos( ( c + d ) * dms::DegToRad );
QVERIFY( fabs( ds2.sin() - sincpd ) < 1e-9 );
QVERIFY( fabs( ds2.cos() - coscpd ) < 1e-9 );
}
void TestCachingDms::subtractionOperator() {
const double a = 123.7;
const double b = 89.5;
CachingDms d1( a );
CachingDms d2( b );
CachingDms ds = d1 - d2;
const double sinamb = std::sin( ( a - b ) * dms::DegToRad );
const double cosamb = std::cos( ( a - b ) * dms::DegToRad );
QVERIFY( fabs( ds.sin() - sinamb ) < 1e-9 );
QVERIFY( fabs( ds.cos() - cosamb ) < 1e-9 );
const double c = -34.7;
const double d = 233.6;
CachingDms d3( c );
CachingDms d4( d );
CachingDms ds2 = d3 - d4;
const double sincmd = std::sin( ( c - d ) * dms::DegToRad );
const double coscmd = std::cos( ( c - d ) * dms::DegToRad );
QVERIFY( fabs( ds2.sin() - sincmd ) < 1e-9 );
QVERIFY( fabs( ds2.cos() - coscmd ) < 1e-9 );
}
void TestCachingDms::testFailsafeUseOfBaseClassPtr() {
typedef union angle { double x; int64_t y; } angle;
const int testCases = 5000;
std::srand( std::time( 0 ) );
for ( int k = 0; k < testCases; ++k ) {
angle a; CachingDms _a; dms __a;
a.y = std::rand();
_a.setD( a.x );
__a.setD( a.x );
dms *d;
if ( rand()%10 > 5 )
d = &_a;
else
d = &__a;
angle b;
b.y = std::rand();
switch( rand()%7 ) {
case 0:
d->setD( b.x );
break;
case 1:
d->setH( b.x / 15. );
break;
case 2: {
dms x( b.x );
d->setD( x.degree(), x.arcmin(), x.arcsec(), x.marcsec() );
break;
}
case 3: {
dms x( b.x );
d->setFromString( x.toDMSString() );
break;
}
case 4: {
dms x( b.x );
d->setFromString( x.toHMSString(), false );
break;
}
case 5: {
dms x( b.x );
dms y( 0.0 );
*d = x + y;
}
case 6:
default:
d->setRadians( b.x * dms::DegToRad );
break;
}
QVERIFY( fabs( d->sin() - sin( b.x * dms::DegToRad ) ) < 1e-12 );
QVERIFY( fabs( d->cos() - cos( b.x * dms::DegToRad ) ) < 1e-12 );
}
}
QTEST_GUILESS_MAIN(TestCachingDms)
/***************************************************************************
testcachingdms.h -
-------------------
begin : Sun 25 Sep 2016 03:56:35 CDT
copyright : (c) 2016 by Akarsh Simha
email : akarsh.simha@kdemail.net
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef TESTCACHINGDMS_H
#define TESTCACHINGDMS_H
#include <QtTest/QtTest>
#include <QDebug>
#include "auxiliary/cachingdms.h"
/**
* @class TestCachingDms
* @short Tests for CachingDms
* @author Akarsh Simha <akarsh.simha@kdemail.net>
*/
class TestCachingDms : public QObject {
Q_OBJECT
public:
/**
* @short Constructor
*/
TestCachingDms();
/**
* @short Destructor
*/
~TestCachingDms();
private slots:
void defaultCtor();
void explicitSexigesimalCtor();
void angleCtor();
void stringCtor();
void setUsing_atan2();
void setUsing_asin();
void setUsing_acos();
void additionOperator();
void subtractionOperator();
void unaryMinusOperator();
void testFailsafeUseOfBaseClassPtr();
};
#endif
......@@ -85,6 +85,46 @@ void TestDMS::stringCtor()
QVERIFY(h.Hours() == d.Degrees());
}
QTEST_GUILESS_MAIN(TestDMS)
void TestDMS::testReduceToRange() {
double base = 67.8;
double a = 360.0 * 11. + base;
double b = -360.0 * 12. + base;
dms d;
d.setD( a );
d.reduceToRange( dms::ZERO_TO_2PI );
QVERIFY( fabs( d.Degrees() - base ) < 1e-9 );
d.setD( b );
d.reduceToRange( dms::ZERO_TO_2PI );
QVERIFY( fabs( d.Degrees() - base ) < 1e-9 );
d.setD( 360.0 );
d.reduceToRange( dms::ZERO_TO_2PI );
QVERIFY( fabs( d.Degrees() - 0. ) < 1e-9 );
double c = 180.0 * 13. + base;
double e = 180.0 * 14. + base;
double f = -180.0 * 15. + base;
double g = -180.0 * 16. + base;
d.setD( c );
d.reduceToRange( dms::MINUSPI_TO_PI );
QVERIFY( fabs( d.Degrees() - ( base - 180.0 ) ) < 1e-9 );
d.setD( e );
d.reduceToRange( dms::MINUSPI_TO_PI );
QVERIFY( fabs( d.Degrees() - base ) < 1e-9 );
d.setD( f );
d.reduceToRange( dms::MINUSPI_TO_PI );
QVERIFY( fabs( d.Degrees() - ( base - 180.0 ) ) < 1e-9 );
d.setD( g );
d.reduceToRange( dms::MINUSPI_TO_PI );
QVERIFY( fabs( d.Degrees() - base ) < 1e-9 );
}
QTEST_GUILESS_MAIN(TestDMS)
......@@ -31,6 +31,7 @@ class TestDMS: public QObject
void explicitSexigesimalCtor();
void angleCtor();
void stringCtor();
void testReduceToRange();
};
......
ADD_EXECUTABLE( test_skypoint test_skypoint.cpp )
TARGET_LINK_LIBRARIES( test_skypoint ${TEST_LIBRARIES})
ADD_TEST( NAME TestSkyPoint COMMAND test_skypoint )
/***************************************************************************
test_skypoint.cpp - KStars Planetarium
-------------------
begin : Tue 27 Sep 2016 20:54:28 CDT
copyright : (c) 2016 by Akarsh Simha
email : akarsh.simha@kdemail.net
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
/* Project Includes */
#include "test_skypoint.h"
#include "ksnumbers.h"
#include "time/kstarsdatetime.h"
#include "auxiliary/dms.h"
void TestSkyPoint::testPrecession() {
/*
* NOTE: These test cases were picked randomly and generated using
* https://ned.ipac.caltech.edu/forms/calculator.html
*/
auto verify = []( const SkyPoint &p, const double targetRA, const double targetDec, const double tolerance ) {
qDebug() << p.ra().toHMSString() << " " << p.dec().toDMSString();
QVERIFY( fabs( p.ra().Degrees() - targetRA ) < tolerance * 15. );
QVERIFY( fabs( p.dec().Degrees() - targetDec ) < tolerance );
};
/* Precession of equinoxes within FK5 system */
// Check precession from J2000.0 to J1992.5
// NOTE: (FIXME?) I set 1950.0 as the observation epoch in the
// calculator. Changing it to 1992.5 made no difference; probably
// required only for FK5 to FK4 conversion. The help is not
// extremely clear on this. -- asimha
constexpr double arcsecPrecision = 3.e-4;
long double jd = KStarsDateTime::epochToJd( 1992.5, KStarsDateTime::JULIAN );
KSNumbers num( jd );
SkyPoint p( dms( "18:22:54", false ), dms( "34:23:19", true ) ); // J2000.0 coordinates
p.precess( &num );
verify( p, 275.65734620, 34.38447020, arcsecPrecision );
// Check precession from J2000.0 to J2016.8
jd = KStarsDateTime::epochToJd( 2016.8 );
num.updateValues( jd );
p.set( dms( "23:24:25", false ), dms( "-08:07:06", true ) );
p.precess( &num );
verify( p, 351.32145112, ( -8.02590004 ) , arcsecPrecision );
// Check precession from J2000.0 to J2109.8
jd = KStarsDateTime::epochToJd( 2109.8 );
num.updateValues( jd );
p.precess( &num );
verify( p, 352.52338626, ( -7.51340424 ) , arcsecPrecision );
/* Precession of equinoxes + conversion from FK4 to FK5 */
// Conversion from B1950.0 to J2000.0
p.set( dms( "11:22:33", false ), dms( "44:55:66", true ) ); // Sets all of RA0,Dec0,RA,Dec
p.B1950ToJ2000(); // Assumes (RA, Dec) are referenced to FK4 @ B1950 and stores the FK5 @ J2000 result in (RA, Dec)
verify( p, 171.32145647, 44.66010982, arcsecPrecision );
// Conversion from B1950.0 to J2016.8
// Current of B1950ToJ2000 is to NOT alter (RA0,Dec0), so we shouldn't have to reset it
jd = KStarsDateTime::epochToJd( 2016.8 );
p.precessFromAnyEpoch( B1950, jd ); // Takes (RA0, Dec0) and precesses to (RA, Dec) applying FK4 <--> FK5 conversions as necessary
verify( p, 171.55045618, 44.56762158, arcsecPrecision );
/* Precession of equinoxes + conversion from FK5 to FK4 */
p.set( dms( "11:22:33", false ), dms( "44:55:66", true ) ); // Sets all of RA0,Dec0,RA,Dec
p.J2000ToB1950(); // Assumes (RA, Dec) are referenced to FK5 @ J2000 and stores the FK4 @ B1950 result in (RA, Dec)
// NOTE: I set observation epoch = 2000.0 in NED's calculator. This time, it made a difference whether I set 2000.0 or 1950.0, but the difference was very small.
verify( p,169.94978888, 45.20928652, arcsecPrecision );
// Conversion from J2016.8 to B1950.0
// Current behavior of J2000ToB1950 is to NOT alter (RA0,Dec0), so we shouldn't have to reset it
jd = KStarsDateTime::epochToJd( 2016.8 );
p.precessFromAnyEpoch( jd, B1950 ); // Takes (RA0, Dec0) and precesses to (RA, Dec) applying FK4 <--> FK5 conversions as necessary
// NOTE: I set observation epoch = 2016.8 in NED's calculator. It made a difference whether I set 2000.0 or 2016.8, but the difference was very small.
verify( p, 169.71785991, 45.30132855, arcsecPrecision );
}
QTEST_GUILESS_MAIN( TestSkyPoint )
/***************************************************************************
test_skypoint.h - KStars Planetarium
-------------------
begin : Tue 27 Sep 2016 20:51:21 CDT
copyright : (c) 2016 by Akarsh Simha
email : akarsh.simha@kdemail.net
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef TEST_SKYPOINT_H
#define TEST_SKYPOINT_H
#include <QtTest/QtTest>
#include <QDebug>
#define UNIT_TEST
#include "skyobjects/skypoint.h"
/**
* @class TestSkyPoint
* @short Tests for some SkyPoint operations
* @author Akarsh Simha <akarsh.simha@kdemail.net>
*/
class TestSkyPoint : public QObject {
Q_OBJECT
public:
TestSkyPoint() : QObject() {};
~TestSkyPoint() {};
private slots:
void testPrecession();
};