Convert to unix files

feature/19
Daniel Warner 2011-12-16 23:38:28 +00:00
parent 12297b37a1
commit 3926116d8e
16 changed files with 1984 additions and 1984 deletions

View File

@ -1,112 +1,112 @@
#ifndef COORDGEODETIC_H_
#define COORDGEODETIC_H_
#include "Globals.h"
#include <string>
#include <sstream>
#include <iomanip>
struct CoordGeodetic
{
public:
CoordGeodetic()
: latitude(0.0), longitude(0.0), altitude(0.0)
{
}
/*
* default is in degrees
*/
CoordGeodetic(double lat, double lon, double alt, bool radians = false)
{
if (radians)
{
latitude = lat;
longitude = lon;
}
else
{
latitude = DegreesToRadians(lat);
longitude = DegreesToRadians(lon);
}
altitude = alt;
}
CoordGeodetic(const CoordGeodetic& g)
{
latitude = g.latitude;
longitude = g.longitude;
altitude = g.altitude;
}
virtual ~CoordGeodetic()
{
}
CoordGeodetic& operator=(const CoordGeodetic& g)
{
if (this != &g)
{
latitude = g.latitude;
longitude = g.longitude;
altitude = g.altitude;
}
return *this;
}
bool operator==(const CoordGeodetic& g) const
{
return IsEqual(g);
}
bool operator!=(const CoordGeodetic& g) const
{
return !IsEqual(g);
}
std::string ToString() const
{
std::stringstream ss;
ss << std::right << std::fixed << std::setprecision(2);
ss << "Lat: " << std::setw(7) << RadiansToDegrees(latitude);
ss << ", Lon: " << std::setw(7) << RadiansToDegrees(longitude);
ss << ", Alt: " << std::setw(9) << altitude;
return ss.str();
}
/*
* radians (north positive, south negative)
*/
double latitude;
/*
* radians (east positive, west negative)
*/
double longitude;
/*
* kilometers
*/
double altitude;
protected:
bool IsEqual(const CoordGeodetic& g) const
{
if (latitude == g.latitude && longitude == g.longitude &&
altitude == g.altitude)
{
return false;
}
else
{
return true;
}
}
};
inline std::ostream& operator<<(std::ostream& strm, const CoordGeodetic& g)
{
return strm << g.ToString();
}
#endif
#ifndef COORDGEODETIC_H_
#define COORDGEODETIC_H_
#include "Globals.h"
#include <string>
#include <sstream>
#include <iomanip>
struct CoordGeodetic
{
public:
CoordGeodetic()
: latitude(0.0), longitude(0.0), altitude(0.0)
{
}
/*
* default is in degrees
*/
CoordGeodetic(double lat, double lon, double alt, bool radians = false)
{
if (radians)
{
latitude = lat;
longitude = lon;
}
else
{
latitude = DegreesToRadians(lat);
longitude = DegreesToRadians(lon);
}
altitude = alt;
}
CoordGeodetic(const CoordGeodetic& g)
{
latitude = g.latitude;
longitude = g.longitude;
altitude = g.altitude;
}
virtual ~CoordGeodetic()
{
}
CoordGeodetic& operator=(const CoordGeodetic& g)
{
if (this != &g)
{
latitude = g.latitude;
longitude = g.longitude;
altitude = g.altitude;
}
return *this;
}
bool operator==(const CoordGeodetic& g) const
{
return IsEqual(g);
}
bool operator!=(const CoordGeodetic& g) const
{
return !IsEqual(g);
}
std::string ToString() const
{
std::stringstream ss;
ss << std::right << std::fixed << std::setprecision(2);
ss << "Lat: " << std::setw(7) << RadiansToDegrees(latitude);
ss << ", Lon: " << std::setw(7) << RadiansToDegrees(longitude);
ss << ", Alt: " << std::setw(9) << altitude;
return ss.str();
}
/*
* radians (north positive, south negative)
*/
double latitude;
/*
* radians (east positive, west negative)
*/
double longitude;
/*
* kilometers
*/
double altitude;
protected:
bool IsEqual(const CoordGeodetic& g) const
{
if (latitude == g.latitude && longitude == g.longitude &&
altitude == g.altitude)
{
return false;
}
else
{
return true;
}
}
};
inline std::ostream& operator<<(std::ostream& strm, const CoordGeodetic& g)
{
return strm << g.ToString();
}
#endif

View File

@ -1,106 +1,106 @@
#ifndef COORDTOPOGRAPHIC_H_
#define COORDTOPOGRAPHIC_H_
#include "Globals.h"
#include <iostream>
#include <sstream>
#include <iomanip>
struct CoordTopographic
{
public:
CoordTopographic()
: azimuth(0.0), elevation(0.0), range(0.0), range_rate(0.0)
{
}
CoordTopographic(double az, double el, double rnge, double rnge_rate)
: azimuth(az), elevation(el), range(rnge), range_rate(rnge_rate)
{
}
CoordTopographic(const CoordTopographic& t)
{
azimuth = t.azimuth;
elevation = t.elevation;
range = t.range;
range_rate = t.range_rate;
}
virtual ~CoordTopographic()
{
};
CoordTopographic& operator=(const CoordTopographic& t)
{
if (this != &t) {
azimuth = t.azimuth;
elevation = t.elevation;
range = t.range;
range_rate = t.range_rate;
}
return *this;
}
bool operator==(const CoordTopographic& t) const
{
return IsEqual(t);
}
bool operator !=(const CoordTopographic& t) const
{
return !IsEqual(t);
}
std::string ToString() const
{
std::stringstream ss;
ss << std::right << std::fixed << std::setprecision(2);
ss << "Az: " << std::setw(7) << RadiansToDegrees(azimuth);
ss << ", El: " << std::setw(7) << RadiansToDegrees(elevation);
ss << ", Rng: " << std::setw(9) << range;
ss << ", Rng Rt: " << std::setw(6) << range_rate;
return ss.str();
}
/*
* radians
*/
double azimuth;
/*
* radians
*/
double elevation;
/*
* kilometers
*/
double range;
/*
* kilometers / second
*/
double range_rate;
protected:
bool IsEqual(const CoordTopographic& t) const
{
if (azimuth == t.azimuth && elevation == t.elevation &&
range == t.range && range_rate == t.range_rate)
{
return true;
}
else
{
return false;
}
}
};
inline std::ostream& operator<<(std::ostream& strm, const CoordTopographic& t)
{
return strm << t.ToString();
}
#endif
#ifndef COORDTOPOGRAPHIC_H_
#define COORDTOPOGRAPHIC_H_
#include "Globals.h"
#include <iostream>
#include <sstream>
#include <iomanip>
struct CoordTopographic
{
public:
CoordTopographic()
: azimuth(0.0), elevation(0.0), range(0.0), range_rate(0.0)
{
}
CoordTopographic(double az, double el, double rnge, double rnge_rate)
: azimuth(az), elevation(el), range(rnge), range_rate(rnge_rate)
{
}
CoordTopographic(const CoordTopographic& t)
{
azimuth = t.azimuth;
elevation = t.elevation;
range = t.range;
range_rate = t.range_rate;
}
virtual ~CoordTopographic()
{
};
CoordTopographic& operator=(const CoordTopographic& t)
{
if (this != &t) {
azimuth = t.azimuth;
elevation = t.elevation;
range = t.range;
range_rate = t.range_rate;
}
return *this;
}
bool operator==(const CoordTopographic& t) const
{
return IsEqual(t);
}
bool operator !=(const CoordTopographic& t) const
{
return !IsEqual(t);
}
std::string ToString() const
{
std::stringstream ss;
ss << std::right << std::fixed << std::setprecision(2);
ss << "Az: " << std::setw(7) << RadiansToDegrees(azimuth);
ss << ", El: " << std::setw(7) << RadiansToDegrees(elevation);
ss << ", Rng: " << std::setw(9) << range;
ss << ", Rng Rt: " << std::setw(6) << range_rate;
return ss.str();
}
/*
* radians
*/
double azimuth;
/*
* radians
*/
double elevation;
/*
* kilometers
*/
double range;
/*
* kilometers / second
*/
double range_rate;
protected:
bool IsEqual(const CoordTopographic& t) const
{
if (azimuth == t.azimuth && elevation == t.elevation &&
range == t.range && range_rate == t.range_rate)
{
return true;
}
else
{
return false;
}
}
};
inline std::ostream& operator<<(std::ostream& strm, const CoordTopographic& t)
{
return strm << t.ToString();
}
#endif

138
Eci.h
View File

@ -1,69 +1,69 @@
#ifndef ECI_H_
#define ECI_H_
#include "CoordGeodetic.h"
#include "Vector.h"
#include "Julian.h"
#include "Globals.h"
class Eci
{
public:
/*
* in degrees
*/
Eci(const Julian& date, double latitude, double longitude, double altitude)
{
ToEci(date, CoordGeodetic(latitude, longitude, altitude));
}
Eci(const Julian& date, const CoordGeodetic& g)
{
ToEci(date, g);
}
Eci(const Julian &date, const Vector &position)
: date_(date), position_(position)
{
}
Eci(const Julian &date, const Vector &position, const Vector &velocity)
: date_(date), position_(position), velocity_(velocity)
{
}
virtual ~Eci()
{
}
Vector GetPosition() const
{
return position_;
}
Vector GetVelocity() const
{
return velocity_;
}
Julian GetDate() const
{
return date_;
}
CoordGeodetic ToGeodetic() const;
protected:
void ToEci(const Julian& date, double latitude, double longitude,
double altitude);
void ToEci(const Julian& date, const CoordGeodetic& g);
private:
Julian date_;
Vector position_;
Vector velocity_;
};
#endif
#ifndef ECI_H_
#define ECI_H_
#include "CoordGeodetic.h"
#include "Vector.h"
#include "Julian.h"
#include "Globals.h"
class Eci
{
public:
/*
* in degrees
*/
Eci(const Julian& date, double latitude, double longitude, double altitude)
{
ToEci(date, CoordGeodetic(latitude, longitude, altitude));
}
Eci(const Julian& date, const CoordGeodetic& g)
{
ToEci(date, g);
}
Eci(const Julian &date, const Vector &position)
: date_(date), position_(position)
{
}
Eci(const Julian &date, const Vector &position, const Vector &velocity)
: date_(date), position_(position), velocity_(velocity)
{
}
virtual ~Eci()
{
}
Vector GetPosition() const
{
return position_;
}
Vector GetVelocity() const
{
return velocity_;
}
Julian GetDate() const
{
return date_;
}
CoordGeodetic ToGeodetic() const;
protected:
void ToEci(const Julian& date, double latitude, double longitude,
double altitude);
void ToEci(const Julian& date, const CoordGeodetic& g);
private:
Julian date_;
Vector position_;
Vector velocity_;
};
#endif

212
Globals.h
View File

