GeoUtil.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. using System;
  2. namespace Ips.Library.Basic
  3. {
  4. public static class GeoUtil
  5. {
  6. public const double WGS84a = 6378137.0;
  7. public const double f = 1.0 / 298.257224;
  8. public const double WGS84b = WGS84a - WGS84a * f;
  9. public const double WGS84a2 = WGS84a * WGS84a;
  10. public const double WGS84b2 = WGS84b * WGS84b;
  11. public const double C = 299792458.0;
  12. public const double R = 6378141.4;
  13. public static double[] LLA2XYZ(double lon, double lat, double alt)
  14. {
  15. lat = Math.PI * lat / 180.0;
  16. lon = Math.PI * lon / 180.0;
  17. double cosLat = Math.Cos(lat);
  18. double sinLat = Math.Sin(lat);
  19. double cosLong = Math.Cos(lon);
  20. double sinLong = Math.Sin(lon);
  21. double c = 1 / Math.Sqrt(cosLat * cosLat + (1 - f) * (1 - f) * sinLat * sinLat);
  22. double s = (1 - f) * (1 - f) * c;
  23. double x = (WGS84a * c + alt) * cosLat * cosLong;
  24. double y = (WGS84a * c + alt) * cosLat * sinLong;
  25. double z = (WGS84a * s + alt) * sinLat;
  26. return new double[3] { x, y, z };
  27. }
  28. public static double[] LLA2XYZ(double[] lla)
  29. {
  30. return LLA2XYZ(lla[0], lla[1], lla[2]);
  31. }
  32. public static double[] XYZ2LLA(double x, double y, double z)
  33. {
  34. double ea = Math.Sqrt((WGS84a * WGS84a - WGS84b * WGS84b) / (WGS84a * WGS84a));
  35. double eb = Math.Sqrt((WGS84a * WGS84a - WGS84b * WGS84b) / (WGS84b * WGS84b));
  36. double p = Math.Sqrt(x * x + y * y);
  37. double theta = Math.Atan2(z * WGS84a, p * WGS84b);
  38. double lon = Math.Atan2(y, x);
  39. double lat = Math.Atan2(z + eb * eb * WGS84b * Math.Pow(Math.Sin(theta), 3),
  40. p - ea * ea * WGS84a * Math.Pow(Math.Cos(theta), 3));
  41. double N = WGS84a / Math.Sqrt(1 - ea * ea * Math.Sin(lat) * Math.Sin(lat));
  42. double alt = p / Math.Cos(lat) - N;
  43. return new double[3] { lon * (180.0 / Math.PI), lat * (180.0 / Math.PI), alt };
  44. }
  45. public static double[] XYZ2LLA(double[] xyz)
  46. {
  47. return XYZ2LLA(xyz[0], xyz[1], xyz[2]);
  48. }
  49. public static double Distince(double x1, double y1, double z1, double x2, double y2, double z2)
  50. {
  51. double x = (x1 - x2);
  52. double y = (y1 - y2);
  53. double z = (z1 - z2);
  54. double dist = Math.Sqrt(x * x + y * y + z * z);
  55. return dist;
  56. }
  57. public static double Distince(double[] xyzOne, double[] xyzTwo)
  58. {
  59. return Distince(xyzOne[0], xyzOne[1], xyzOne[2], xyzTwo[0], xyzTwo[1], xyzTwo[2]);
  60. }
  61. public static double DistinceLla(double lon1, double lat1, double alt1, double lon2, double lat2, double alt2)
  62. {
  63. var xyz1 = LLA2XYZ(lon1, lat1, alt1);
  64. var xyz2 = LLA2XYZ(lon2, lat2, alt2);
  65. return Distince(xyz1, xyz2);
  66. }
  67. public static double DistinceLla(double[] lla1, double[] lla2)
  68. {
  69. double[] xyz1 = LLA2XYZ(lla1), xyz2 = LLA2XYZ(lla2);
  70. return Distince(xyz1, xyz2);
  71. }
  72. public static double CalcDt(double x1, double y1, double z1, double x2, double y2, double z2)
  73. {
  74. var dis = Distince(x1, y1, z1, x2, y2, z2);
  75. return (dis / C) * 1e6;
  76. }
  77. public static double CalcDt(double[] xyzOne, double[] xyzTwo)
  78. {
  79. return CalcDt(xyzOne[0], xyzOne[1], xyzOne[2], xyzTwo[0], xyzTwo[1], xyzTwo[2]);
  80. }
  81. public static double CalcDtoCenter(double[] tarLla, double[] satXyz, double[] antLla)
  82. {
  83. double[] tarXyz = LLA2XYZ(tarLla);
  84. double[] antXyz = LLA2XYZ(antLla);
  85. double disTarSat = Distince(tarXyz, satXyz);
  86. double disSatAnt = Distince(satXyz, antXyz);
  87. return -1 * (disTarSat + disSatAnt) / C * 1e6;
  88. }
  89. public static double CalcDtoCenter(double[] tarLla, double[] mSatXyz, double[] aSatXyz, double[] mAntLla, double[] aAntLla)
  90. {
  91. double[] tarXyz = LLA2XYZ(tarLla);
  92. double[] mAntXyz = LLA2XYZ(mAntLla);
  93. double[] aAntXyz = LLA2XYZ(aAntLla);
  94. double mDisTarSatAnt = Distince(tarXyz, mSatXyz) + Distince(mSatXyz, mAntXyz);
  95. double aDisTarSatAnt = Distince(tarXyz, aSatXyz) + Distince(aSatXyz, aAntXyz);
  96. return -1 * (aDisTarSatAnt - mDisTarSatAnt) / C * 1e6;
  97. }
  98. public static double[] CalcDtMinMax(double tarLonMin, double tarLonMax, double tarLatMin, double tarLatMax, double tarAlt,
  99. double satX, double satY, double satZ,
  100. double antLon, double antLat, double antAlt)
  101. {
  102. double[] p1 = LLA2XYZ(tarLonMin, tarLatMin, tarAlt);
  103. double[] p2 = LLA2XYZ(tarLonMin, tarLatMax, tarAlt);
  104. double[] p3 = LLA2XYZ(tarLonMax, tarLatMin, tarAlt);
  105. double[] p4 = LLA2XYZ(tarLonMax, tarLatMax, tarAlt);
  106. double[] satXYZ = new[] { satX, satY, satZ };
  107. double dt1 = CalcDt(p1, satXYZ), dt2 = CalcDt(p2, satXYZ), dt3 = CalcDt(p3, satXYZ), dt4 = CalcDt(p4, satXYZ);
  108. double dtMax = Math.Max(Math.Max(dt1, dt2), Math.Max(dt3, dt4));
  109. double dtMin;
  110. double[] satLLA = XYZ2LLA(satX, satY, satZ);
  111. if (GeoUtil.InZone(satLLA[0], satLLA[1], tarLonMin, tarLonMax, tarLatMin, tarLatMax))
  112. {
  113. double satLon = satLLA[0], satLat = satLLA[1];
  114. double[] minLLA = new[] { satLon, satLat, 0 };
  115. double[] minXYZ = LLA2XYZ(minLLA);
  116. dtMin = CalcDt(minXYZ, satXYZ);
  117. }
  118. else
  119. {
  120. var lonRange = GeoUtil.LonRange(tarLonMax, tarLonMin);
  121. var latRange = GeoUtil.LatRange(tarLatMax, tarLatMin);
  122. var centerLLA = new double[] { tarLonMin + lonRange / 2, tarLatMin + latRange / 2, tarAlt };
  123. var centerXYZ = LLA2XYZ(centerLLA);
  124. var dtCenter = CalcDt(centerXYZ, satXYZ);
  125. dtMin = dtMax - (dtMax - dtCenter) * 2;
  126. }
  127. var antXYZ = LLA2XYZ(antLon, antLat, antAlt);
  128. var dtSatAnt = CalcDt(satXYZ, antXYZ);
  129. dtMin += dtSatAnt;
  130. dtMax += dtSatAnt;
  131. return new double[] { dtMin, dtMax };
  132. }
  133. public static double[] CalcDtCR(double[] tarRange, double[] satXyz, double[] antLla)
  134. {
  135. var lonRange = tarRange[3];
  136. var latRange = tarRange[4];
  137. var lonMin = tarRange[0] - lonRange / 2;
  138. var lonMax = tarRange[0] + lonRange / 2;
  139. var latMin = tarRange[1] - latRange / 2;
  140. var latMax = tarRange[1] + latRange / 2;
  141. var dtoCenter = CalcDtoCenter(tarRange, satXyz, antLla);
  142. double[] p1 = LLA2XYZ(lonMin, latMin, tarRange[2]);
  143. double[] p2 = LLA2XYZ(lonMin, latMax, tarRange[2]);
  144. double[] p3 = LLA2XYZ(lonMax, latMin, tarRange[2]);
  145. double[] p4 = LLA2XYZ(lonMax, latMax, tarRange[2]);
  146. double disP1Sat = Distince(p1, satXyz), disP2Sat = Distince(p2, satXyz), disP3Sat = Distince(p3, satXyz), disP4Sat = Distince(p4, satXyz);
  147. var disMax = Math.Max(Math.Max(disP1Sat, disP2Sat), Math.Max(disP3Sat, disP4Sat));
  148. var dtMax = -1 * (disMax + Distince(satXyz, LLA2XYZ(antLla))) / C * 1e6;
  149. var dtoRange = Math.Abs(2 * (dtMax - dtoCenter));
  150. return new double[] { dtoCenter, dtoRange };
  151. }
  152. public static double[] CalcDtCRByZone(double tarLonMin, double tarLonMax, double tarLatMin, double tarLatMax, double tarAlt, double[] satXyz, double[] antLla)
  153. {
  154. var lonRange = GeoUtil.LonRange(tarLonMax, tarLonMin);
  155. var latRange = GeoUtil.LatRange(tarLatMax, tarLatMin);
  156. var tarLon = GeoUtil.Lon180(tarLonMin + lonRange / 2);
  157. var tarLat = tarLatMin + latRange / 2;
  158. var tarLla = new[] { tarLon, tarLat, tarAlt };
  159. var dtoCenter = CalcDtoCenter(tarLla, satXyz, antLla);
  160. double[] p1 = LLA2XYZ(tarLonMin, tarLatMin, tarAlt);
  161. double[] p2 = LLA2XYZ(tarLonMin, tarLatMax, tarAlt);
  162. double[] p3 = LLA2XYZ(tarLonMax, tarLatMin, tarAlt);
  163. double[] p4 = LLA2XYZ(tarLonMax, tarLatMax, tarAlt);
  164. double disP1Sat = Distince(p1, satXyz), disP2Sat = Distince(p2, satXyz), disP3Sat = Distince(p3, satXyz), disP4Sat = Distince(p4, satXyz);
  165. var disMax = Math.Max(Math.Max(disP1Sat, disP2Sat), Math.Max(disP3Sat, disP4Sat));
  166. var dtMax = -1 * (disMax + Distince(satXyz, LLA2XYZ(antLla))) / C * 1e6;
  167. var dtoRange = Math.Abs(2 * (dtMax - dtoCenter));
  168. return new double[] { dtoCenter, dtoRange };
  169. }
  170. public static double[] CalcDtCR(double[] tarRange, double[] mSatXyz, double[] aSatXyz, double[] mAntLla, double[] aAntLla)
  171. {
  172. var lonRange = tarRange[3];
  173. var latRange = tarRange[4];
  174. var lonMin = tarRange[0] - lonRange / 2;
  175. var lonMax = tarRange[0] + lonRange / 2;
  176. var latMin = tarRange[1] - latRange / 2;
  177. var latMax = tarRange[1] + latRange / 2;
  178. var tarAlt = tarRange[2];
  179. var dtoCenter = CalcDtoCenter(tarRange, mSatXyz, aSatXyz, mAntLla, aAntLla);
  180. var lonStep = 0.2;
  181. var latStep = 0.2;
  182. double dtMax = double.MinValue, dtMin = double.MaxValue;
  183. for (double lon = lonMin; lon <= lonMax; lon += lonStep)
  184. {
  185. for (double lat = latMin; lat <= latMax; lat += latStep)
  186. {
  187. var dt = CalcDtoCenter(new[] { lon, lat, tarAlt }, mSatXyz, aSatXyz, mAntLla, aAntLla);
  188. dtMax = Math.Max(dt, dtMax);
  189. dtMin = Math.Min(dt, dtMin);
  190. }
  191. }
  192. var dtoRange = (dtMax - dtMin) * 1.2;
  193. return new double[] { dtoCenter, dtoRange };
  194. }
  195. public static double CalcLeadDt(double dt1, double[] tarLla, double[] antLla, double[] ephXyz1, double[] ephXyz2)
  196. {
  197. var refTimeDt = GeoUtil.CalcDtoCenter(tarLla, ephXyz1, antLla);
  198. var tarTimeDt = GeoUtil.CalcDtoCenter(tarLla, ephXyz2, antLla);
  199. var dt2 = dt1 + (tarTimeDt - refTimeDt);
  200. return dt2;
  201. }
  202. public static double CalcLeadDt(double dt1, double[] tarLla, double[] mAntLla, double[] aAntLla, double[] mEph1, double[] aEph1, double[] mEph2, double[] aEph2)
  203. {
  204. var refTimeDt = GeoUtil.CalcDtoCenter(tarLla, mEph1, aEph1, mAntLla, aAntLla);
  205. var tarTimeDt = GeoUtil.CalcDtoCenter(tarLla, mEph2, aEph2, mAntLla, aAntLla);
  206. var dt2 = dt1 + (tarTimeDt - refTimeDt);
  207. return dt2;
  208. }
  209. public static double[] GetRange(params double?[][] ranges)
  210. {
  211. double lonMin = -180;
  212. double lonMax = 180;
  213. double latMin = -90;
  214. double latMax = 90;
  215. foreach (var range in ranges)
  216. {
  217. lonMin = Math.Max(lonMin, range?[0] ?? -180);
  218. lonMax = Math.Min(lonMax, range?[1] ?? 180);
  219. latMin = Math.Max(latMin, range?[2] ?? -90);
  220. latMax = Math.Min(latMax, range?[3] ?? 90);
  221. }
  222. return new double[] { lonMin, lonMax, latMin, latMax };
  223. }
  224. public static bool InZone(double tarLon, double tarLat, double lonMin, double lonMax, double latMin, double latMax)
  225. {
  226. tarLon = Lon360(tarLon);
  227. lonMin = Lon360(lonMin);
  228. lonMax = Lon360(lonMax);
  229. return tarLon >= lonMin && tarLon <= lonMax && tarLat >= latMin && tarLat <= latMax;
  230. }
  231. public static double LonRange(double lon1, double lon2)
  232. {
  233. lon1 = Lon360(lon1);
  234. lon2 = Lon360(lon2);
  235. return Math.Abs(lon1 - lon2);
  236. }
  237. public static double LatRange(double lat1, double lat2)
  238. {
  239. return Math.Abs(lat1 - lat2);
  240. }
  241. public static double Lon360(double lon)
  242. {
  243. return lon < 0 ? lon + 360 : lon;
  244. }
  245. public static double Lon180(double lon)
  246. {
  247. return lon > 180 ? lon - 360 : lon;
  248. }
  249. public static bool IsValidPoint(double lon, double lat)
  250. {
  251. return IsValidLon(lon) && IsValidLat(lat);
  252. }
  253. public static bool IsValidLon(double lon)
  254. {
  255. return lon > -180 && lon < 180;
  256. }
  257. public static bool IsValidLat(double lat)
  258. {
  259. return lat > -90 && lat < 90;
  260. }
  261. }
  262. }