1 |
//
|
2 |
// cSite.cpp
|
3 |
//
|
4 |
// Copyright (c) 2003 Michael F. Henry
|
5 |
//
|
6 |
//////////////////////////////////////////////////////////////////////////////
|
7 |
#include "stdafx.h"
|
8 |
#include "cSite.h"
|
9 |
#include "globals.h"
|
10 |
|
11 |
//////////////////////////////////////////////////////////////////////////////
|
12 |
// Construction/Destruction
|
13 |
cSite::cSite(const cCoordGeo &geo) : m_geo(geo)
|
14 |
{}
|
15 |
|
16 |
//////////////////////////////////////////////////////////////////////////////
|
17 |
// c'tor accepting:
|
18 |
// Latitude in degress (negative south)
|
19 |
// Longitude in degress (negative west)
|
20 |
// Altitude in km
|
21 |
cSite::cSite(double degLat, double degLon, double kmAlt) :
|
22 |
m_geo(deg2rad(degLat), deg2rad(degLon), kmAlt)
|
23 |
{}
|
24 |
|
25 |
cSite::~cSite()
|
26 |
{}
|
27 |
|
28 |
//////////////////////////////////////////////////////////////////////////////
|
29 |
// setGeo()
|
30 |
// Set a new geographic position
|
31 |
void cSite::setGeo(const cCoordGeo &geo)
|
32 |
{
|
33 |
m_geo = geo;
|
34 |
}
|
35 |
|
36 |
//////////////////////////////////////////////////////////////////////////////
|
37 |
// getPosition()
|
38 |
// Return the ECI coordinate of the site at the given time.
|
39 |
cEci cSite::getPosition(const cJulian &date) const
|
40 |
{
|
41 |
return cEci(m_geo, date);
|
42 |
}
|
43 |
|
44 |
//////////////////////////////////////////////////////////////////////////////
|
45 |
// getLookAngle()
|
46 |
// Return the topocentric (azimuth, elevation, etc.) coordinates for a target
|
47 |
// object described by the input ECI coordinates.
|
48 |
cCoordTopo cSite::getLookAngle(const cEci &eci) const
|
49 |
{
|
50 |
// Calculate the ECI coordinates for this cSite object at the time
|
51 |
// of interest.
|
52 |
cJulian date = eci.getDate();
|
53 |
cEci eciSite(m_geo, date);
|
54 |
|
55 |
// The Site ECI units are km-based; ensure target ECI units are same
|
56 |
assert(eci.UnitsAreKm());
|
57 |
|
58 |
cVector vecRgRate(eci.getVel().m_x - eciSite.getVel().m_x,
|
59 |
eci.getVel().m_y - eciSite.getVel().m_y,
|
60 |
eci.getVel().m_z - eciSite.getVel().m_z);
|
61 |
|
62 |
double x = eci.getPos().m_x - eciSite.getPos().m_x;
|
63 |
double y = eci.getPos().m_y - eciSite.getPos().m_y;
|
64 |
double z = eci.getPos().m_z - eciSite.getPos().m_z;
|
65 |
double w = sqrt(sqr(x) + sqr(y) + sqr(z));
|
66 |
|
67 |
cVector vecRange(x, y, z, w);
|
68 |
|
69 |
// The site's Local Mean Sidereal Time at the time of interest.
|
70 |
double theta = date.toLMST(getLon());
|
71 |
|
72 |
double sin_lat = sin(getLat());
|
73 |
double cos_lat = cos(getLat());
|
74 |
double sin_theta = sin(theta);
|
75 |
double cos_theta = cos(theta);
|
76 |
|
77 |
double top_s = sin_lat * cos_theta * vecRange.m_x +
|
78 |
sin_lat * sin_theta * vecRange.m_y -
|
79 |
cos_lat * vecRange.m_z;
|
80 |
double top_e = -sin_theta * vecRange.m_x +
|
81 |
cos_theta * vecRange.m_y;
|
82 |
double top_z = cos_lat * cos_theta * vecRange.m_x +
|
83 |
cos_lat * sin_theta * vecRange.m_y +
|
84 |
sin_lat * vecRange.m_z;
|
85 |
double az = atan(-top_e / top_s);
|
86 |
|
87 |
if (top_s > 0.0)
|
88 |
az += PI;
|
89 |
|
90 |
if (az < 0.0)
|
91 |
az += 2.0*PI;
|
92 |
|
93 |
double el = asin(top_z / vecRange.m_w);
|
94 |
double rate = (vecRange.m_x * vecRgRate.m_x +
|
95 |
vecRange.m_y * vecRgRate.m_y +
|
96 |
vecRange.m_z * vecRgRate.m_z) / vecRange.m_w;
|
97 |
|
98 |
cCoordTopo topo(az, // azimuth, radians
|
99 |
el, // elevation, radians
|
100 |
vecRange.m_w, // range, km
|
101 |
rate); // rate, km / sec
|
102 |
|
103 |
#ifdef WANT_ATMOSPHERIC_CORRECTION
|
104 |
// Elevation correction for atmospheric refraction.
|
105 |
// Reference: Astronomical Algorithms by Jean Meeus, pp. 101-104
|
106 |
// Note: Correction is meaningless when apparent elevation is below horizon
|
107 |
topo.m_El += deg2rad((1.02 /
|
108 |
tan(deg2rad(rad2deg(el) + 10.3 /
|
109 |
(rad2deg(el) + 5.11)))) / 60.0);
|
110 |
if (topo.m_El < 0.0)
|
111 |
topo.m_El = el; // Reset to true elevation
|
112 |
|
113 |
if (topo.m_El > (PI / 2))
|
114 |
topo.m_El = (PI / 2);
|
115 |
#endif
|
116 |
|
117 |
return topo;
|
118 |
}
|
119 |
|
120 |
//////////////////////////////////////////////////////////////////////////////
|
121 |
// toString()
|
122 |
//
|
123 |
string cSite::toString() const
|
124 |
{
|
125 |
const int TEMP_SIZE = 128;
|
126 |
char sz[TEMP_SIZE];
|
127 |
|
128 |
bool LatNorth = true;
|
129 |
bool LonEast = true;
|
130 |
|
131 |
if (m_geo.m_Lat < 0.0)
|
132 |
{
|
133 |
LatNorth = false;
|
134 |
}
|
135 |
|
136 |
if (m_geo.m_Lon < 0.0)
|
137 |
{
|
138 |
LonEast = false;
|
139 |
}
|
140 |
|
141 |
snprintf(sz, TEMP_SIZE,
|
142 |
"%06.3f%c, ",
|
143 |
fabs(rad2deg(m_geo.m_Lat)),
|
144 |
(LatNorth ? 'N' : 'S'));
|
145 |
|
146 |
string strLoc = sz;
|
147 |
|
148 |
snprintf(sz, TEMP_SIZE,
|
149 |
"%07.3f%c, ",
|
150 |
fabs(rad2deg(m_geo.m_Lon)),
|
151 |
(LonEast ? 'E' : 'W'));
|
152 |
strLoc += sz;
|
153 |
|
154 |
snprintf(sz, TEMP_SIZE,
|
155 |
"%.1fm\n",
|
156 |
(m_geo.m_Alt * 1000.0));
|
157 |
strLoc += sz;
|
158 |
|
159 |
return strLoc;
|
160 |
}
|
161 |
|