@ -1,106 +1,106 @@
#ifndef GLOBALS_H_
#define GLOBALS_H_
#include <cmath>
#include <string>
const double kAE = 1.0;
const double kQ0 = 120.0;
const double kS0 = 78.0;
const double kMU = 398600.8;
const double kXKMPER = 6378.135;
const double kXJ2 = 1.082616e-3;
const double kXJ3 = -2.53881e-6;
const double kXJ4 = -1.65597e-6;
/*
* alternative XKE
* affects final results
* aiaa-2006-6573
* const double kXKE = 60.0 / sqrt(kXKMPER * kXKMPER * kXKMPER / kMU);
* dundee
* const double kXKE = 7.43669161331734132e-2;
*/
const double kXKE = 60.0 / sqrt(kXKMPER * kXKMPER * kXKMPER / kMU);
const double kCK2 = 0.5 * kXJ2 * kAE * kAE;
const double kCK4 = -0.375 * kXJ4 * kAE * kAE * kAE * kAE;
/*
* alternative QOMS2T
* affects final results
* aiaa-2006-6573
* #define QOMS2T (pow(((Q0 - S0) / XKMPER), 4.0))
* dundee
* #define QOMS2T (1.880279159015270643865e-9)
*/
const double kQOMS2T = pow(((kQ0 - kS0) / kXKMPER), 4.0);
const double kS = kAE * (1.0 + kS0 / kXKMPER);
const double kPI = 3.14159265358979323846264338327950288419716939937510582;
const double kTWOPI = 2.0 * kPI;
const double kTWOTHIRD = 2.0 / 3.0;
const double kTHDT = 4.37526908801129966e-3;
/*
* earth flattening
*/
const double kF = 1.0 / 298.26;
/*
* earth rotation per sideral day
*/
const double kOMEGA_E = 1.00273790934;
const double kAU = 1.49597870691e8;
const double kSECONDS_PER_DAY = 86400.0;
const double kMINUTES_PER_DAY = 1440.0;
const double kHOURS_PER_DAY = 24.0;
// Jan 1.0 1900 = Jan 1 1900 00h UTC
const double kEPOCH_JAN1_00H_1900 = 2415019.5;
// Jan 1.5 1900 = Jan 1 1900 12h UTC
const double kEPOCH_JAN1_12H_1900 = 2415020.0;
// Jan 1.5 2000 = Jan 1 2000 12h UTC
const double kEPOCH_JAN1_12H_2000 = 2451545.0;
inline double Fmod2p(const double arg) {
double modu = fmod(arg, kTWOPI);
if (modu < 0.0)
modu += kTWOPI;
return modu;
}
inline double DegreesToRadians(const double degrees) {
return degrees * kPI / 180.0;
}
inline double RadiansToDegrees(const double radians) {
return radians * 180.0 / kPI;
}
inline double AcTan(const double sinx, const double cosx) {
if (cosx == 0.0) {
if (sinx > 0.0)
return kPI / 2.0;
else
return 3.0 * kPI / 2.0;
} else {
if (cosx > 0.0)
return atan(sinx / cosx);
else
return kPI + atan(sinx / cosx);
}
}
void TrimLeft(std::string& str);
void TrimRight(std::string& str);
void Trim(std::string& str);
#endif
#ifndef GLOBALS_H_
#define GLOBALS_H_
#include <cmath>
#include <string>
const double kAE = 1.0;
const double kQ0 = 120.0;
const double kS0 = 78.0;
const double kMU = 398600.8;
const double kXKMPER = 6378.135;
const double kXJ2 = 1.082616e-3;
const double kXJ3 = -2.53881e-6;
const double kXJ4 = -1.65597e-6;
/*
* alternative XKE
* affects final results
* aiaa-2006-6573
* const double kXKE = 60.0 / sqrt(kXKMPER * kXKMPER * kXKMPER / kMU);
* dundee
* const double kXKE = 7.43669161331734132e-2;
*/
const double kXKE = 60.0 / sqrt(kXKMPER * kXKMPER * kXKMPER / kMU);
const double kCK2 = 0.5 * kXJ2 * kAE * kAE;
const double kCK4 = -0.375 * kXJ4 * kAE * kAE * kAE * kAE;
/*
* alternative QOMS2T
* affects final results
* aiaa-2006-6573
* #define QOMS2T (pow(((Q0 - S0) / XKMPER), 4.0))
* dundee
* #define QOMS2T (1.880279159015270643865e-9)
*/
const double kQOMS2T = pow(((kQ0 - kS0) / kXKMPER), 4.0);
const double kS = kAE * (1.0 + kS0 / kXKMPER);
const double kPI = 3.14159265358979323846264338327950288419716939937510582;
const double kTWOPI = 2.0 * kPI;
const double kTWOTHIRD = 2.0 / 3.0;
const double kTHDT = 4.37526908801129966e-3;
/*
* earth flattening
*/
const double kF = 1.0 / 298.26;
/*
* earth rotation per sideral day
*/
const double kOMEGA_E = 1.00273790934;
const double kAU = 1.49597870691e8;
const double kSECONDS_PER_DAY = 86400.0;
const double kMINUTES_PER_DAY = 1440.0;
const double kHOURS_PER_DAY = 24.0;
// Jan 1.0 1900 = Jan 1 1900 00h UTC
const double kEPOCH_JAN1_00H_1900 = 2415019.5;
// Jan 1.5 1900 = Jan 1 1900 12h UTC
const double kEPOCH_JAN1_12H_1900 = 2415020.0;
// Jan 1.5 2000 = Jan 1 2000 12h UTC
const double kEPOCH_JAN1_12H_2000 = 2451545.0;
inline double Fmod2p(const double arg) {
double modu = fmod(arg, kTWOPI);
if (modu < 0.0)
modu += kTWOPI;
return modu;
}
inline double DegreesToRadians(const double degrees) {
return degrees * kPI / 180.0;
}
inline double RadiansToDegrees(const double radians) {
return radians * 180.0 / kPI;
}
inline double AcTan(const double sinx, const double cosx) {
if (cosx == 0.0) {
if (sinx > 0.0)
return kPI / 2.0;
else
return 3.0 * kPI / 2.0;
} else {
if (cosx > 0.0)
return atan(sinx / cosx);
else
return kPI + atan(sinx / cosx);
}
}
void TrimLeft(std::string& str);
void TrimRight(std::string& str);
void Trim(std::string& str);
#endif

336
Julian.h
View File

@ -1,168 +1,168 @@
#ifndef JULIAN_H_
#define JULIAN_H_
#include "Globals.h"
#include "Timespan.h"
#include <ctime>
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
class Julian
{
public:
Julian();
Julian(const Julian& jul)
{
date_ = jul.date_;
}
Julian(const time_t t);
/*
* create julian date from year and day of year
*/
Julian(int year, double day)
{
Initialize(year, day);
}
/*
* create julian date from individual components
* year: 2004
* mon: 1-12
* day: 1-31
* hour: 0-23
* min: 0-59
* sec: 0-59.99
*/
Julian(int year, int mon, int day, int hour, int min, double sec)
{
Initialize(year, mon, day, hour, min, sec);
}
~Julian()
{
}
// comparison operators
bool operator==(const Julian &date) const;
bool operator!=(const Julian &date) const;
bool operator>(const Julian &date) const;
bool operator<(const Julian &date) const;
bool operator>=(const Julian &date) const;
bool operator<=(const Julian &date) const;
// assignment
Julian& operator =(const Julian& b);
Julian& operator =(const double b);
// arithmetic
Julian operator +(const Timespan& b) const;
Julian operator -(const Timespan& b) const;
Timespan operator -(const Julian& b) const;
// compound assignment
Julian & operator +=(const Timespan& b);
Julian & operator -=(const Timespan& b);
std::string ToString() const
{
std::stringstream ss;
struct DateTimeComponents dt;
ToGregorian(&dt);
ss << std::right << std::fixed;
ss << std::setprecision(6) << std::setfill('0');
ss << std::setw(4) << dt.years << "-";
ss << std::setw(2) << dt.months << "-";
ss << std::setw(2) << dt.days << " ";
ss << std::setw(2) << dt.hours << ":";
ss << std::setw(2) << dt.minutes << ":";
ss << std::setw(9) << dt.seconds << " UTC";
return ss.str();
}
struct DateTimeComponents {
DateTimeComponents()
: years(0), months(0), days(0),
hours(0), minutes(0), seconds(0.0) {
}
int years;
int months;
int days;
int hours;
int minutes;
double seconds;
};
void ToGregorian(struct DateTimeComponents* datetime) const;
time_t ToTime() const;
double ToGreenwichSiderealTime() const;
double ToLocalMeanSiderealTime(const double& lon) const;
double FromJan1_00h_1900() const
{
return date_ - kEPOCH_JAN1_00H_1900;
}
double FromJan1_12h_1900() const
{
return date_ - kEPOCH_JAN1_12H_1900;
}
double FromJan1_12h_2000() const
{
return date_ - kEPOCH_JAN1_12H_2000;
}
double GetDate() const
{
return date_;
}
void AddDay(double day)
{
date_ += day;
}
void AddHour(double hr)
{
date_ += (hr / kHOURS_PER_DAY);
}
void AddMin(double min)
{
date_ += (min / kMINUTES_PER_DAY);
}
void AddSec(double sec)
{
date_ += (sec / kSECONDS_PER_DAY);
}
static bool IsLeapYear(int y)
{
return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0);
}
protected:
void Initialize(int year, double day);
void Initialize(int year, int mon, int day, int hour, int min, double sec);
/*
* the stored julian date
*/
double date_;
};
inline std::ostream& operator<<(std::ostream& strm, const Julian& j)
{
return strm << j.ToString();
}
#endif
#ifndef JULIAN_H_
#define JULIAN_H_
#include "Globals.h"
#include "Timespan.h"
#include <ctime>
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
class Julian
{
public:
Julian();
Julian(const Julian& jul)
{
date_ = jul.date_;
}
Julian(const time_t t);
/*
* create julian date from year and day of year
*/
Julian(int year, double day)
{
Initialize(year, day);
}
/*
* create julian date from individual components
* year: 2004
* mon: 1-12
* day: 1-31
* hour: 0-23
* min: 0-59
* sec: 0-59.99
*/
Julian(int year, int mon, int day, int hour, int min, double sec)
{
Initialize(year, mon, day, hour, min, sec);
}
~Julian()
{
}
// comparison operators
bool operator==(const Julian &date) const;
bool operator!=(const Julian &date) const;
bool operator>(const Julian &date) const;
bool operator<(const Julian &date) const;
bool operator>=(const Julian &date) const;
bool operator<=(const Julian &date) const;
// assignment
Julian& operator =(const Julian& b);
Julian& operator =(const double b);
// arithmetic
Julian operator +(const Timespan& b) const;
Julian operator -(const Timespan& b) const;
Timespan operator -(const Julian& b) const;
// compound assignment
Julian & operator +=(const Timespan& b);
Julian & operator -=(const Timespan& b);
std::string ToString() const
{
std::stringstream ss;
struct DateTimeComponents dt;
ToGregorian(&dt);
ss << std::right << std::fixed;
ss << std::setprecision(6) << std::setfill('0');
ss << std::setw(4) << dt.years << "-";
ss << std::setw(2) << dt.months << "-";
ss << std::setw(2) << dt.days << " ";
ss << std::setw(2) << dt.hours << ":";
ss << std::setw(2) << dt.minutes << ":";
ss << std::setw(9) << dt.seconds << " UTC";
return ss.str();
}
struct DateTimeComponents {
DateTimeComponents()
: years(0), months(0), days(0),
hours(0), minutes(0), seconds(0.0) {
}
int years;
int months;
int days;
int hours;
int minutes;
double seconds;
};
void ToGregorian(struct DateTimeComponents* datetime) const;
time_t ToTime() const;
double ToGreenwichSiderealTime() const;
double ToLocalMeanSiderealTime(const double& lon) const;
double FromJan1_00h_1900() const
{
return date_ - kEPOCH_JAN1_00H_1900;
}
double FromJan1_12h_1900() const
{
return date_ - kEPOCH_JAN1_12H_1900;
}
double FromJan1_12h_2000() const
{
return date_ - kEPOCH_JAN1_12H_2000;
}
double GetDate() const
{
return date_;
}
void AddDay(double day)
{
date_ += day;
}
void AddHour(double hr)
{
date_ += (hr / kHOURS_PER_DAY);
}
void AddMin(double min)
{
date_ += (min / kMINUTES_PER_DAY);
}
void AddSec(double sec)
{
date_ += (sec / kSECONDS_PER_DAY);
}
static bool IsLeapYear(int y)
{
return (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0);
}
protected:
void Initialize(int year, double day);
void Initialize(int year, int mon, int day, int hour, int min, double sec);
/*
* the stored julian date
*/
double date_;
};
inline std::ostream& operator<<(std::ostream& strm, const Julian& j)
{
return strm << j.ToString();
}
#endif

View File

@ -1,68 +1,68 @@
#ifndef OBSERVER_H_
#define OBSERVER_H_
#include "CoordGeodetic.h"
#include "CoordTopographic.h"
#include "Julian.h"
#include "Eci.h"
class Observer
{
public:
Observer(double latitude, double longitude, double altitude)
: geo_(latitude, longitude, altitude),
observers_eci_(Julian(), geo_)
{
}
Observer(const CoordGeodetic &g)
: geo_(g), observers_eci_(Julian(), geo_)
{
}
virtual ~Observer()
{
}
void SetLocation(const CoordGeodetic& g)
{
geo_ = g;
observers_eci_ = Eci(observers_eci_.GetDate(), geo_);
}
CoordGeodetic GetLocation() const
{
return geo_;
}
Eci GetEciPosition(const Julian &date) const
{
return Eci(date, geo_);
}
CoordTopographic GetLookAngle(const Eci &eci);
private:
void UpdateObserversEci(const Julian &date)
{
/*
* if date has changed, update for new date
*/
if (observers_eci_.GetDate() != date)
{
observers_eci_ = Eci(date, geo_);
}
}
/*
* the observers position
*/
CoordGeodetic geo_;
/*
* the observers eci for a particular time
*/
Eci observers_eci_;
};
#endif
#ifndef OBSERVER_H_
#define OBSERVER_H_
#include "CoordGeodetic.h"
#include "CoordTopographic.h"
#include "Julian.h"
#include "Eci.h"
class Observer
{
public:
Observer(double latitude, double longitude, double altitude)
: geo_(latitude, longitude, altitude),
observers_eci_(Julian(), geo_)
{
}
Observer(const CoordGeodetic &g)
: geo_(g), observers_eci_(Julian(), geo_)
{
}
virtual ~Observer()
{
}
void SetLocation(const CoordGeodetic& g)
{
geo_ = g;
observers_eci_ = Eci(observers_eci_.GetDate(), geo_);
}
CoordGeodetic GetLocation() const
{
return geo_;
}
Eci GetEciPosition(const Julian &date) const
{
return Eci(date, geo_);
}
CoordTopographic GetLookAngle(const Eci &eci);
private:
void UpdateObserversEci(const Julian &date)
{
/*
* if date has changed, update for new date
*/
if (observers_eci_.GetDate() != date)
{
observers_eci_ = Eci(date, geo_);
}
}
/*
* the observers position
*/
CoordGeodetic geo_;
/*
* the observers eci for a particular time
*/
Eci observers_eci_;
};
#endif

