// // cSite.cpp // // Copyright (c) 2003 Michael F. Henry // ////////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "cSite.h" #include "globals.h" ////////////////////////////////////////////////////////////////////////////// // Construction/Destruction cSite::cSite(const cCoordGeo &geo) : m_geo(geo) {} ////////////////////////////////////////////////////////////////////////////// // c'tor accepting: // Latitude in degress (negative south) // Longitude in degress (negative west) // Altitude in km cSite::cSite(double degLat, double degLon, double kmAlt) : m_geo(deg2rad(degLat), deg2rad(degLon), kmAlt) {} cSite::~cSite() {} ////////////////////////////////////////////////////////////////////////////// // setGeo() // Set a new geographic position void cSite::setGeo(const cCoordGeo &geo) { m_geo = geo; } ////////////////////////////////////////////////////////////////////////////// // getPosition() // Return the ECI coordinate of the site at the given time. cEci cSite::getPosition(const cJulian &date) const { return cEci(m_geo, date); } ////////////////////////////////////////////////////////////////////////////// // getLookAngle() // Return the topocentric (azimuth, elevation, etc.) coordinates for a target // object described by the input ECI coordinates. cCoordTopo cSite::getLookAngle(const cEci &eci) const { // Calculate the ECI coordinates for this cSite object at the time // of interest. cJulian date = eci.getDate(); cEci eciSite(m_geo, date); // The Site ECI units are km-based; ensure target ECI units are same assert(eci.UnitsAreKm()); cVector vecRgRate(eci.getVel().m_x - eciSite.getVel().m_x, eci.getVel().m_y - eciSite.getVel().m_y, eci.getVel().m_z - eciSite.getVel().m_z); double x = eci.getPos().m_x - eciSite.getPos().m_x; double y = eci.getPos().m_y - eciSite.getPos().m_y; double z = eci.getPos().m_z - eciSite.getPos().m_z; double w = sqrt(sqr(x) + sqr(y) + sqr(z)); cVector vecRange(x, y, z, w); // The site's Local Mean Sidereal Time at the time of interest. double theta = date.toLMST(getLon()); double sin_lat = sin(getLat()); double cos_lat = cos(getLat()); double sin_theta = sin(theta); double cos_theta = cos(theta); double top_s = sin_lat * cos_theta * vecRange.m_x + sin_lat * sin_theta * vecRange.m_y - cos_lat * vecRange.m_z; double top_e = -sin_theta * vecRange.m_x + cos_theta * vecRange.m_y; double top_z = cos_lat * cos_theta * vecRange.m_x + cos_lat * sin_theta * vecRange.m_y + sin_lat * vecRange.m_z; double az = atan(-top_e / top_s); if (top_s > 0.0) az += PI; if (az < 0.0) az += 2.0*PI; double el = asin(top_z / vecRange.m_w); double rate = (vecRange.m_x * vecRgRate.m_x + vecRange.m_y * vecRgRate.m_y + vecRange.m_z * vecRgRate.m_z) / vecRange.m_w; cCoordTopo topo(az, // azimuth, radians el, // elevation, radians vecRange.m_w, // range, km rate); // rate, km / sec #ifdef WANT_ATMOSPHERIC_CORRECTION // Elevation correction for atmospheric refraction. // Reference: Astronomical Algorithms by Jean Meeus, pp. 101-104 // Note: Correction is meaningless when apparent elevation is below horizon topo.m_El += deg2rad((1.02 / tan(deg2rad(rad2deg(el) + 10.3 / (rad2deg(el) + 5.11)))) / 60.0); if (topo.m_El < 0.0) topo.m_El = el; // Reset to true elevation if (topo.m_El > (PI / 2)) topo.m_El = (PI / 2); #endif return topo; } ////////////////////////////////////////////////////////////////////////////// // toString() // string cSite::toString() const { const int TEMP_SIZE = 128; char sz[TEMP_SIZE]; bool LatNorth = true; bool LonEast = true; if (m_geo.m_Lat < 0.0) { LatNorth = false; } if (m_geo.m_Lon < 0.0) { LonEast = false; } snprintf(sz, TEMP_SIZE, "%06.3f%c, ", fabs(rad2deg(m_geo.m_Lat)), (LatNorth ? 'N' : 'S')); string strLoc = sz; snprintf(sz, TEMP_SIZE, "%07.3f%c, ", fabs(rad2deg(m_geo.m_Lon)), (LonEast ? 'E' : 'W')); strLoc += sz; snprintf(sz, TEMP_SIZE, "%.1fm\n", (m_geo.m_Alt * 1000.0)); strLoc += sz; return strLoc; }