PhysicsHelper.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. using System;
  2. using System.IO;
  3. using System.Security.Cryptography;
  4. using static System.Math;
  5. /// <summary>
  6. /// 物理公式帮助类
  7. /// </summary>
  8. public static class PhysicsHelper
  9. {
  10. readonly static double PI = Math.PI;//圆周率
  11. public readonly static double C = 299792458.458;//光速 m/s
  12. ///// <summary>
  13. ///// 地球半径(m)
  14. ///// </summary>
  15. //public static double R = 6378.1414 * 1000; //地球半径(m)
  16. /// <summary>
  17. /// GEO转ECEF地心地固坐标
  18. /// </summary>
  19. /// <param name="geo">经纬高(m)三元组</param>
  20. /// <returns>返回x、y、z三元组,单位m</returns>
  21. public static (double x, double y, double z) GeoToEcef((double, double, double) geo)
  22. {
  23. var (lon, lat, alt) = geo;
  24. var c45 = 180 / PI;
  25. //double lr = 6378137;//地球长半轴
  26. //double sr = 6356752.3142;//地球短半轴
  27. double lr = 6378136.49;//地球长半轴
  28. double sr = 6356755.00;//地球短半轴
  29. var e2 = (lr + sr) * (lr - sr) / lr / lr;
  30. var lonArc = lon / c45;//弧度
  31. var latArc = lat / c45;//弧度
  32. var r = lr / Sqrt(1 - e2 * Pow(Sin(latArc), 2));//地球曲率半径
  33. double x = (r + alt) * Cos(latArc) * Cos(lonArc);
  34. double y = (r + alt) * Cos(latArc) * Sin(lonArc);
  35. double z = (r * (1 - e2) + alt) * Sin(latArc);
  36. return (x, y, z);
  37. }
  38. //public static (double x, double y, double z) GeoToEcef((double, double, double) geo)
  39. //{
  40. // /*
  41. // R=6378.1414;
  42. // p=p/180*pi;
  43. // q=q/180*pi;
  44. // r=[R*cos(q)*cos(p) R*cos(q)*sin(p) R*sin(q)];
  45. // * */
  46. // //double r = 6378.1414; //地球半径(Km)
  47. // var (lon, lat, alt) = geo;
  48. // double p = lon * Math.PI / 180;
  49. // double q = lat * Math.PI / 180;
  50. // var x = R * Math.Cos(q) * Math.Cos(p);
  51. // var y= R * Math.Cos(q) * Math.Sin(p);
  52. // var z = R * Math.Sin(q);
  53. // return (x,y,z);
  54. //}
  55. /// <summary>
  56. /// ECEF转GEO
  57. /// </summary>
  58. /// <param name="ecef">ECEF地心地固坐标x、y、z三元组</param>
  59. /// <returns>返回经度(°)、纬度(°)、高度(m)三元组</returns>
  60. public static (double lon, double lat, double alt) EcefToGeo((double, double, double) ecef)
  61. {
  62. var (x, y, z) = ecef;
  63. double lr = 6378137;//地球长半轴
  64. double sr = 6356752.3142;//地球短半轴
  65. var e2 = (lr + sr) * (lr - sr) / (double)lr / lr;//轨道第一偏心率平方
  66. double B0 = Atan2(z, Sqrt(x * x + y * y));
  67. double N;//卯酉圈曲率半径
  68. double lon = Atan2(y, x);
  69. double lat, alt;
  70. lon *= (180 / PI);
  71. while (true)//纬度度多次逼近
  72. {
  73. N = lr / Sqrt(1 - e2 * Sin(B0) * Sin(B0));
  74. lat = Atan2(z + N * e2 * Sin(B0), Sqrt(x * x + y * y));
  75. if (Abs(B0 - lat) < 1e-6) break;
  76. B0 = lat;
  77. }
  78. alt = Sqrt(x * x + y * y) / Cos(lat) - N;
  79. lat *= (180 / PI);
  80. return (lon, lat, alt);
  81. }
  82. /// <summary>
  83. /// 求ECEF坐标系下两个点的直线距离(单位:m)
  84. /// </summary>
  85. /// <param name="ecef1">ECEF地心地固坐标1,x、y、z三元组</param>
  86. /// <param name="ecef2">ECEF地心地固坐标2,x、y、z三元组</param>
  87. /// <returns>返回距离,单位m</returns>
  88. public static double DistanceEcf((double, double, double) ecef1, (double, double, double) ecef2)
  89. {
  90. double xr = ecef1.Item1 - ecef2.Item1;
  91. double yr = ecef1.Item2 - ecef2.Item2;
  92. double zr = ecef1.Item3 - ecef2.Item3;
  93. double xr2 = xr * xr;
  94. double yr2 = yr * yr;
  95. double zr2 = zr * zr;
  96. double s = xr2 + yr2 + zr2;
  97. double distanse = Sqrt(s);
  98. return distanse;
  99. }
  100. /// <summary>
  101. /// <para>求Geo坐标系下两个点的直线距离(单位:m)</para>
  102. /// </summary>
  103. /// <param name="geo1">geo位置1,经纬高三元组</param>
  104. /// <param name="geo2">geo位置2,经纬高三元组</param>
  105. /// <returns>返回距离,单位m</returns>
  106. public static double DistanceGeo((double, double, double) geo1, (double, double, double) geo2)
  107. {
  108. var posEcef1 = GeoToEcef(geo1);
  109. var posEcef2 = GeoToEcef(geo2);
  110. return DistanceEcf(posEcef1, posEcef2);
  111. }
  112. /// <summary>
  113. /// <para>求Geo坐标系下两个点的测地线距离(单位:m),没有高度</para>
  114. /// <para>得到的是地球表面最短路径,而不是直线距离</para>
  115. /// </summary>
  116. /// <param name="geo1">geo位置1,经纬度二元组</param>
  117. /// <param name="geo2">geo位置2,经纬度二元组</param>
  118. /// <returns>测地线距离,单位m</returns>
  119. public static double DistanceArcGeo((double, double) geo1, (double, double) geo2)
  120. {
  121. var (lon1, lat1) = geo1;
  122. var (lon2, lat2) = geo2;
  123. double dLat1InRad = lat1 * (PI / 180);
  124. double dLong1InRad = lon1 * (PI / 180);
  125. double dLat2InRad = lat2 * (PI / 180);
  126. double dLong2InRad = lon2 * (PI / 180);
  127. double dLongitude = dLong2InRad - dLong1InRad;
  128. double dLatitude = dLat2InRad - dLat1InRad;
  129. double a = Pow(Sin(dLatitude / 2), 2) + Cos(dLat1InRad) * Cos(dLat2InRad) * Pow(Sin(dLongitude / 2), 2);
  130. double c = 2 * Atan2(Sqrt(a), Sqrt(1 - a));
  131. double dDistance = 6378137 * c;//地球长轴半径
  132. return dDistance;
  133. }
  134. /// <summary>
  135. /// 求ecef坐标系下两个点的光速时差(单位:s)
  136. /// </summary>
  137. /// <param name="ecef1">ECEF地心地固坐标1,x、y、z三元组</param>
  138. /// <param name="ecef2">ECEF地心地固坐标2,x、y、z三元组</param>
  139. /// <returns>光速走过的时间,单位s,不会出现负数。交换参数1和参数2的位置不影响结果</returns>
  140. public static double Dto((double, double, double) ecef1, (double, double, double) ecef2)
  141. {
  142. var distance = DistanceEcf(ecef1, ecef2);
  143. return distance / C;
  144. }
  145. /// <summary>
  146. /// 求ecef坐标系下三个点的光速时差(单位:s)
  147. /// </summary>
  148. /// <param name="ecef1">ECEF地心地固坐标1,x、y、z三元组</param>
  149. /// <param name="ecef2">ECEF地心地固坐标2,x、y、z三元组</param>
  150. /// <param name="ecef3">ECEF地心地固坐标3,x、y、z三元组</param>
  151. /// <returns>光速走过的时间,单位s,不会出现负数。交换参数位置不影响结果</returns>
  152. public static double Dto((double, double, double) ecef1, (double, double, double) ecef2, (double, double, double) ecef3)
  153. {
  154. var distance = DistanceEcf(ecef1, ecef2) + DistanceEcf(ecef2, ecef3);
  155. return distance / C;
  156. }
  157. /// <summary>
  158. /// 求ecef坐标系下两个目标的多普勒
  159. /// </summary>
  160. /// <param name="f0">目标载频(上行频点Hz)</param>
  161. /// <param name="ecef1"></param>
  162. /// <param name="ecef2"></param>
  163. /// <param name="v1"></param>
  164. /// <param name="v2"></param>
  165. /// <returns></returns>
  166. public static double Doppler(double f0, (double, double, double) ecef1, (double, double, double) ecef2,
  167. (double, double, double) v1, (double, double, double) v2)
  168. {
  169. var distance = DistanceEcf(ecef1, ecef2);
  170. if (distance == 0) return 0;
  171. var (vx1, vy1, vz1) = v1;
  172. var (vx2, vy2, vz2) = v2;
  173. var (x1, y1, z1) = ecef1;
  174. var (x2, y2, z2) = ecef2;
  175. var fm = (vx1 - vx2) * (x1 - x2) + (vy1 - vy2) * (y1 - y2) + (vz1 - vz2) * (z1 - z2);
  176. var f = f0 / C * fm / distance;
  177. return f;
  178. }
  179. }