View File

@ -1,128 +1,128 @@
#ifndef ORBITALELEMENTS_H_
#define ORBITALELEMENTS_H_
#include "Tle.h"
class OrbitalElements
{
public:
OrbitalElements(const Tle& tle);
virtual ~OrbitalElements()
{
}
/*
* XMO
*/
double MeanAnomoly() const
{
return mean_anomoly_;
}
/*
* XNODEO
*/
double AscendingNode() const
{
return ascending_node_;
}
/*
* OMEGAO
*/
double ArgumentPerigee() const
{
return argument_perigee_;
}
/*
* EO
*/
double Eccentricity() const
{
return eccentricity_;
}
/*
* XINCL
*/
double Inclination() const
{
return inclination_;
}
/*
* XNO
*/
double MeanMotion() const
{
return mean_motion_;
}
/*
* BSTAR
*/
double BStar() const
{
return bstar_;
}
/*
* AODP
*/
double RecoveredSemiMajorAxis() const
{
return recovered_semi_major_axis_;
}
/*
* XNODP
*/
double RecoveredMeanMotion() const
{
return recovered_mean_motion_;
}
/*
* PERIGE
*/
double Perigee() const
{
return perigee_;
}
/*
* Period in minutes
*/
double Period() const
{
return period_;
}
/*
* EPOCH
*/
Julian Epoch() const
{
return epoch_;
}
private:
double mean_anomoly_;
double ascending_node_;
double argument_perigee_;
double eccentricity_;
double inclination_;
double mean_motion_;
double bstar_;
double recovered_semi_major_axis_;
double recovered_mean_motion_;
double perigee_;
double period_;
Julian epoch_;
};
#endif
#ifndef ORBITALELEMENTS_H_
#define ORBITALELEMENTS_H_
#include "Tle.h"
class OrbitalElements
{
public:
OrbitalElements(const Tle& tle);
virtual ~OrbitalElements()
{
}
/*
* XMO
*/
double MeanAnomoly() const
{
return mean_anomoly_;
}
/*
* XNODEO
*/
double AscendingNode() const
{
return ascending_node_;
}
/*
* OMEGAO
*/
double ArgumentPerigee() const
{
return argument_perigee_;
}
/*
* EO
*/
double Eccentricity() const
{
return eccentricity_;
}
/*
* XINCL
*/
double Inclination() const
{
return inclination_;
}
/*
* XNO
*/
double MeanMotion() const
{
return mean_motion_;
}
/*
* BSTAR
*/
double BStar() const
{
return bstar_;
}
/*
* AODP
*/
double RecoveredSemiMajorAxis() const
{
return recovered_semi_major_axis_;
}
/*
* XNODP
*/
double RecoveredMeanMotion() const
{
return recovered_mean_motion_;
}
/*
* PERIGE
*/
double Perigee() const
{
return perigee_;
}
/*
* Period in minutes
*/
double Period() const
{
return period_;
}
/*
* EPOCH
*/
Julian Epoch() const
{
return epoch_;
}
private:
double mean_anomoly_;
double ascending_node_;
double argument_perigee_;
double eccentricity_;
double inclination_;
double mean_motion_;
double bstar_;
double recovered_semi_major_axis_;
double recovered_mean_motion_;
double perigee_;
double period_;
Julian epoch_;
};
#endif

View File

