/// <summary> /// Creates a instance of the class from geodetic coordinates. /// </summary> /// <param name="geo">The geocentric coordinates.</param> /// <param name="date">The Julian date.</param> /// <remarks> /// Assumes the Earth is an oblate spheroid. /// Reference: The 1992 Astronomical Almanac, page K11 /// Reference: www.celestrak.com (Dr. T.S. Kelso) /// </remarks> public Eci(Geo geo, Julian date) { double lat = geo.LatitudeRad; double lon = geo.LongitudeRad; double alt = geo.Altitude; // Calculate Local Mean Sidereal Time (theta) double theta = date.ToLmst(lon); double c = 1.0 / Math.Sqrt(1.0 + Globals.F * (Globals.F - 2.0) * Globals.Sqr(Math.Sin(lat))); double s = Globals.Sqr(1.0 - Globals.F) * c; double achcp = (Globals.Xkmper * c + alt) * Math.Cos(lat); Position = new Vector(); Position.X = achcp * Math.Cos(theta); // km Position.Y = achcp * Math.Sin(theta); // km Position.Z = (Globals.Xkmper * s + alt) * Math.Sin(lat); // km Position.W = Math.Sqrt(Globals.Sqr(Position.X) + Globals.Sqr(Position.Y) + Globals.Sqr(Position.Z)); // range, km Velocity = new Vector(); double mfactor = Globals.TwoPi * (Globals.OmegaE / Globals.SecPerDay); Velocity.X = -mfactor * Position.Y; // km / sec Velocity.Y = mfactor * Position.X; // km / sec Velocity.Z = 0.0; // km / sec Velocity.W = Math.Sqrt(Globals.Sqr(Velocity.X) + // range rate km/sec^2 Globals.Sqr(Velocity.Y)); }
/// <summary> /// Creates a instance of the class from geodetic coordinates. /// </summary> /// <param name="geo">The geocentric coordinates.</param> /// <param name="date">The Julian date.</param> /// <remarks> /// Assumes the Earth is an oblate spheroid. /// Reference: The 1992 Astronomical Almanac, page K11 /// Reference: www.celestrak.com (Dr. T.S. Kelso) /// </remarks> public Eci(Geo geo, Julian date) { double lat = geo.LatitudeRad; double lon = geo.LongitudeRad; double alt = geo.Altitude; // Calculate Local Mean Sidereal Time (theta) double theta = date.ToLmst(lon); double c = 1.0 / Math.Sqrt(1.0 + Globals.F * (Globals.F - 2.0) * Globals.Sqr(Math.Sin(lat))); double s = Globals.Sqr(1.0 - Globals.F) * c; double achcp = (Globals.Xkmper * c + alt) * Math.Cos(lat); Position = new Vector(); Position.X = achcp * Math.Cos(theta); // km Position.Y = achcp * Math.Sin(theta); // km Position.Z = (Globals.Xkmper * s + alt) * Math.Sin(lat); // km Position.W = Math.Sqrt(Globals.Sqr(Position.X) + Globals.Sqr(Position.Y) + Globals.Sqr(Position.Z)); // range, km Velocity = new Vector(); double mfactor = Globals.TwoPi * (Globals.OmegaE / Globals.SecPerDay); Velocity.X = -mfactor * Position.Y; // km / sec Velocity.Y = mfactor * Position.X; // km / sec Velocity.Z = 0.0; // km / sec Velocity.W = Math.Sqrt(Globals.Sqr(Velocity.X) + // range rate km/sec^2 Globals.Sqr(Velocity.Y)); }
/// <summary> /// Returns the topo-centric (azimuth, elevation, etc.) coordinates for /// a target object described by the given ECI coordinates. /// </summary> /// <param name="eci">The ECI coordinates of the target object.</param> /// <returns>The look angle to the target object.</returns> public TopoTime GetLookAngle(EciTime eci) { // Calculate the ECI coordinates for this Site object at the time // of interest. Julian date = eci.Date; EciTime eciSite = PositionEci(date); Vector vecRgRate = new Vector(eci.Velocity.X - eciSite.Velocity.X, eci.Velocity.Y - eciSite.Velocity.Y, eci.Velocity.Z - eciSite.Velocity.Z); double x = eci.Position.X - eciSite.Position.X; double y = eci.Position.Y - eciSite.Position.Y; double z = eci.Position.Z - eciSite.Position.Z; double w = Math.Sqrt(Globals.Sqr(x) + Globals.Sqr(y) + Globals.Sqr(z)); Vector vecRange = new Vector(x, y, z, w); // The site's Local Mean Sidereal Time at the time of interest. double theta = date.ToLmst(LongitudeRad); double sin_lat = Math.Sin(LatitudeRad); double cos_lat = Math.Cos(LatitudeRad); double sin_theta = Math.Sin(theta); double cos_theta = Math.Cos(theta); double top_s = sin_lat * cos_theta * vecRange.X + sin_lat * sin_theta * vecRange.Y - cos_lat * vecRange.Z; double top_e = -sin_theta * vecRange.X + cos_theta * vecRange.Y; double top_z = cos_lat * cos_theta * vecRange.X + cos_lat * sin_theta * vecRange.Y + sin_lat * vecRange.Z; double az = Math.Atan(-top_e / top_s); if (top_s > 0.0) { az += Globals.Pi; } if (az < 0.0) { az += 2.0 * Globals.Pi; } double el = Math.Asin(top_z / vecRange.W); double rate = (vecRange.X * vecRgRate.X + vecRange.Y * vecRgRate.Y + vecRange.Z * vecRgRate.Z) / vecRange.W; TopoTime topo = new TopoTime(az, // azimuth, radians el, // elevation, radians vecRange.W, // range, km rate, // rate, km / sec eci.Date); #if 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.ElevationRad += Globals.ToRadians((1.02 / Math.Tan(Globals.ToRadians(Globals.ToDegrees(el) + 10.3 / (Globals.ToDegrees(el) + 5.11)))) / 60.0); if (topo.ElevationRad < 0.0) { topo.ElevationRad = el; // Reset to true elevation } if (topo.ElevationRad > (Math.PI / 2.0)) { topo.ElevationRad = (Math.PI / 2.0); } #endif return(topo); }