using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ScoutBase.Core;
namespace ScoutBase.Core
{
public static class Propagation
{
///
/// Returns the angle Alpha between an observer at 0° and an object in a given distance on Earth's surface seen from the Earth's midpoint
///
/// The distance of the object [km].
/// The equivalent earth radius [km].
/// The angle Alpha [rad].
public static double AlphaFromDistance(double dist, double re)
{
return dist / re;
}
///
/// Returns the slant range of an object at (h)eight of observer, position of observer (mylat, mylon), position of object (lat, lon), (H))eight of object is seen from an observer
///
/// The height of the observer [m].
/// The latitude of the observer [deg].
/// The longitude of the observer [deg].
/// The latitude of the object [deg].
/// The longitude of the object [deg].
/// The height of the object [m].
/// The equivalent earth radius [km].
/// The slant range in [km].
public static double SlantRangeFromHeights(double h, double mylat, double mylon, double lat, double lon, double H, double radius)
{
return SlantRangeFromHeights(h, LatLon.Distance(mylat, mylon, lat, lon), H, radius);
}
///
/// Returns the slant range of an object at (h)eight of observer, (dist)ance to object, (H))eight of object is seen from an observer
///
/// The height of the observer [m].
/// The distance of the object [km].
/// The height of the object [m].
/// The equivalent earth radius [km].
/// The slant range in [km].
public static double SlantRangeFromHeights(double h, double dist, double H, double radius)
{
// convert heights into [km]
h = h / 1000.0;
H = H / 1000.0;
// calculate alpha angle in [rad]
double alpha = AlphaFromDistance(dist, radius);
// double d = Math.Sqrt((radius + h) * (radius + h) + (radius + H) * (radius + H) - 2.0 * (radius + h) * (radius + H) * Math.Cos(alpha));
double d = Math.Sqrt((radius + H) * (radius + H) + (radius + h) * (radius + h) - (2.0 * (radius + H) * (radius + h) * Math.Cos(alpha)));
return d;
}
///
/// Returns the elevation angle Epsilon an object at (h)eight of observer, (dist)ance to object, (H))eight of object is seen from an observer
///
/// The height of the observer [m].
/// The distance of the object [km].
/// The height of the object [m].
/// The equivalent earth radius [km].
/// The elevation angle Epsilon [rad].
public static double EpsilonFromHeights(double h, double dist, double H, double radius)
{
// calculate alpha angle in [rad]
double alpha = dist / radius;
double d = SlantRangeFromHeights(h, dist, H, radius);
// convert heights into [km]
h = h / 1000.0;
H = H / 1000.0;
double a = ((radius + H) * (radius + H) - (radius + h) * (radius + h) - d * d) / 2.0 / d;
double eps = Math.Asin(a / (radius + h));
return eps;
}
///
/// Returns the angle a wavefront sent by an observer at (h) will meet an object at (bearing, distance, H) based on the object's horizontal line
///
/// The height of the observer [m].
/// The distance of the object [km].
/// The height of the object [m].
/// The equivalent earth radius [km].
/// The angle Theta [rad].
public static double ThetaFromHeights(double h, double dist, double H, double radius)
{
// convert heights into [km]
h = h / 1000.0;
H = H / 1000.0;
// calculate alpha angle in [rad]
double alpha = AlphaFromDistance(dist, radius);
double d = Math.Sqrt((radius + h) * (radius + h) + (radius + H) * (radius + H) - 2.0 * (radius + h) * (radius + H) * Math.Cos(alpha));
double a = ((radius + H) * (radius + H) - (radius + h) * (radius + h) - d * d) / 2.0 / d;
return Math.Asin((a + d) / (radius + H));
}
///
/// Returns the height of an object at a given distance (dist) an observer(h) would see at an angle Epsilon (eps)
///
/// The height of the observer [m].
/// The distance of the object [km].
/// The angle Epsilon [rad].
/// The equivalent earth radius [km].
/// The height of the object [m].
public static double HeightFromEpsilon(double h, double dist, double eps, double radius)
{
// convert heights into [km]
h = h / 1000.0;
double beta = Math.PI / 2.0 + eps;
double gamma = Math.PI - AlphaFromDistance(dist, radius) - beta;
return ((radius + h) * Math.Sin(beta) / Math.Sin(gamma) - radius) * 1000;
}
///
/// Returns the maximum distance an object can have at a given Height (H) to be still visible to an observer(h) at an angle Epsilon (eps)
///
/// The height of the observer [m].
/// The height of the object [m].
/// The angle Epsilon [rad].
/// The equivalent earth radius [km].
/// The distance of the object [km].
public static double DistanceFromEpsilon(double h, double H, double eps, double radius)
{
// convert heights into [km]
h = h / 1000.0;
H = H / 1000.0;
double beta = Math.PI / 2.0 + eps;
double gamma = Math.Asin((radius + h) / (radius + H) * Math.Sin(beta));
double alpha = Math.PI - beta - gamma;
return alpha * radius;
}
///
/// Returns the radius of the F1 Fresnel Zone
///
/// The frequency in [GHz].
/// The distance from one end [km].
/// The distance from the other end [km].
/// The radius of the F1 Fresnel Zone in [m].
public static double F1Radius(double qrg, double dist1, double dist2)
{
return Math.Sqrt(300.0 / qrg * dist1 * dist2 / (dist1 + dist2));
}
///
/// Returns the maximum distance an object (h2) can have to be seen from an observer (h1) --> visiblity distance
///
/// The height of the observer [m].
/// The height of the object [m].
/// The equivalent earth radius [km].
/// The visibility distance in [km].
public static double VisibilityDistance(double h1, double h2, double re)
{
// convert heights into [km]
h1 = h1 / 1000.0;
h2 = h2 / 1000.0;
return Math.Sqrt(2 * re) * (Math.Sqrt(h1) + Math.Sqrt(h2));
}
///
/// Returns the Doppler shift of a moving object in relation to an observer
///
/// The frequency in [Hz].
/// The resulting speed [m/s] - positive when moving away, negative when moving towards.
/// The resulting doppler shift [Hz].
public static double DopplerShift(double qrg, double speed)
{
double c = 300000000.0; // light speed in m/s
return qrg - qrg * c / (c + speed);
}
}
}