@ -1,110 +1,110 @@
# ------------------ Verification test cases ----------------------
# # TEME example
1 00005U 58002B 00179.78495062 .00000023 00000-0 28098-4 0 4753
2 00005 34.2682 348.7242 1859667 331.7664 19.3264 10.82419157413667 0.00 4320.0 360.00
# ## fig show lyddane fix error with gsfc ver
1 04632U 70093B 04031.91070959 -.00000084 00000-0 10000-3 0 9955
2 04632 11.4628 273.1101 1450506 207.6000 143.9350 1.20231981 44145 -5184.0 -4896.0 120.00
# DELTA 1 DEB # near earth normal drag equation
# # perigee = 377.26km, so moderate drag case
1 06251U 62025E 06176.82412014 .00008885 00000-0 12808-3 0 3985
2 06251 58.0579 54.0425 0030035 139.1568 221.1854 15.56387291 6774 0.0 2880.0 120.00
# MOLNIYA 2-14 # 12h resonant ecc in 0.65 to 0.7 range
1 08195U 75081A 06176.33215444 .00000099 00000-0 11873-3 0 813
2 08195 64.1586 279.0717 6877146 264.7651 20.2257 2.00491383225656 0.0 2880.0 120.00
# MOLNIYA 1-36 ## fig 12h resonant ecc in 0.7 to 0.715 range
1 09880U 77021A 06176.56157475 .00000421 00000-0 10000-3 0 9814
2 09880 64.5968 349.3786 7069051 270.0229 16.3320 2.00813614112380 0.0 2880.0 120.00
# SMS 1 AKM # show the integrator problem with gsfc ver
1 09998U 74033F 05148.79417928 -.00000112 00000-0 00000+0 0 4480
2 09998 9.4958 313.1750 0270971 327.5225 30.8097 1.16186785 45878 -1440.0 -720.00 60.0
# # Original STR#3 SDP4 test
1 11801U 80230.29629788 .01431103 00000-0 14311-1 13
2 11801 46.7916 230.4354 7318036 47.4722 10.4117 2.28537848 13 0.0 1440.0 360.00
# EUTELSAT 1-F1 (ECS1)## fig lyddane choice in GSFC at 2080 min
1 14128U 83058A 06176.02844893 -.00000158 00000-0 10000-3 0 9627
2 14128 11.4384 35.2134 0011562 26.4582 333.5652 0.98870114 46093 0.0 2880.0 120.00
# SL-6 R/B(2) # Deep space, perigee = 82.48 (<98) for
# # s4 > 20 mod
1 16925U 86065D 06151.67415771 .02550794 -30915-6 18784-3 0 4486
2 16925 62.0906 295.0239 5596327 245.1593 47.9690 4.88511875148616 0.0 1440.0 120.00
# SL-12 R/B # Shows Lyddane choice at 1860 and 4700 min
1 20413U 83020D 05363.79166667 .00000000 00000-0 00000+0 0 7041
2 20413 12.3514 187.4253 7864447 196.3027 356.5478 0.24690082 7978 1440.0 4320.0 120.00
# MOLNIYA 1-83 # 12h resonant, ecc > 0.715 (negative BSTAR)
1 21897U 92011A 06176.02341244 -.00001273 00000-0 -13525-3 0 3044
2 21897 62.1749 198.0096 7421690 253.0462 20.1561 2.01269994104880 0.0 2880.0 120.00
# SL-6 R/B(2) # last tle given, decayed 2006-04-04, day 94
1 22312U 93002D 06094.46235912 .99999999 81888-5 49949-3 0 3953
2 22312 62.1486 77.4698 0308723 267.9229 88.7392 15.95744531 98783 54.2028672 1440.0 20.00
# SL-6 R/B(2) # 12h resonant ecc in the > 0.715 range
1 22674U 93035D 06176.55909107 .00002121 00000-0 29868-3 0 6569
2 22674 63.5035 354.4452 7541712 253.3264 18.7754 1.96679808 93877 0.0 2880.0 120.00
# ARIANE 44L+ R/B # Lyddane bug at <= 70 min for atan2(),
# # no quadrant fix
1 23177U 94040C 06175.45752052 .00000386 00000-0 76590-3 0 95
2 23177 7.0496 179.8238 7258491 296.0482 8.3061 2.25906668 97438 0.0 1440.0 120.00
# WIND # STR#3 Kepler failes past about 200 min
1 23333U 94071A 94305.49999999 -.00172956 26967-3 10000-3 0 15
2 23333 28.7490 2.3720 9728298 30.4360 1.3500 0.07309491 70 0.0 1600.0 120.00
# ARIANE 42P+3 R/B ## fig Lyddane bug at > 280.5 min for AcTan()
1 23599U 95029B 06171.76535463 .00085586 12891-6 12956-2 0 2905
2 23599 6.9327 0.2849 5782022 274.4436 25.2425 4.47796565123555 0.0 720.0 20.00
# ITALSAT 2 # 24h resonant GEO, inclination > 3 deg
1 24208U 96044A 06177.04061740 -.00000094 00000-0 10000-3 0 1600
2 24208 3.8536 80.0121 0026640 311.0977 48.3000 1.00778054 36119 0.0 1440.0 120.00
# AMC-4 ## fig low incl, show incl shift with
# ## gsfc version from 240 to 1440 min
1 25954U 99060A 04039.68057285 -.00000108 00000-0 00000-0 0 6847
2 25954 0.0004 243.8136 0001765 15.5294 22.7134 1.00271289 15615 -1440.0 1440.0 120.00
# INTELSAT 902 # negative incl at 9313 min then
# # 270 deg Lyddane bug at 37606 min
1 26900U 01039A 06106.74503247 .00000045 00000-0 10000-3 0 8290
2 26900 0.0164 266.5378 0003319 86.1794 182.2590 1.00273847 16981 9300.00 9400.00 60.00
# COSMOS 1024 DEB # 12h resonant ecc in 0.5 to 0.65 range
1 26975U 78066F 06174.85818871 .00000620 00000-0 10000-3 0 6809
2 26975 68.4714 236.1303 5602877 123.7484 302.5767 2.05657553 67521 0.0 2880.0 120.00
# CBERS 2 # Near Earth, ecc = 8.84E-5 (< 1.0e-4)
# # drop certain normal drag terms
1 28057U 03049A 06177.78615833 .00000060 00000-0 35940-4 0 1836
2 28057 98.4283 247.6961 0000884 88.1964 271.9322 14.35478080140550 0.0 2880.0 120.00
# NAVSTAR 53 (USA 175)# 12h non-resonant GPS (ecc < 0.5 ecc)
1 28129U 03058A 06175.57071136 -.00000104 00000-0 10000-3 0 459
2 28129 54.7298 324.8098 0048506 266.2640 93.1663 2.00562768 18443 0.0 1440.0 120.00
# COSMOS 2405 # Near Earth, perigee = 127.20 (< 156) s4 mod
1 28350U 04020A 06167.21788666 .16154492 76267-5 18678-3 0 8894
2 28350 64.9977 345.6130 0024870 260.7578 99.9590 16.47856722116490 0.0 2880.0 120.00
# H-2 R/B # Deep space, perigee = 135.75 (<156) s4 mod
1 28623U 05006B 06177.81079184 .00637644 69054-6 96390-3 0 6000
2 28623 28.5200 114.9834 6249053 170.2550 212.8965 3.79477162 12753 0.0 1440.0 120.00
# XM-3 # 24h resonant geo, incl < 3 deg goes
# # negative around 1130 min
1 28626U 05008A 06176.46683397 -.00000205 00000-0 10000-3 0 2190
2 28626 0.0019 286.9433 0000335 13.7918 55.6504 1.00270176 4891 0.0 1440.0 120.00
# MINOTAUR R/B # Sub-orbital case - Decayed 2005-11-29
# #(perigee = -51km), lost in 50 minutes
1 28872U 05037B 05333.02012661 .25992681 00000-0 24476-3 0 1534
2 28872 96.4736 157.9986 0303955 244.0492 110.6523 16.46015938 10708 0.0 60.0 5.00
# SL-14 DEB # Last stage of decay - lost in under 420 min
1 29141U 85108AA 06170.26783845 .99999999 00000-0 13519-0 0 718
2 29141 82.4288 273.4882 0015848 277.2124 83.9133 15.93343074 6828 0.0 440.0 20.00
# SL-12 DEB # Near Earth, perigee = 212.24 < 220
# # simplified drag eq
1 29238U 06022G 06177.28732010 .00766286 10823-4 13334-2 0 101
2 29238 51.5595 213.7903 0202579 95.2503 267.9010 15.73823839 1061 0.0 1440.0 120.00
# # Original STR#3 SGP4 test
1 88888U 80275.98708465 .00073094 13844-3 66816-4 0 87
2 88888 72.8435 115.9689 0086731 52.6988 110.5714 16.05824518 1058 0.0 1440.0 120.00
#
# # check error code 4
1 33333U 05037B 05333.02012661 .25992681 00000-0 24476-3 0 1534
2 33333 96.4736 157.9986 9950000 244.0492 110.6523 4.00004038 10708 0.0 150.0 5.00
# # try and check error code 2 but this
1 33334U 78066F 06174.85818871 .00000620 00000-0 10000-3 0 6809
2 33334 68.4714 236.1303 5602877 123.7484 302.5767 0.00001000 67521 0.0 1440.0 1.00
# # try to check error code 3 looks like ep never goes below zero, tied close to ecc
1 33335U 05008A 06176.46683397 -.00000205 00000-0 10000-3 0 2190
2 33335 0.0019 286.9433 0000004 13.7918 55.6504 1.00270176 4891 0.0 1440.0 20.00
# SL-12 R/B # Shows Lyddane choice at 1860 and 4700 min
1 20413U 83020D 05363.79166667 .00000000 00000-0 00000+0 0 7041
2 20413 12.3514 187.4253 7864447 196.3027 356.5478 0.24690082 7978 1844000 1845100 5.00
# ------------------ Verification test cases ----------------------
# # TEME example
1 00005U 58002B 00179.78495062 .00000023 00000-0 28098-4 0 4753
2 00005 34.2682 348.7242 1859667 331.7664 19.3264 10.82419157413667 0.00 4320.0 360.00
# ## fig show lyddane fix error with gsfc ver
1 04632U 70093B 04031.91070959 -.00000084 00000-0 10000-3 0 9955
2 04632 11.4628 273.1101 1450506 207.6000 143.9350 1.20231981 44145 -5184.0 -4896.0 120.00
# DELTA 1 DEB # near earth normal drag equation
# # perigee = 377.26km, so moderate drag case
1 06251U 62025E 06176.82412014 .00008885 00000-0 12808-3 0 3985
2 06251 58.0579 54.0425 0030035 139.1568 221.1854 15.56387291 6774 0.0 2880.0 120.00
# MOLNIYA 2-14 # 12h resonant ecc in 0.65 to 0.7 range
1 08195U 75081A 06176.33215444 .00000099 00000-0 11873-3 0 813
2 08195 64.1586 279.0717 6877146 264.7651 20.2257 2.00491383225656 0.0 2880.0 120.00
# MOLNIYA 1-36 ## fig 12h resonant ecc in 0.7 to 0.715 range
1 09880U 77021A 06176.56157475 .00000421 00000-0 10000-3 0 9814
2 09880 64.5968 349.3786 7069051 270.0229 16.3320 2.00813614112380 0.0 2880.0 120.00
# SMS 1 AKM # show the integrator problem with gsfc ver
1 09998U 74033F 05148.79417928 -.00000112 00000-0 00000+0 0 4480
2 09998 9.4958 313.1750 0270971 327.5225 30.8097 1.16186785 45878 -1440.0 -720.00 60.0
# # Original STR#3 SDP4 test
1 11801U 80230.29629788 .01431103 00000-0 14311-1 13
2 11801 46.7916 230.4354 7318036 47.4722 10.4117 2.28537848 13 0.0 1440.0 360.00
# EUTELSAT 1-F1 (ECS1)## fig lyddane choice in GSFC at 2080 min
1 14128U 83058A 06176.02844893 -.00000158 00000-0 10000-3 0 9627
2 14128 11.4384 35.2134 0011562 26.4582 333.5652 0.98870114 46093 0.0 2880.0 120.00
# SL-6 R/B(2) # Deep space, perigee = 82.48 (<98) for
# # s4 > 20 mod
1 16925U 86065D 06151.67415771 .02550794 -30915-6 18784-3 0 4486
2 16925 62.0906 295.0239 5596327 245.1593 47.9690 4.88511875148616 0.0 1440.0 120.00
# SL-12 R/B # Shows Lyddane choice at 1860 and 4700 min
1 20413U 83020D 05363.79166667 .00000000 00000-0 00000+0 0 7041
2 20413 12.3514 187.4253 7864447 196.3027 356.5478 0.24690082 7978 1440.0 4320.0 120.00
# MOLNIYA 1-83 # 12h resonant, ecc > 0.715 (negative BSTAR)
1 21897U 92011A 06176.02341244 -.00001273 00000-0 -13525-3 0 3044
2 21897 62.1749 198.0096 7421690 253.0462 20.1561 2.01269994104880 0.0 2880.0 120.00
# SL-6 R/B(2) # last tle given, decayed 2006-04-04, day 94
1 22312U 93002D 06094.46235912 .99999999 81888-5 49949-3 0 3953
2 22312 62.1486 77.4698 0308723 267.9229 88.7392 15.95744531 98783 54.2028672 1440.0 20.00
# SL-6 R/B(2) # 12h resonant ecc in the > 0.715 range
1 22674U 93035D 06176.55909107 .00002121 00000-0 29868-3 0 6569
2 22674 63.5035 354.4452 7541712 253.3264 18.7754 1.96679808 93877 0.0 2880.0 120.00
# ARIANE 44L+ R/B # Lyddane bug at <= 70 min for atan2(),
# # no quadrant fix
1 23177U 94040C 06175.45752052 .00000386 00000-0 76590-3 0 95
2 23177 7.0496 179.8238 7258491 296.0482 8.3061 2.25906668 97438 0.0 1440.0 120.00
# WIND # STR#3 Kepler failes past about 200 min
1 23333U 94071A 94305.49999999 -.00172956 26967-3 10000-3 0 15
2 23333 28.7490 2.3720 9728298 30.4360 1.3500 0.07309491 70 0.0 1600.0 120.00
# ARIANE 42P+3 R/B ## fig Lyddane bug at > 280.5 min for AcTan()
1 23599U 95029B 06171.76535463 .00085586 12891-6 12956-2 0 2905
2 23599 6.9327 0.2849 5782022 274.4436 25.2425 4.47796565123555 0.0 720.0 20.00
# ITALSAT 2 # 24h resonant GEO, inclination > 3 deg
1 24208U 96044A 06177.04061740 -.00000094 00000-0 10000-3 0 1600
2 24208 3.8536 80.0121 0026640 311.0977 48.3000 1.00778054 36119 0.0 1440.0 120.00
# AMC-4 ## fig low incl, show incl shift with
# ## gsfc version from 240 to 1440 min
1 25954U 99060A 04039.68057285 -.00000108 00000-0 00000-0 0 6847
2 25954 0.0004 243.8136 0001765 15.5294 22.7134 1.00271289 15615 -1440.0 1440.0 120.00
# INTELSAT 902 # negative incl at 9313 min then
# # 270 deg Lyddane bug at 37606 min
1 26900U 01039A 06106.74503247 .00000045 00000-0 10000-3 0 8290
2 26900 0.0164 266.5378 0003319 86.1794 182.2590 1.00273847 16981 9300.00 9400.00 60.00
# COSMOS 1024 DEB # 12h resonant ecc in 0.5 to 0.65 range
1 26975U 78066F 06174.85818871 .00000620 00000-0 10000-3 0 6809
2 26975 68.4714 236.1303 5602877 123.7484 302.5767 2.05657553 67521 0.0 2880.0 120.00
# CBERS 2 # Near Earth, ecc = 8.84E-5 (< 1.0e-4)
# # drop certain normal drag terms
1 28057U 03049A 06177.78615833 .00000060 00000-0 35940-4 0 1836
2 28057 98.4283 247.6961 0000884 88.1964 271.9322 14.35478080140550 0.0 2880.0 120.00
# NAVSTAR 53 (USA 175)# 12h non-resonant GPS (ecc < 0.5 ecc)
1 28129U 03058A 06175.57071136 -.00000104 00000-0 10000-3 0 459
2 28129 54.7298 324.8098 0048506 266.2640 93.1663 2.00562768 18443 0.0 1440.0 120.00
# COSMOS 2405 # Near Earth, perigee = 127.20 (< 156) s4 mod
1 28350U 04020A 06167.21788666 .16154492 76267-5 18678-3 0 8894
2 28350 64.9977 345.6130 0024870 260.7578 99.9590 16.47856722116490 0.0 2880.0 120.00
# H-2 R/B # Deep space, perigee = 135.75 (<156) s4 mod
1 28623U 05006B 06177.81079184 .00637644 69054-6 96390-3 0 6000
2 28623 28.5200 114.9834 6249053 170.2550 212.8965 3.79477162 12753 0.0 1440.0 120.00
# XM-3 # 24h resonant geo, incl < 3 deg goes
# # negative around 1130 min
1 28626U 05008A 06176.46683397 -.00000205 00000-0 10000-3 0 2190
2 28626 0.0019 286.9433 0000335 13.7918 55.6504 1.00270176 4891 0.0 1440.0 120.00
# MINOTAUR R/B # Sub-orbital case - Decayed 2005-11-29
# #(perigee = -51km), lost in 50 minutes
1 28872U 05037B 05333.02012661 .25992681 00000-0 24476-3 0 1534
2 28872 96.4736 157.9986 0303955 244.0492 110.6523 16.46015938 10708 0.0 60.0 5.00
# SL-14 DEB # Last stage of decay - lost in under 420 min
1 29141U 85108AA 06170.26783845 .99999999 00000-0 13519-0 0 718
2 29141 82.4288 273.4882 0015848 277.2124 83.9133 15.93343074 6828 0.0 440.0 20.00
# SL-12 DEB # Near Earth, perigee = 212.24 < 220
# # simplified drag eq
1 29238U 06022G 06177.28732010 .00766286 10823-4 13334-2 0 101
2 29238 51.5595 213.7903 0202579 95.2503 267.9010 15.73823839 1061 0.0 1440.0 120.00
# # Original STR#3 SGP4 test
1 88888U 80275.98708465 .00073094 13844-3 66816-4 0 87
2 88888 72.8435 115.9689 0086731 52.6988 110.5714 16.05824518 1058 0.0 1440.0 120.00
#
# # check error code 4
1 33333U 05037B 05333.02012661 .25992681 00000-0 24476-3 0 1534
2 33333 96.4736 157.9986 9950000 244.0492 110.6523 4.00004038 10708 0.0 150.0 5.00
# # try and check error code 2 but this
1 33334U 78066F 06174.85818871 .00000620 00000-0 10000-3 0 6809
2 33334 68.4714 236.1303 5602877 123.7484 302.5767 0.00001000 67521 0.0 1440.0 1.00
# # try to check error code 3 looks like ep never goes below zero, tied close to ecc
1 33335U 05008A 06176.46683397 -.00000205 00000-0 10000-3 0 2190
2 33335 0.0019 286.9433 0000004 13.7918 55.6504 1.00270176 4891 0.0 1440.0 20.00
# SL-12 R/B # Shows Lyddane choice at 1860 and 4700 min
1 20413U 83020D 05363.79166667 .00000000 00000-0 00000+0 0 7041
2 20413 12.3514 187.4253 7864447 196.3027 356.5478 0.24690082 7978 1844000 1845100 5.00

498
SGP4.h
View File

