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); } } }