@ -1,249 +1,249 @@
#ifndef SGP4_H_
#define SGP4_H_
#include "Tle.h"
#include "OrbitalElements.h"
#include "Eci.h"
#include "SatelliteException.h"
class SGP4
{
public:
SGP4(const Tle& tle)
: elements_(tle)
{
Initialise();
}
virtual ~SGP4()
{
}
void SetTle(const Tle& tle);
Eci FindPosition(double tsince) const;
Eci FindPosition(const Julian& date) const;
struct CommonConstants
{
CommonConstants()
: cosio(0.0), sinio(0.0), eta(0.0), t2cof(0.0), a3ovk2(0.0),
x1mth2(0.0), x3thm1(0.0), x7thm1(0.0), aycof(0.0), xlcof(0.0),
xnodcf(0.0), c1(0.0), c4(0.0), omgdot(0.0), xnodot(0.0), xmdot(0.0)
{
}
double cosio;
double sinio;
double eta;
double t2cof;
double a3ovk2;
double x1mth2;
double x3thm1;
double x7thm1;
double aycof;
double xlcof;
double xnodcf;
double c1;
double c4;
double omgdot; // secular rate of omega (radians/sec)
double xnodot; // secular rate of xnode (radians/sec)
double xmdot; // secular rate of xmo (radians/sec)
};
struct NearSpaceConstants
{
NearSpaceConstants()
: c5(0.0), omgcof(0.0), xmcof(0.0), delmo(0.0), sinmo(0.0), d2(0.0),
d3(0.0), d4(0.0), t3cof(0.0), t4cof(0.0), t5cof(0.0)
{
}
double c5;
double omgcof;
double xmcof;
double delmo;
double sinmo;
double d2;
double d3;
double d4;
double t3cof;
double t4cof;
double t5cof;
};
struct DeepSpaceConstants
{
DeepSpaceConstants()
: gsto(0.0), zmol(0.0), zmos(0.0), resonance_flag(false),
synchronous_flag(false), sse(0.0), ssi(0.0), ssl(0.0), ssg(0.0),
ssh(0.0), se2(0.0), si2(0.0), sl2(0.0), sgh2(0.0), sh2(0.0), se3(0.0),
si3(0.0), sl3(0.0), sgh3(0.0), sh3(0.0), sl4(0.0), sgh4(0.0), ee2(0.0),
e3(0.0), xi2(0.0), xi3(0.0), xl2(0.0), xl3(0.0), xl4(0.0), xgh2(0.0),
xgh3(0.0), xgh4(0.0), xh2(0.0), xh3(0.0), d2201(0.0), d2211(0.0),
d3210(0.0), d3222(0.0), d4410(0.0), d4422(0.0), d5220(0.0), d5232(0.0),
d5421(0.0), d5433(0.0), del1(0.0), del2(0.0), del3(0.0)
{
}
double gsto;
double zmol;
double zmos;
/*
* whether the deep space orbit is
* geopotential resonance for 12 hour orbits
*/
bool resonance_flag;
/*
* whether the deep space orbit is
* 24h synchronous resonance
*/
bool synchronous_flag;
/*
* lunar / solar constants for epoch
* applied during DeepSpaceSecular()
*/
double sse;
double ssi;
double ssl;
double ssg;
double ssh;
/*
* lunar / solar constants
* used during DeepSpaceCalculateLunarSolarTerms()
*/
double se2;
double si2;
double sl2;
double sgh2;
double sh2;
double se3;
double si3;
double sl3;
double sgh3;
double sh3;
double sl4;
double sgh4;
double ee2;
double e3;
double xi2;
double xi3;
double xl2;
double xl3;
double xl4;
double xgh2;
double xgh3;
double xgh4;
double xh2;
double xh3;
/*
* used during DeepSpaceCalcDotTerms()
*/
double d2201;
double d2211;
double d3210;
double d3222;
double d4410;
double d4422;
double d5220;
double d5232;
double d5421;
double d5433;
double del1;
double del2;
double del3;
};
struct IntegratorValues
{
IntegratorValues() : xndot(0.0), xnddt(0.0), xldot(0.0)
{
}
double xndot;
double xnddt;
double xldot;
};
struct IntegratorConstants
{
IntegratorConstants() : xfact(0.0), xlamo(0.0)
{
}
/*
* integrator constants
*/
double xfact;
double xlamo;
/*
* integrator values for epoch
*/
struct IntegratorValues values_0;
};
struct IntegratorParams
{
IntegratorParams() : xli(0.0), xni(0.0), atime(0.0)
{
}
/*
* integrator values
*/
double xli;
double xni;
double atime;
/*
* itegrator values for current d_atime_
*/
struct IntegratorValues values_t;
};
private:
void Initialise();
void DeepSpaceInitialise(const double& eosq, const double& sinio, const double& cosio, const double& betao,
const double& theta2, const double& betao2,
const double& xmdot, const double& omgdot, const double& xnodot);
void DeepSpaceCalculateLunarSolarTerms(const double t, double* pe, double* pinc,
double* pl, double* pgh, double* ph) const;
void DeepSpacePeriodics(const double& t, double* em, double* xinc,
double* omgasm, double* xnodes, double* xll) const;
void DeepSpaceSecular(const double& t, double* xll, double* omgasm,
double* xnodes, double* em, double* xinc, double* xn) const;
Eci FindPositionSDP4(double tsince) const;
Eci FindPositionSGP4(double tsince) const;
Eci CalculateFinalPositionVelocity(const double& tsince, const double& e,
const double& a, const double& omega, const double& xl, const double& xnode,
const double& xincl, const double& xlcof, const double& aycof,
const double& x3thm1, const double& x1mth2, const double& x7thm1,
const double& cosio, const double& sinio) const;
void DeepSpaceCalcDotTerms(struct IntegratorValues *values) const;
void DeepSpaceIntegrator(const double delt, const double step2,
const struct IntegratorValues& values) const;
void Reset();
/*
* flags
*/
bool first_run_;
bool use_simple_model_;
bool use_deep_space_;
/*
* the constants used
*/
struct CommonConstants common_consts_;
struct NearSpaceConstants nearspace_consts_;
struct DeepSpaceConstants deepspace_consts_;
struct IntegratorConstants integrator_consts_;
mutable struct IntegratorParams integrator_params_;
/*
* the orbit data
*/
OrbitalElements elements_;
};
#endif
#ifndef SGP4_H_
#define SGP4_H_
#include "Tle.h"
#include "OrbitalElements.h"
#include "Eci.h"
#include "SatelliteException.h"
class SGP4
{
public:
SGP4(const Tle& tle)
: elements_(tle)
{
Initialise();
}
virtual ~SGP4()
{
}
void SetTle(const Tle& tle);
Eci FindPosition(double tsince) const;
Eci FindPosition(const Julian& date) const;
struct CommonConstants
{
CommonConstants()
: cosio(0.0), sinio(0.0), eta(0.0), t2cof(0.0), a3ovk2(0.0),
x1mth2(0.0), x3thm1(0.0), x7thm1(0.0), aycof(0.0), xlcof(0.0),
xnodcf(0.0), c1(0.0), c4(0.0), omgdot(0.0), xnodot(0.0), xmdot(0.0)
{
}
double cosio;
double sinio;
double eta;
double t2cof;
double a3ovk2;
double x1mth2;
double x3thm1;
double x7thm1;
double aycof;
double xlcof;
double xnodcf;
double c1;
double c4;
double omgdot; // secular rate of omega (radians/sec)
double xnodot; // secular rate of xnode (radians/sec)
double xmdot; // secular rate of xmo (radians/sec)
};
struct NearSpaceConstants
{
NearSpaceConstants()
: c5(0.0), omgcof(0.0), xmcof(0.0), delmo(0.0), sinmo(0.0), d2(0.0),
d3(0.0), d4(0.0), t3cof(0.0), t4cof(0.0), t5cof(0.0)
{
}
double c5;
double omgcof;
double xmcof;
double delmo;
double sinmo;
double d2;
double d3;
double d4;
double t3cof;
double t4cof;
double t5cof;
};
struct DeepSpaceConstants
{
DeepSpaceConstants()
: gsto(0.0), zmol(0.0), zmos(0.0), resonance_flag(false),
synchronous_flag(false), sse(0.0), ssi(0.0), ssl(0.0), ssg(0.0),
ssh(0.0), se2(0.0), si2(0.0), sl2(0.0), sgh2(0.0), sh2(0.0), se3(0.0),
si3(0.0), sl3(0.0), sgh3(0.0), sh3(0.0), sl4(0.0), sgh4(0.0), ee2(0.0),
e3(0.0), xi2(0.0), xi3(0.0), xl2(0.0), xl3(0.0), xl4(0.0), xgh2(0.0),
xgh3(0.0), xgh4(0.0), xh2(0.0), xh3(0.0), d2201(0.0), d2211(0.0),
d3210(0.0), d3222(0.0), d4410(0.0), d4422(0.0), d5220(0.0), d5232(0.0),
d5421(0.0), d5433(0.0), del1(0.0), del2(0.0), del3(0.0)
{
}
double gsto;
double zmol;
double zmos;
/*
* whether the deep space orbit is
* geopotential resonance for 12 hour orbits
*/
bool resonance_flag;
/*
* whether the deep space orbit is
* 24h synchronous resonance
*/
bool synchronous_flag;
/*
* lunar / solar constants for epoch
* applied during DeepSpaceSecular()
*/
double sse;
double ssi;
double ssl;
double ssg;
double ssh;
/*
* lunar / solar constants
* used during DeepSpaceCalculateLunarSolarTerms()
*/
double se2;
double si2;
double sl2;
double sgh2;
double sh2;
double se3;
double si3;
double sl3;
double sgh3;
double sh3;
double sl4;
double sgh4;
double ee2;
double e3;
double xi2;
double xi3;
double xl2;
double xl3;
double xl4;
double xgh2;
double xgh3;
double xgh4;
double xh2;
double xh3;
/*
* used during DeepSpaceCalcDotTerms()
*/
double d2201;
double d2211;
double d3210;
double d3222;
double d4410;
double d4422;
double d5220;
double d5232;
double d5421;
double d5433;
double del1;
double del2;
double del3;
};
struct IntegratorValues
{
IntegratorValues() : xndot(0.0), xnddt(0.0), xldot(0.0)
{
}
double xndot;
double xnddt;
double xldot;
};
struct IntegratorConstants
{
IntegratorConstants() : xfact(0.0), xlamo(0.0)
{
}
/*
* integrator constants
*/
double xfact;
double xlamo;
/*
* integrator values for epoch
*/
struct IntegratorValues values_0;
};
struct IntegratorParams
{
IntegratorParams() : xli(0.0), xni(0.0), atime(0.0)
{
}
/*
* integrator values
*/
double xli;
double xni;
double atime;
/*
* itegrator values for current d_atime_
*/
struct IntegratorValues values_t;
};
private:
void Initialise();
void DeepSpaceInitialise(const double& eosq, const double& sinio, const double& cosio, const double& betao,
const double& theta2, const double& betao2,
const double& xmdot, const double& omgdot, const double& xnodot);
void DeepSpaceCalculateLunarSolarTerms(const double t, double* pe, double* pinc,
double* pl, double* pgh, double* ph) const;
void DeepSpacePeriodics(const double& t, double* em, double* xinc,
double* omgasm, double* xnodes, double* xll) const;
void DeepSpaceSecular(const double& t, double* xll, double* omgasm,
double* xnodes, double* em, double* xinc, double* xn) const;
Eci FindPositionSDP4(double tsince) const;
Eci FindPositionSGP4(double tsince) const;
Eci CalculateFinalPositionVelocity(const double& tsince, const double& e,
const double& a, const double& omega, const double& xl, const double& xnode,
const double& xincl, const double& xlcof, const double& aycof,
const double& x3thm1, const double& x1mth2, const double& x7thm1,
const double& cosio, const double& sinio) const;
void DeepSpaceCalcDotTerms(struct IntegratorValues *values) const;
void DeepSpaceIntegrator(const double delt, const double step2,
const struct IntegratorValues& values) const;
void Reset();
/*
* flags
*/
bool first_run_;
bool use_simple_model_;
bool use_deep_space_;
/*
* the constants used
*/
struct CommonConstants common_consts_;
struct NearSpaceConstants nearspace_consts_;
struct DeepSpaceConstants deepspace_consts_;
struct IntegratorConstants integrator_consts_;
mutable struct IntegratorParams integrator_params_;
/*
* the orbit data
*/
OrbitalElements elements_;
};
#endif

View File

@ -1,28 +1,28 @@
#ifndef SATELLITEEXCEPTION_H_
#define SATELLITEEXCEPTION_H_
#include <exception>
#include <iostream>
class SatelliteException : public std::exception
{
public:
SatelliteException(const char* message)
: message_(message)
{
}
virtual ~SatelliteException(void) throw ()
{
}
virtual const char* what() const throw ()
{
return message_.c_str();
}
private:
std::string message_;
};
#endif
#ifndef SATELLITEEXCEPTION_H_
#define SATELLITEEXCEPTION_H_
#include <exception>
#include <iostream>
class SatelliteException : public std::exception
{
public:
SatelliteException(const char* message)
: message_(message)
{
}
virtual ~SatelliteException(void) throw ()
{
}
virtual const char* what() const throw ()
{
return message_.c_str();
}
private:
std::string message_;
};
#endif

View File

@ -1,25 +1,25 @@
#ifndef SOLARPOSITION_H_
#define SOLARPOSITION_H_
#include "Julian.h"
#include "Eci.h"
class SolarPosition
{
public:
SolarPosition()
{
}
virtual ~SolarPosition()
{
}
Eci FindPosition(const Julian& j);
private:
double Modulus(double arg1, double arg2) const;
double Delta_ET(double year) const;
};
#endif
#ifndef SOLARPOSITION_H_
#define SOLARPOSITION_H_
#include "Julian.h"
#include "Eci.h"
class SolarPosition
{
public:
SolarPosition()
{
}
virtual ~SolarPosition()
{
}
Eci FindPosition(const Julian& j);
private:
double Modulus(double arg1, double arg2) const;
double Delta_ET(double year) const;
};
#endif

View File

@ -1,57 +1,57 @@
#ifndef TIMESPAN_H_
#define TIMESPAN_H_
class Timespan {
public:
Timespan();
Timespan(const unsigned int days, const unsigned int hours,
const unsigned int minutes, const double seconds);
Timespan(const double b);
Timespan(const Timespan& b);
virtual ~Timespan(void);
void SetValue(const unsigned int days, const unsigned int hours,
const unsigned int minutes, const double seconds);
void AddDays(const unsigned int days);
void AddHours(const unsigned int hours);
void AddMinutes(const unsigned int minutes);
void AddSeconds(const double seconds);
double GetTotalDays() const;
double GetTotalHours() const;
double GetTotalMinutes() const;
double GetTotalSeconds() const;
// assignment
Timespan & operator=(const Timespan& b);
// arithmetic
Timespan operator+(const Timespan& b) const;
Timespan operator-(const Timespan& b) const;
Timespan operator/(const double b) const;
Timespan operator*(const double b) const;
// compound arithmetic
Timespan & operator+=(const Timespan& b);
Timespan & operator-=(const Timespan& b);
Timespan & operator/=(const double b);
Timespan & operator*=(const double b);
// comparison
bool operator==(const Timespan& b) const;
bool operator!=(const Timespan& b) const;
bool operator>(const Timespan& b) const;
bool operator<(const Timespan& b) const;
bool operator>=(const Timespan& b) const;
bool operator<=(const Timespan& b) const;
friend double& operator +=(double& a, const Timespan& b);
friend double& operator -=(double& a, const Timespan& b);
private:
/*
* stores value in minutes
*/
double time_span_;
};
#endif
#ifndef TIMESPAN_H_
#define TIMESPAN_H_
class Timespan {
public:
Timespan();
Timespan(const unsigned int days, const unsigned int hours,
const unsigned int minutes, const double seconds);
Timespan(const double b);
Timespan(const Timespan& b);
virtual ~Timespan(void);
void SetValue(const unsigned int days, const unsigned int hours,
const unsigned int minutes, const double seconds);
void AddDays(const unsigned int days);
void AddHours(const unsigned int hours);
void AddMinutes(const unsigned int minutes);
void AddSeconds(const double seconds);
double GetTotalDays() const;
double GetTotalHours() const;
double GetTotalMinutes() const;
double GetTotalSeconds() const;
// assignment
Timespan & operator=(const Timespan& b);
// arithmetic
Timespan operator+(const Timespan& b) const;
Timespan operator-(const Timespan& b) const;
Timespan operator/(const double b) const;
Timespan operator*(const double b) const;
// compound arithmetic
Timespan & operator+=(const Timespan& b);
Timespan & operator-=(const Timespan& b);
Timespan & operator/=(const double b);
Timespan & operator*=(const double b);
// comparison
bool operator==(const Timespan& b) const;
bool operator!=(const Timespan& b) const;
bool operator>(const Timespan& b) const;
bool operator<(const Timespan& b) const;
bool operator>=(const Timespan& b) const;
bool operator<=(const Timespan& b) const;
friend double& operator +=(double& a, const Timespan& b);
friend double& operator -=(double& a, const Timespan& b);
private:
/*
* stores value in minutes
*/
double time_span_;
};
#endif

832
Tle.cpp
View File

@ -1,416 +1,416 @@
#include "Tle.h"
#include <cstdlib>
namespace
{
/*
* line 1
*/
static const unsigned int TLE1_COL_NORADNUM = 2;
static const unsigned int TLE1_LEN_NORADNUM = 5;
static const unsigned int TLE1_COL_INTLDESC_A = 9;
static const unsigned int TLE1_LEN_INTLDESC_A = 2;
static const unsigned int TLE1_COL_INTLDESC_B = 11;
static const unsigned int TLE1_LEN_INTLDESC_B = 3;
static const unsigned int TLE1_COL_INTLDESC_C = 14;
static const unsigned int TLE1_LEN_INTLDESC_C = 3;
static const unsigned int TLE1_COL_EPOCH_A = 18;
static const unsigned int TLE1_LEN_EPOCH_A = 2;
static const unsigned int TLE1_COL_EPOCH_B = 20;
static const unsigned int TLE1_LEN_EPOCH_B = 12;
static const unsigned int TLE1_COL_MEANMOTIONDT = 33;
static const unsigned int TLE1_LEN_MEANMOTIONDT = 10;
static const unsigned int TLE1_COL_MEANMOTIONDT2 = 44;
static const unsigned int TLE1_LEN_MEANMOTIONDT2 = 8;
static const unsigned int TLE1_COL_BSTAR = 53;
static const unsigned int TLE1_LEN_BSTAR = 8;
static const unsigned int TLE1_COL_EPHEMTYPE = 62;
static const unsigned int TLE1_LEN_EPHEMTYPE = 1;
static const unsigned int TLE1_COL_ELNUM = 64;
static const unsigned int TLE1_LEN_ELNUM = 4;
/*
* line 2
*/
static const unsigned int TLE2_COL_NORADNUM = 2;
static const unsigned int TLE2_LEN_NORADNUM = 5;
static const unsigned int TLE2_COL_INCLINATION = 8;
static const unsigned int TLE2_LEN_INCLINATION = 8;
static const unsigned int TLE2_COL_RAASCENDNODE = 17;
static const unsigned int TLE2_LEN_RAASCENDNODE = 8;
static const unsigned int TLE2_COL_ECCENTRICITY = 26;
static const unsigned int TLE2_LEN_ECCENTRICITY = 7;
static const unsigned int TLE2_COL_ARGPERIGEE = 34;
static const unsigned int TLE2_LEN_ARGPERIGEE = 8;
static const unsigned int TLE2_COL_MEANANOMALY = 43;
static const unsigned int TLE2_LEN_MEANANOMALY = 8;
static const unsigned int TLE2_COL_MEANMOTION = 52;
static const unsigned int TLE2_LEN_MEANMOTION = 11;
static const unsigned int TLE2_COL_REVATEPOCH = 63;
static const unsigned int TLE2_LEN_REVATEPOCH = 5;
}
Tle::Tle(const Tle& tle)
{
name_ = tle.name_;
line_one_ = tle.line_one_;
line_two_ = tle.line_two_;
norad_number_ = tle.norad_number_;
international_designator_ = tle.international_designator_;
epoch_ = tle.epoch_;
mean_motion_dot_ = tle.mean_motion_dot_;
mean_motion_dot2_ = tle.mean_motion_dot2_;
bstar_ = tle.bstar_;
inclination_ = tle.inclination_;
right_ascending_node_ = tle.right_ascending_node_;
eccentricity_ = tle.eccentricity_;
argument_perigee_ = tle.argument_perigee_;
mean_anomaly_ = tle.mean_anomaly_;
mean_motion_ = tle.mean_motion_;
orbit_number_ = tle.orbit_number_;
}
/*
* convert a tle raw string into an exponent string
*/
std::string Tle::ExpToDecimal(const std::string& str)
{
static const int START_SIGN = 0;
static const int LENGTH_SIGN = 1;
static const int START_MANTISSA = 1;
static const int LENGTH_MANTISSA = 5;
static const int START_EXP = 6;
static const int LENGTH_EXP = 2;
if ((LENGTH_SIGN + LENGTH_MANTISSA + LENGTH_EXP) != str.length())
{
throw TleException("Invalid string length for exponential conversion.");
}
std::string value = str.substr(START_SIGN, LENGTH_SIGN);
value += ".";
value += str.substr(START_MANTISSA, LENGTH_MANTISSA);
value += "e";
value += str.substr(START_EXP, LENGTH_EXP);
return value;
}
/*
* extract all variables
*/
void Tle::Initialize()
{
std::string temp;
/*
* trim whitespace
*/
TrimLeft(name_);
TrimRight(name_);
TrimLeft(line_one_);
TrimRight(line_one_);
TrimLeft(line_two_);
TrimRight(line_two_);
/*
* check the two lines are valid
*/
IsValidPair(line_one_, line_two_);
/*
* line 1
*/
temp = ExtractNoradNumber(line_one_, 1);
norad_number_ = atoi(temp.c_str());
/*
* if blank use norad number for name
*/
if (name_.empty())
{
name_ = temp;
}
international_designator_ = line_one_.substr(TLE1_COL_INTLDESC_A,
TLE1_LEN_INTLDESC_A + TLE1_LEN_INTLDESC_B + TLE1_LEN_INTLDESC_C);
int year = atoi(line_one_.substr(TLE1_COL_EPOCH_A,
TLE1_LEN_EPOCH_A).c_str());
double day = atof(line_one_.substr(TLE1_COL_EPOCH_B,
TLE1_LEN_EPOCH_B).c_str());
/*
* generate julian date for epoch
*/
if (year < 57)
year += 2000;
else
year += 1900;
epoch_ = Julian(year, day);
if (line_one_[TLE1_COL_MEANMOTIONDT] == '-') {
temp = "-0";
} else
temp = "0";
temp += line_one_.substr(TLE1_COL_MEANMOTIONDT + 1, TLE1_LEN_MEANMOTIONDT);
mean_motion_dot_ = atof(temp.c_str());
temp = ExpToDecimal(line_one_.substr(TLE1_COL_MEANMOTIONDT2,
TLE1_LEN_MEANMOTIONDT2));
mean_motion_dot2_ = atof(temp.c_str());
temp = ExpToDecimal(line_one_.substr(TLE1_COL_BSTAR,
TLE1_LEN_BSTAR).c_str());
bstar_ = atof(temp.c_str());
/*
* line 2
*/
temp = line_two_.substr(TLE2_COL_INCLINATION, TLE2_LEN_INCLINATION);
TrimLeft(temp);
inclination_ = atof(temp.c_str());
temp = line_two_.substr(TLE2_COL_RAASCENDNODE, TLE2_LEN_RAASCENDNODE);
TrimLeft(temp);
right_ascending_node_ = atof(temp.c_str());
temp = "0.";
temp += line_two_.substr(TLE2_COL_ECCENTRICITY, TLE2_LEN_ECCENTRICITY);
eccentricity_ = atof(temp.c_str());
temp = line_two_.substr(TLE2_COL_ARGPERIGEE, TLE2_LEN_ARGPERIGEE);
TrimLeft(temp);
argument_perigee_ = atof(temp.c_str());
temp = line_two_.substr(TLE2_COL_MEANANOMALY, TLE2_LEN_MEANANOMALY);
TrimLeft(temp);
mean_anomaly_ = atof(temp.c_str());
temp = line_two_.substr(TLE2_COL_MEANMOTION, TLE2_LEN_MEANMOTION);
TrimLeft(temp);
mean_motion_ = atof(temp.c_str());
temp = line_two_.substr(TLE2_COL_REVATEPOCH, TLE2_LEN_REVATEPOCH);
TrimLeft(temp);
orbit_number_ = atoi(temp.c_str());
}
/*
* check the two lines have matching norad numbers
* and that the lines themselves are equal
*/
void Tle::IsValidPair(const std::string& line1, const std::string& line2)
{
/*
* validate each line
*/
IsValidLine(line1, 1);
IsValidLine(line2, 2);
/*
* extract norad numbers
*/
std::string norad_1 = ExtractNoradNumber(line1, 1);
std::string norad_2 = ExtractNoradNumber(line2, 2);
/*
* make sure they match
*/
if (norad_1.compare(norad_2) != 0)
{
throw TleException("Norad numbers do not match.");
}
}
/*
* validate a line
*/
void Tle::IsValidLine(const std::string& str, int line_number)
{
/*
* validation patterns
*/
static const std::string line1_pattern = "1 NNNNNC NNNNNXXX NNNNN.NNNNNNNN +.NNNNNNNN +NNNNN-N +NNNNN-N N NNNNN";
static const std::string line2_pattern = "2 NNNNN NNN.NNNN NNN.NNNN NNNNNNN NNN.NNNN NNN.NNNN NN.NNNNNNNNNNNNNN";
/*
* validate line against the pattern
*/
if (1 == line_number)
{
ValidateLine(str, line1_pattern);
}
else if (2 == line_number)
{
ValidateLine(str, line2_pattern);
}
else
{
throw TleException("Invalid line number to check.");
}
/*
* last char in string is modulo 10 checksum
* edited out as checksum isnt consistent
*
* int chk = CheckSum(str);
* if (chk != (str[TLE_LEN_LINE_DATA - 1] - '0'))
* return false;
*/
}
bool Tle::IsValidLineLength(const std::string& str)
{
return str.length() == GetLineLength() ? true : false;
}
/*
* validate line given a pattern
*/
void Tle::ValidateLine(const std::string& line, const std::string& pattern)
{
/*
* check length of line
*/
if (!IsValidLineLength(line))
{
throw TleException("Invalid line length.");
}
std::string::const_iterator pattern_itr = pattern.begin();
std::string::const_iterator line_itr = line.begin();
while (pattern_itr != pattern.end())
{
if (isdigit(*pattern_itr) || *pattern_itr == ' ' ||
*pattern_itr == '.')
{
/*
* should match exactly
*/
if (*pattern_itr != *line_itr)
{
throw TleException("Invalid character.");
}
}
else if (*pattern_itr == 'N')
{
/*
* 'N' = number or ' '
*/
if (!isdigit(*line_itr) && *line_itr != ' ')
{
throw TleException("Invalid character.");
}
}
else if (*pattern_itr == '+')
{
/*
* '+' = '+' or '-' or ' ' or '0'
*/
if (*line_itr != '+' && *line_itr != '-' &&
*line_itr != ' ' && *line_itr != '0')
{
throw TleException("Invalid character.");
}
}
else if (*pattern_itr == '-')
{
/*
* '-' = '+' or '-'
*/
if (*line_itr != '+' && *line_itr != '-')
{
throw TleException("Invalid character.");
}
}
else if (*pattern_itr == 'C')
{
/*
* 'C' = 'U' or 'S'
*/
if (*line_itr != 'U' && *line_itr != 'S')
{
throw TleException("Invalid character.");
}
}
else if (*pattern_itr == 'X')
{
/*
* 'X' = A-Z or ' '
*/
if (!(*line_itr >= 'A' || *line_itr <= 'Z') && *line_itr != ' ')
{
throw TleException("Invalid character.");
}
}
pattern_itr++;
line_itr++;
}
}
/*
* compute checksum
*/
int Tle::CheckSum(const std::string & str)
{
size_t len = str.size() - 1;
int xsum = 0;
for (size_t i = 0; i < len; i++)
{
char ch = str[i];
if (isdigit(ch))
{
xsum += (ch - '0');
}
else if (ch == '-')
{
xsum++;
}
}
return (xsum % 10);
}
std::string Tle::ExtractNoradNumber(const std::string& str, int line_number)
{
std::string norad_number;
/*
* check length
*/
if (!IsValidLineLength(str))
{
throw TleException("Invalid line length.");
}
/*
* extract string
*/
if (1 == line_number)
{
norad_number = str.substr(TLE1_COL_NORADNUM, TLE1_LEN_NORADNUM);
}
else if (2 == line_number)
{
norad_number = str.substr(TLE2_COL_NORADNUM, TLE2_LEN_NORADNUM);
}
else
{
throw TleException("Invalid line number to check.");
}
return norad_number;
}
#include "Tle.h"
#include <cstdlib>
namespace
{
/*
* line 1
*/
static const unsigned int TLE1_COL_NORADNUM = 2;
static const unsigned int TLE1_LEN_NORADNUM = 5;
static const unsigned int TLE1_COL_INTLDESC_A = 9;
static const unsigned int TLE1_LEN_INTLDESC_A = 2;
static const unsigned int TLE1_COL_INTLDESC_B = 11;
static const unsigned int TLE1_LEN_INTLDESC_B = 3;
static const unsigned int TLE1_COL_INTLDESC_C = 14;
static const unsigned int TLE1_LEN_INTLDESC_C = 3;
static const unsigned int TLE1_COL_EPOCH_A = 18;
static const unsigned int TLE1_LEN_EPOCH_A = 2;
static const unsigned int TLE1_COL_EPOCH_B = 20;
static const unsigned int TLE1_LEN_EPOCH_B = 12;
static const unsigned int TLE1_COL_MEANMOTIONDT = 33;
static const unsigned int TLE1_LEN_MEANMOTIONDT = 10;
static const unsigned int TLE1_COL_MEANMOTIONDT2 = 44;
static const unsigned int TLE1_LEN_MEANMOTIONDT2 = 8;
static const unsigned int TLE1_COL_BSTAR = 53;
static const unsigned int TLE1_LEN_BSTAR = 8;
static const unsigned int TLE1_COL_EPHEMTYPE = 62;
static const unsigned int TLE1_LEN_EPHEMTYPE = 1;
static const unsigned int TLE1_COL_ELNUM = 64;
static const unsigned int TLE1_LEN_ELNUM = 4;
/*
* line 2
*/
static const unsigned int TLE2_COL_NORADNUM = 2;
static const unsigned int TLE2_LEN_NORADNUM = 5;
static const unsigned int TLE2_COL_INCLINATION = 8;
static const unsigned int TLE2_LEN_INCLINATION = 8;
static const unsigned int TLE2_COL_RAASCENDNODE = 17;
static const unsigned int TLE2_LEN_RAASCENDNODE = 8;
static const unsigned int TLE2_COL_ECCENTRICITY = 26;
static const unsigned int TLE2_LEN_ECCENTRICITY = 7;
static const unsigned int TLE2_COL_ARGPERIGEE = 34;
static const unsigned int TLE2_LEN_ARGPERIGEE = 8;
static const unsigned int TLE2_COL_MEANANOMALY = 43;
static const unsigned int TLE2_LEN_MEANANOMALY = 8;
static const unsigned int TLE2_COL_MEANMOTION = 52;
static const unsigned int TLE2_LEN_MEANMOTION = 11;
static const unsigned int TLE2_COL_REVATEPOCH = 63;
static const unsigned int TLE2_LEN_REVATEPOCH = 5;
}
Tle::Tle(const Tle& tle)
{
name_ = tle.name_;
line_one_ = tle.line_one_;
line_two_ = tle.line_two_;
norad_number_ = tle.norad_number_;
international_designator_ = tle.international_designator_;
epoch_ = tle.epoch_;
mean_motion_dot_ = tle.mean_motion_dot_;
mean_motion_dot2_ = tle.mean_motion_dot2_;
bstar_ = tle.bstar_;
inclination_ = tle.inclination_;
right_ascending_node_ = tle.right_ascending_node_;
eccentricity_ = tle.eccentricity_;
argument_perigee_ = tle.argument_perigee_;
mean_anomaly_ = tle.mean_anomaly_;
mean_motion_ = tle.mean_motion_;
orbit_number_ = tle.orbit_number_;
}
/*
* convert a tle raw string into an exponent string
*/
std::string Tle::ExpToDecimal(const std::string& str)
{
static const int START_SIGN = 0;
static const int LENGTH_SIGN = 1;
static const int START_MANTISSA = 1;
static const int LENGTH_MANTISSA = 5;
static const int START_EXP = 6;
static const int LENGTH_EXP = 2;
if ((LENGTH_SIGN + LENGTH_MANTISSA + LENGTH_EXP) != str.length())
{
throw TleException("Invalid string length for exponential conversion.");
}
std::string value = str.substr(START_SIGN, LENGTH_SIGN);
value += ".";
value += str.substr(START_MANTISSA, LENGTH_MANTISSA);
value += "e";
value += str.substr(START_EXP, LENGTH_EXP);
return value;
}
/*
* extract all variables
*/
void Tle::Initialize()
{
std::string temp;
/*
* trim whitespace
*/
TrimLeft(name_);
TrimRight(name_);
TrimLeft(line_one_);
TrimRight(line_one_);
TrimLeft(line_two_);
TrimRight(line_two_);
/*
* check the two lines are valid
*/
IsValidPair(line_one_, line_two_);
/*
* line 1
*/
temp = ExtractNoradNumber(line_one_, 1);
norad_number_ = atoi(temp.c_str());
/*
* if blank use norad number for name
*/
if (name_.empty())
{
name_ = temp;
}
international_designator_ = line_one_.substr(TLE1_COL_INTLDESC_A,
TLE1_LEN_INTLDESC_A + TLE1_LEN_INTLDESC_B + TLE1_LEN_INTLDESC_C);
int year = atoi(line_one_.substr(TLE1_COL_EPOCH_A,
TLE1_LEN_EPOCH_A).c_str());
double day = atof(line_one_.substr(TLE1_COL_EPOCH_B,
TLE1_LEN_EPOCH_B).c_str());
/*
* generate julian date for epoch
*/
if (year < 57)
year += 2000;
else
year += 1900;
epoch_ = Julian(year, day);
if (line_one_[TLE1_COL_MEANMOTIONDT] == '-') {
temp = "-0";
} else
temp = "0";
temp += line_one_.substr(TLE1_COL_MEANMOTIONDT + 1, TLE1_LEN_MEANMOTIONDT);
mean_motion_dot_ = atof(temp.c_str());
temp = ExpToDecimal(line_one_.substr(TLE1_COL_MEANMOTIONDT2,
TLE1_LEN_MEANMOTIONDT2));
mean_motion_dot2_ = atof(temp.c_str());
temp = ExpToDecimal(line_one_.substr(TLE1_COL_BSTAR,
TLE1_LEN_BSTAR).c_str());
bstar_ = atof(temp.c_str());
/*
* line 2
*/
temp = line_two_.substr(TLE2_COL_INCLINATION, TLE2_LEN_INCLINATION);
TrimLeft(temp);
inclination_ = atof(temp.c_str());
temp = line_two_.substr(TLE2_COL_RAASCENDNODE, TLE2_LEN_RAASCENDNODE);
TrimLeft(temp);
right_ascending_node_ = atof(temp.c_str());
temp = "0.";
temp += line_two_.substr(TLE2_COL_ECCENTRICITY, TLE2_LEN_ECCENTRICITY);
eccentricity_ = atof(temp.c_str());
temp = line_two_.substr(TLE2_COL_ARGPERIGEE, TLE2_LEN_ARGPERIGEE);
TrimLeft(temp);
argument_perigee_ = atof(temp.c_str());
temp = line_two_.substr(TLE2_COL_MEANANOMALY, TLE2_LEN_MEANANOMALY);
TrimLeft(temp);
mean_anomaly_ = atof(temp.c_str());
temp = line_two_.substr(TLE2_COL_MEANMOTION, TLE2_LEN_MEANMOTION);
TrimLeft(temp);
mean_motion_ = atof(temp.c_str());
temp = line_two_.substr(TLE2_COL_REVATEPOCH, TLE2_LEN_REVATEPOCH);
TrimLeft(temp);
orbit_number_ = atoi(temp.c_str());
}
/*
* check the two lines have matching norad numbers
* and that the lines themselves are equal
*/
void Tle::IsValidPair(const std::string& line1, const std::string& line2)
{
/*
* validate each line
*/
IsValidLine(line1, 1);
IsValidLine(line2, 2);
/*
* extract norad numbers
*/
std::string norad_1 = ExtractNoradNumber(line1, 1);
std::string norad_2 = ExtractNoradNumber(line2, 2);
/*
* make sure they match
*/
if (norad_1.compare(norad_2) != 0)
{
throw TleException("Norad numbers do not match.");
}
}
/*
* validate a line
*/
void Tle::IsValidLine(const std::string& str, int line_number)
{
/*
* validation patterns
*/
static const std::string line1_pattern = "1 NNNNNC NNNNNXXX NNNNN.NNNNNNNN +.NNNNNNNN +NNNNN-N +NNNNN-N N NNNNN";
static const std::string line2_pattern = "2 NNNNN NNN.NNNN NNN.NNNN NNNNNNN NNN.NNNN NNN.NNNN NN.NNNNNNNNNNNNNN";
/*
* validate line against the pattern
*/
if (1 == line_number)
{
ValidateLine(str, line1_pattern);
}
else if (2 == line_number)
{
ValidateLine(str, line2_pattern);
}
else
{
throw TleException("Invalid line number to check.");
}
/*
* last char in string is modulo 10 checksum
* edited out as checksum isnt consistent
*
* int chk = CheckSum(str);
* if (chk != (str[TLE_LEN_LINE_DATA - 1] - '0'))
* return false;
*/
}
bool Tle::IsValidLineLength(const std::string& str)
{
return str.length() == GetLineLength() ? true : false;
}
/*
* validate line given a pattern
*/
void Tle::ValidateLine(const std::string& line, const std::string& pattern)
{
/*
* check length of line
*/
if (!IsValidLineLength(line))
{
throw TleException("Invalid line length.");
}
std::string::const_iterator pattern_itr = pattern.begin();
std::string::const_iterator line_itr = line.begin();
while (pattern_itr != pattern.end())
{
if (isdigit(*pattern_itr) || *pattern_itr == ' ' ||
*pattern_itr == '.')
{
/*
* should match exactly
*/
if (*pattern_itr != *line_itr)
{
throw TleException("Invalid character.");
}
}
else if (*pattern_itr == 'N')
{
/*
* 'N' = number or ' '
*/
if (!isdigit(*line_itr) && *line_itr != ' ')
{
throw TleException("Invalid character.");
}
}
else if (*pattern_itr == '+')
{
/*
* '+' = '+' or '-' or ' ' or '0'
*/
if (*line_itr != '+' && *line_itr != '-' &&
*line_itr != ' ' && *line_itr != '0')
{
throw TleException("Invalid character.");
}
}
else if (*pattern_itr == '-')
{
/*
* '-' = '+' or '-'
*/
if (*line_itr != '+' && *line_itr != '-')
{
throw TleException("Invalid character.");
}
}
else if (*pattern_itr == 'C')
{
/*
* 'C' = 'U' or 'S'
*/
if (*line_itr != 'U' && *line_itr != 'S')
{
throw TleException("Invalid character.");
}
}
else if (*pattern_itr == 'X')
{
/*
* 'X' = A-Z or ' '
*/
if (!(*line_itr >= 'A' || *line_itr <= 'Z') && *line_itr != ' ')
{
throw TleException("Invalid character.");
}
}
pattern_itr++;
line_itr++;
}
}
/*
* compute checksum
*/
int Tle::CheckSum(const std::string & str)
{
size_t len = str.size() - 1;
int xsum = 0;
for (size_t i = 0; i < len; i++)
{
char ch = str[i];
if (isdigit(ch))
{
xsum += (ch - '0');
}
else if (ch == '-')
{
xsum++;
}
}
return (xsum % 10);
}
std::string Tle::ExtractNoradNumber(const std::string& str, int line_number)
{
std::string norad_number;
/*
* check length
*/
if (!IsValidLineLength(str))
{
throw TleException("Invalid line length.");
}
/*
* extract string
*/
if (1 == line_number)
{
norad_number = str.substr(TLE1_COL_NORADNUM, TLE1_LEN_NORADNUM);
}
else if (2 == line_number)
{
norad_number = str.substr(TLE2_COL_NORADNUM, TLE2_LEN_NORADNUM);
}
else
{
throw TleException("Invalid line number to check.");
}
return norad_number;
}

430
Tle.h
View File

@ -1,215 +1,215 @@
#ifndef TLE_H_
#define TLE_H_
#include "Globals.h"
#include "Julian.h"
#include "TleException.h"
#include <iostream>
class Tle
{
public:
Tle(const std::string& line_one, const std::string& line_two)
: line_one_(line_one), line_two_(line_two)
{
Initialize();
}
Tle(const std::string& name, const std::string& line_one,
const std::string& line_two)
: name_(name),line_one_(line_one), line_two_(line_two)
{
Initialize();
}
Tle(const Tle& tle);
virtual ~Tle()
{
}
/*
* get raw strings
*/
std::string GetName() const
{
return name_;
}
std::string GetLine1() const
{
return line_one_;
}
std::string GetLine2() const
{
return line_two_;
}
/*
* get tle values
*/
unsigned int NoradNumber() const
{
return norad_number_;
}
std::string InternationlDesignator() const
{
return international_designator_;
}
Julian Epoch() const
{
return epoch_;
}
double MeanMotionDot() const
{
return mean_motion_dot_;
}
double MeanMotionDot2() const
{
return mean_motion_dot2_;
}
double BStar() const
{
return bstar_;
}
double Inclination(bool in_degrees) const
{
if (in_degrees)
{
return inclination_;
}
else
{
return DegreesToRadians(inclination_);
}
}
double RightAscendingNode(const bool in_degrees) const
{
if (in_degrees)
{
return right_ascending_node_;
}
else
{
return DegreesToRadians(right_ascending_node_);
}
}
double Eccentricity() const
{
return eccentricity_;
}
double ArgumentPerigee(const bool in_degrees) const
{
if (in_degrees)
{
return argument_perigee_;
}
else
{
return DegreesToRadians(argument_perigee_);
}
}
double MeanAnomaly(const bool in_degrees) const
{
if (in_degrees)
{
return mean_anomaly_;
}
else
{
return DegreesToRadians(mean_anomaly_);
}
}
double MeanMotion() const
{
return mean_motion_;
}
unsigned int OrbitNumber() const
{
return orbit_number_;
}
/*
* helper / validation methods
*/
static unsigned int GetLineLength()
{
return TLE_LEN_LINE_DATA;
}
static void IsValidPair(const std::string& line1, const std::string& line2);
static void IsValidLine(const std::string& str, int line_number);
private:
/*
* initialize from raw tle strings
*/
void Initialize();
/*
* format a raw string into an exponent string
*/
static std::string ExpToDecimal(const std::string&);
/*
* validate a line against a pattern
*/
static void ValidateLine(const std::string& line,
const std::string& pattern);
/*
* compute checksum
*/
static int CheckSum(const std::string& str);
static std::string ExtractNoradNumber(const std::string& str,
int line_number);
static bool IsValidLineLength(const std::string& str);
private:
/*
* raw tle data
*/
std::string name_;
std::string line_one_;
std::string line_two_;
/*
* extracted values all in native units
*/
unsigned int norad_number_;
std::string international_designator_;
Julian epoch_;
double mean_motion_dot_;
double mean_motion_dot2_;
double bstar_;
double inclination_;
double right_ascending_node_;
double eccentricity_;
double argument_perigee_;
double mean_anomaly_;
double mean_motion_;
unsigned int orbit_number_;
/*
* line lengths
*/
static const unsigned int TLE_LEN_LINE_DATA = 69;
static const unsigned int TLE_LEN_LINE_NAME = 22;
};
#endif
#ifndef TLE_H_
#define TLE_H_
#include "Globals.h"
#include "Julian.h"
#include "TleException.h"
#include <iostream>
class Tle
{
public:
Tle(const std::string& line_one, const std::string& line_two)
: line_one_(line_one), line_two_(line_two)
{
Initialize();
}
Tle(const std::string& name, const std::string& line_one,
const std::string& line_two)
: name_(name),line_one_(line_one), line_two_(line_two)
{
Initialize();
}
Tle(const Tle& tle);
virtual ~Tle()
{
}
/*
* get raw strings
*/
std::string GetName() const
{
return name_;
}
std::string GetLine1() const
{
return line_one_;
}
std::string GetLine2() const
{
return line_two_;
}
/*
* get tle values
*/
unsigned int NoradNumber() const
{
return norad_number_;
}
std::string InternationlDesignator() const
{
return international_designator_;
}
Julian Epoch() const
{
return epoch_;
}
double MeanMotionDot() const
{
return mean_motion_dot_;
}
double MeanMotionDot2() const
{
return mean_motion_dot2_;
}
double BStar() const
{
return bstar_;
}
double Inclination(bool in_degrees) const
{
if (in_degrees)
{
return inclination_;
}
else
{
return DegreesToRadians(inclination_);
}
}
double RightAscendingNode(const bool in_degrees) const
{
if (in_degrees)
{
return right_ascending_node_;
}
else
{
return DegreesToRadians(right_ascending_node_);
}
}
double Eccentricity() const
{
return eccentricity_;
}
double ArgumentPerigee(const bool in_degrees) const
{
if (in_degrees)
{
return argument_perigee_;
}
else
{
return DegreesToRadians(argument_perigee_);
}
}
double MeanAnomaly(const bool in_degrees) const
{
if (in_degrees)
{
return mean_anomaly_;
}
else
{
return DegreesToRadians(mean_anomaly_);
}
}
double MeanMotion() const
{
return mean_motion_;
}
unsigned int OrbitNumber() const
{
return orbit_number_;
}
/*
* helper / validation methods
*/
static unsigned int GetLineLength()
{
return TLE_LEN_LINE_DATA;
}
static void IsValidPair(const std::string& line1, const std::string& line2);
static void IsValidLine(const std::string& str, int line_number);
private:
/*
* initialize from raw tle strings
*/
void Initialize();
/*
* format a raw string into an exponent string
*/
static std::string ExpToDecimal(const std::string&);
/*
* validate a line against a pattern
*/
static void ValidateLine(const std::string& line,
const std::string& pattern);
/*
* compute checksum
*/
static int CheckSum(const std::string& str);
static std::string ExtractNoradNumber(const std::string& str,
int line_number);
static bool IsValidLineLength(const std::string& str);
private:
/*
* raw tle data
*/
std::string name_;
std::string line_one_;
std::string line_two_;
/*
* extracted values all in native units
*/
unsigned int norad_number_;
std::string international_designator_;
Julian epoch_;
double mean_motion_dot_;
double mean_motion_dot2_;
double bstar_;
double inclination_;
double right_ascending_node_;
double eccentricity_;
double argument_perigee_;
double mean_anomaly_;
double mean_motion_;
unsigned int orbit_number_;
/*
* line lengths
*/
static const unsigned int TLE_LEN_LINE_DATA = 69;
static const unsigned int TLE_LEN_LINE_NAME = 22;
};
#endif

View File

@ -1,29 +1,29 @@
#ifndef TLEEXCEPTION_H_
#define TLEEXCEPTION_H_
#include <exception>
#include <iostream>
class TleException : public std::exception
{
public:
TleException(const char* message)
: message_(message)
{
}
virtual ~TleException(void) throw ()
{
}
virtual const char* what() const throw ()
{
return message_.c_str();
}
private:
std::string message_;
};
#endif
#ifndef TLEEXCEPTION_H_
#define TLEEXCEPTION_H_
#include <exception>
#include <iostream>
class TleException : public std::exception
{
public:
TleException(const char* message)
: message_(message)
{
}
virtual ~TleException(void) throw ()
{
}
virtual const char* what() const throw ()
{
return message_.c_str();
}
private:
std::string message_;
};
#endif

196
Vector.h
View File

@ -1,98 +1,98 @@
#ifndef VECTOR_H_
#define VECTOR_H_
#include <cmath>
#include <string>
#include <sstream>
#include <iomanip>
struct Vector
{
public:
Vector()
: x(0.0), y(0.0), z(0.0), w(0.0)
{
}
Vector(double xx, double yy, double zz)
: x(xx), y(yy), z(zz), w(0.0)
{
}
Vector(double xx, double yy, double zz, double ww)
: x(xx), y(yy), z(zz), w(ww)
{
}
Vector(const Vector& v)
{
x = v.x;
y = v.y;
z = v.z;
w = v.w;
}
virtual ~Vector()
{
}
Vector& operator=(const Vector& v)
{
if (this != &v)
{
x = v.x;
y = v.y;
z = v.z;
w = v.w;
}
return *this;
}
double GetMagnitude() const
{
return sqrt(x * x + y * y + z * z);
}
Vector Subtract(const Vector& v) const
{
/*
* subtract (this) - (v)
* and return result
*/
return Vector(x - v.x,
y - v.y,
z - v.z,
0.0);
}
double Dot(const Vector& vec) const
{
return (x * vec.x) +
(y * vec.y) +
(z * vec.z);
}
std::string ToString() const
{
std::stringstream ss;
ss << std::right << std::fixed << std::setprecision(2);
ss << "X: " << std::setw(8) << x;
ss << ", Y: " << std::setw(8) << y;
ss << ", Z: " << std::setw(8) << z;
ss << ", W: " << std::setw(8) << w;
return ss.str();
}
double x;
double y;
double z;
double w;
};
inline std::ostream& operator<<(std::ostream& strm, const Vector& v)
{
return strm << v.ToString();
}
#endif
#ifndef VECTOR_H_
#define VECTOR_H_
#include <cmath>
#include <string>
#include <sstream>
#include <iomanip>
struct Vector
{
public:
Vector()
: x(0.0), y(0.0), z(0.0), w(0.0)
{
}
Vector(double xx, double yy, double zz)
: x(xx), y(yy), z(zz), w(0.0)
{
}
Vector(double xx, double yy, double zz, double ww)
: x(xx), y(yy), z(zz), w(ww)
{
}
Vector(const Vector& v)
{
x = v.x;
y = v.y;
z = v.z;
w = v.w;
}
virtual ~Vector()
{
}
Vector& operator=(const Vector& v)
{
if (this != &v)
{
x = v.x;
y = v.y;
z = v.z;
w = v.w;
}
return *this;
}
double GetMagnitude() const
{
return sqrt(x * x + y * y + z * z);
}
Vector Subtract(const Vector& v) const
{
/*
* subtract (this) - (v)
* and return result
*/
return Vector(x - v.x,
y - v.y,
z - v.z,
0.0);
}
double Dot(const Vector& vec) const
{
return (x * vec.x) +
(y * vec.y) +
(z * vec.z);
}
std::string ToString() const
{
std::stringstream ss;
ss << std::right << std::fixed << std::setprecision(2);
ss << "X: " << std::setw(8) << x;
ss << ", Y: " << std::setw(8) << y;
ss << ", Z: " << std::setw(8) << z;
ss << ", W: " << std::setw(8) << w;
return ss.str();
}
double x;
double y;
double z;
double w;
};
inline std::ostream& operator<<(std::ostream& strm, const Vector& v)
{
return strm << v.ToString();
}
#endif