SeaSJ.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. using OpenCvSharp;
  2. namespace SimulationCommon;
  3. public class WeatherResponse
  4. {
  5. public Wind Wind { get; set; }
  6. }
  7. public class Wind
  8. {
  9. public double Speed { get; set; }
  10. public double Deg { get; set; }
  11. }
  12. public class CurrentResponse
  13. {
  14. public Current Current { get; set; }
  15. }
  16. public class Current
  17. {
  18. public double Speed { get; set; }
  19. public double Direction { get; set; }
  20. }
  21. public class NCread
  22. {
  23. //各数组来源文件'Text_readNC.cs';时间范围:2024-06-04T00:00:00 ... 2024-06-04T23:00:00;
  24. //地点范围:落水点为中心100公里
  25. public float[] longitudeArray = new float[10];//经度一维数组来源自文件'Text_readNC.cs'
  26. public float[] latitudeArray = new float[7];//纬度一维数组来源自文件'Text_readNC.cs'
  27. public float[][][] u10Array;//风的10米U(向东)分量三维数组来源自文件'Text_readNC.cs'
  28. public float[][][] v10Array;//风的10米V(向北)分量三维数组来源自文件'Text_readNC.cs'
  29. public float[][][] p140208Array;//海洋上空的自由对流速度三维数组来源自文件'Text_readNC.cs'
  30. public float[][][] mwdArray;//平均波向(单位:度;0度表示北方,90度表示东方)三维数组来源自文件'Text_readNC.cs'
  31. public float[][][] hmaxArray;
  32. }
  33. public class SeaSJ
  34. {
  35. // 生成符合正态分布的随机数
  36. public static double NormalDistributionRandom(double mu, double sigma)
  37. {
  38. Random rand = new Random();
  39. double u1 = 1.0 - rand.NextDouble(); // uniform(0,1] random doubles
  40. double u2 = 1.0 - rand.NextDouble();
  41. double normalRandom = Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2); // random normal(0,1)
  42. return mu + sigma * normalRandom; // random normal(mean,stdDev^2)
  43. }
  44. // 交付类方法
  45. public static List<double[]> GetDrift(NCread nCread, double[] initialPosition, double dt, double totalTime, int times, int latitudes, int longitudes, int times1, int latitudes1, int longitudes1, int times2, int latitudes2, int longitudes2, int times3, int latitudes3, int longitudes3, int days, int hour, double initlatitudes, double initlongitudes)
  46. {
  47. // run 获取轨迹的函数
  48. // initialPosition --> 初始位置; dt --> 时间步长; totalTime --> 总时长
  49. List<double[]> trajectory = CalculateDriftTrajectory(nCread, initialPosition, dt, totalTime, times, latitudes, longitudes, times1, latitudes1, longitudes1, times2, latitudes2, longitudes2, times3, latitudes3, longitudes3, days, hour, initlatitudes, initlongitudes);
  50. return trajectory;
  51. }
  52. public static List<double[]> CalculateDriftTrajectory(NCread nCread, double[] initialPosition, double dt, double totalTime, int times, int latitudes, int longitudes, int times1, int latitudes1, int longitudes1, int times2, int latitudes2, int longitudes2, int times3, int latitudes3, int longitudes3, int days, int hour, double initlatitudes, double initlongitudes)
  53. {
  54. int timeSteps = (int)(totalTime / dt);
  55. List<double[]> trajectory = new List<double[]>();
  56. trajectory.Add(new double[] { initialPosition[0], initialPosition[1] });
  57. for (int t = 1; t < timeSteps; t++)
  58. {
  59. double[] currentPos = trajectory[t - 1];
  60. int outputTime = 3600 * t;
  61. // 动态获取当前位置的风力和洋流数据
  62. double[] windVelocity = GetWindVelocityFromAPI(nCread, currentPos[0], currentPos[1], outputTime, times, latitudes, longitudes, times1, latitudes1, longitudes1, days, hour);
  63. double[] currentVelocity = GetCurrentVelocityFromAPI(nCread, currentPos[0], currentPos[1], outputTime, times2, latitudes2, longitudes2, times3, latitudes3, longitudes3, days, hour);
  64. //foreach (var item in windVelocity)
  65. //{
  66. // Console.WriteLine("windVelocity:" + item);
  67. //}
  68. //foreach (var item in currentVelocity)
  69. //{
  70. // Console.WriteLine("currentVelocity:" + item);
  71. //}
  72. // 计算漂移速度(m/s)
  73. double[] driftVelocity = {
  74. currentVelocity[0] + windVelocity[0],
  75. currentVelocity[1] + windVelocity[1]
  76. };
  77. //foreach (var item in driftVelocity)
  78. //{
  79. // Console.WriteLine("driftVelocity:" + item);
  80. //}
  81. // 更新位置(漂移速度单位是m/s,需要转换成经纬度的变化量)
  82. double[] newPosition = {
  83. currentPos[0] + (driftVelocity[0] * dt * 3600) / ((6371000 * Math.Cos(currentPos[0] * Math.PI / 180)) * 180 / Math.PI), // 纬度变化量
  84. currentPos[1] + (driftVelocity[1] * dt * 3600) / ((6371000 * Math.Cos(currentPos[1] * Math.PI / 180)) * 180 / Math.PI) // 经度变化量
  85. };
  86. //foreach (var item in newPosition)
  87. //{
  88. // Console.WriteLine("newPosition:" + item);
  89. //}
  90. //Console.WriteLine("currentPos[0]:" + (driftVelocity[0] * dt * 3600) / ((6371000 * Math.Cos(currentPos[0] * Math.PI / 180)) * 180 / Math.PI));
  91. //Console.WriteLine("currentPos[1]:" + (driftVelocity[1] * dt * 3600) / ((6371000 * Math.Cos(currentPos[1] * Math.PI / 180)) * 180 / Math.PI));
  92. trajectory.Add(newPosition);
  93. }
  94. return trajectory;//(纬度,经度)
  95. }
  96. public static double[] GetWindVelocityFromAPI(NCread windNCread, double latitude, double longitude, double temptime, int times, int latitudes, int longitudes, int times1, int latitudes1, int longitudes1, int days, int hour)
  97. {
  98. float[] longitudeArray = windNCread.longitudeArray;//经度一维数组来源自文件'Text_readNC.cs'
  99. float[] latitudeArray = windNCread.latitudeArray;//纬度一维数组来源自文件'Text_readNC.cs'
  100. float[][][] u10Array = windNCread.u10Array;//风的10米U(向东)分量三维数组来源自文件'Text_readNC.cs'
  101. float[][][] v10Array = windNCread.v10Array;//风的10米V(向北)分量三维数组来源自文件'Text_readNC.cs'
  102. int longitudeNum = 0;
  103. int latitudeNum = 0;
  104. int temptimeNum = 0;
  105. //定义NC文件中读取不到的坐标点海洋数据信息(后续可采用插值法等)
  106. //经度连续化
  107. for (int i = 0; i < longitudes - 1; i++)
  108. {
  109. if (longitude >= longitudeArray[i] && longitude < longitudeArray[i + 1])
  110. {
  111. longitude = longitudeArray[i];
  112. longitudeNum = i;
  113. }
  114. }
  115. //纬度连续化
  116. for (int i = 0; i < latitudes - 1; i++)
  117. {
  118. if (latitude >= latitudeArray[i] && latitude < latitudeArray[i + 1])
  119. {
  120. latitude = latitudeArray[i];
  121. latitudeNum = i;
  122. }
  123. }
  124. //时间连续化
  125. for (int i = 0; i < times - 1; i++)
  126. {
  127. if (temptime >= 3600 * i && temptime < (3600 * (i + 1)))
  128. {
  129. temptimeNum = i;
  130. }
  131. }
  132. temptimeNum += (days - 1) * 24 + hour;
  133. double windX = (double)u10Array[temptimeNum][latitudeNum][longitudeNum];
  134. double windY = (double)v10Array[temptimeNum][latitudeNum][longitudeNum];
  135. return new double[] { windX, windY };
  136. }
  137. public static double[] GetCurrentVelocityFromAPI(NCread CurrentNCread, double latitude, double longitude, double temptime, int times2, int latitudes2, int longitudes2, int times3, int latitudes3, int longitudes3, int days, int hour)
  138. {
  139. float[] longitudeArray = CurrentNCread.longitudeArray;//经度一维数组来源自文件'Text_readNC.cs'
  140. float[] latitudeArray = CurrentNCread.latitudeArray;//纬度一维数组来源自文件'Text_readNC.cs'
  141. float[][][] u10Array = CurrentNCread.u10Array;//风的10米U(向东)分量三维数组来源自文件'Text_readNC.cs'
  142. float[][][] v10Array = CurrentNCread.v10Array;//风的10米V(向北)分量三维数组来源自文件'Text_readNC.cs'
  143. float[][][] p140208Array = CurrentNCread.p140208Array;//海洋上空的自由对流速度三维数组来源自文件'Text_readNC.cs'
  144. //foreach (var item in p140208Array)
  145. //{
  146. // foreach (var item1 in item)
  147. // {
  148. // foreach (var item2 in item1)
  149. // {
  150. // Console.WriteLine("p140208Array:" + item2);
  151. // }
  152. // }
  153. //}
  154. float[][][] mwdArray = CurrentNCread.mwdArray;//平均波向(单位:度;0度表示北方,90度表示东方)三维数组来源自文件'Text_readNC.cs'
  155. int longitudeNum = 0;
  156. int latitudeNum = 0;
  157. int temptimeNum = 0;
  158. //定义NC文件中读取不到的坐标点海洋数据信息(后续可采用插值法等)
  159. //经度连续化
  160. for (int i = 0; i < longitudes2 - 1; i++)
  161. {
  162. if (longitude >= longitudeArray[i] && longitude < longitudeArray[i + 1])
  163. {
  164. longitude = longitudeArray[i];
  165. longitudeNum = i;
  166. }
  167. }
  168. //纬度连续化
  169. for (int i = 0; i < latitudes2 - 1; i++)
  170. {
  171. if (latitude >= latitudeArray[i] && latitude < latitudeArray[i + 1])
  172. {
  173. latitude = latitudeArray[i];
  174. latitudeNum = i;
  175. }
  176. }
  177. //时间连续化
  178. for (int i = 0; i < times2 - 1; i++)
  179. {
  180. if (temptime >= 3600 * i && temptime < 3600 * (i + 1))
  181. {
  182. temptimeNum = i;
  183. }
  184. }
  185. temptimeNum += (days - 1) * 24 + hour;
  186. //foreach (var item in p140208Array)
  187. //{
  188. // Console.WriteLine("p140208Array:" + (double)p140208Array[0][1][2]);
  189. //}
  190. //Console.WriteLine("p140208Array:" + (double)p140208Array[2640][1][2]);
  191. double currentSpeed = (double)p140208Array[temptimeNum][latitudeNum][longitudeNum];
  192. Random random = new Random();
  193. if (currentSpeed > 10)
  194. currentSpeed = random.NextDouble();
  195. //Console.WriteLine("temptimeNum:" + temptimeNum + "_" + "latitudeNum:" + latitudeNum + "_" + "longitudeNum:" + longitudeNum);
  196. double currentDirection = (double)mwdArray[temptimeNum][latitudeNum][longitudeNum];
  197. //double currentSpeed = (double)p140208Array[2401][0][0];
  198. //Console.WriteLine("currentSpeed:" + currentSpeed);
  199. //Console.WriteLine("currentDirection:" + currentDirection);
  200. double currentDirectionInRadians = currentDirection * (Math.PI / 180);
  201. double currentX = currentSpeed * Math.Cos(currentDirectionInRadians);
  202. double currentY = currentSpeed * Math.Sin(currentDirectionInRadians);
  203. return new double[] { currentX, currentY };
  204. }
  205. //海浪高度获取
  206. public static double GetWaveHeightFromAPI(NCread WaveNCread, double latitude, double longitude, double temptime, int times4, int latitudes4, int longitudes4, int days, int hour)//temptime:仿真时间(秒)
  207. {
  208. float[] longitudeArray = WaveNCread.longitudeArray;//经度一维数组来源自文件'Text_readNC.cs'
  209. float[] latitudeArray = WaveNCread.latitudeArray;//纬度一维数组来源自文件'Text_readNC.cs'
  210. float[][][] hmaxArray = WaveNCread.hmaxArray;//风的10米U(向东)分量三维数组来源自文件'Text_readNC.cs'
  211. int longitudeNum = 0;
  212. int latitudeNum = 0;
  213. int temptimeNum = 0;
  214. //定义NC文件中读取不到的坐标点海洋数据信息(后续可采用插值法等)
  215. //经度连续化
  216. for (int i = 0; i < longitudes4 - 1; i++)
  217. {
  218. if (longitude >= longitudeArray[i] && longitude < longitudeArray[i + 1])
  219. {
  220. longitude = longitudeArray[i];
  221. longitudeNum = i;
  222. }
  223. }
  224. //纬度连续化
  225. for (int i = 0; i < latitudes4 - 1; i++)
  226. {
  227. if (latitude >= latitudeArray[i] && latitude < latitudeArray[i + 1])
  228. {
  229. latitude = latitudeArray[i];
  230. latitudeNum = i;
  231. }
  232. }
  233. //时间连续化
  234. for (int i = 0; i < times4 - 1; i++)
  235. {
  236. if (temptime >= 3600 * i && temptime < (3600 * (i + 1)))
  237. {
  238. temptimeNum = i;
  239. }
  240. }
  241. temptimeNum += (days - 1) * 24 + hour;
  242. double WaveHeight = (double)hmaxArray[temptimeNum][latitudeNum][longitudeNum];
  243. return WaveHeight;
  244. }
  245. // 交付部分方法代码
  246. public static List<double[]> getminEnclosingRect(List<double[]> latLonList)
  247. {
  248. // 转换经纬度为墨卡托投影坐标,并添加到点集合
  249. List<Point2f> pointList = new List<Point2f>();
  250. foreach (var latLon in latLonList)
  251. {
  252. double x = Rectangular_Area_Search_Function.MokatuoLat(latLon[1]);
  253. double y = Rectangular_Area_Search_Function.MokatuoLon(latLon[0]);
  254. pointList.Add(new Point2f((float)y, (float)x));
  255. }
  256. // 获取凸包
  257. Point2f[] convexHull = Rectangular_Area_Search_Function.GetConvexHull(pointList);
  258. //获取凸包各点经纬度坐标
  259. List<double[]> hullPoint = new List<double[]>();
  260. for (int num = 0; num < convexHull.Length - 1; num++)
  261. {
  262. hullPoint.Add(new double[] { convexHull[num].Y, convexHull[num].X });
  263. }
  264. List<double[]> hullPointLatLon = new List<double[]>();
  265. foreach (var point in hullPoint)
  266. {
  267. double pointLat = Rectangular_Area_Search_Function.RMokatuoLat(point[1]);
  268. double pointLon = Rectangular_Area_Search_Function.RMokatuoLon(point[0]);
  269. hullPointLatLon.Add(new double[] { pointLat, pointLon });
  270. }
  271. // 计算最小包围矩形
  272. List<double[]> minEnclosingRect = Rectangular_Area_Search_Function.MinEnclosingRectangle(convexHull);
  273. //foreach (var point in minEnclosingRect)
  274. //{
  275. // foreach (var item in point)
  276. // {
  277. // Console.WriteLine("item:" + item);
  278. // }
  279. //}
  280. // 最小包围矩形顶点经纬度坐标
  281. List<double[]> startPoint = new List<double[]>();
  282. foreach (var minEnclosingRectPoint in minEnclosingRect)
  283. {
  284. double lat = Rectangular_Area_Search_Function.RMokatuoLat(minEnclosingRectPoint[0]);
  285. double lon = Rectangular_Area_Search_Function.RMokatuoLon(minEnclosingRectPoint[1]);
  286. startPoint.Add(new double[] { lat, lon });
  287. }
  288. //foreach (var point in startPoint)
  289. //{
  290. // foreach (var item in point)
  291. // {
  292. // Console.WriteLine("startPoint:" + item);
  293. // }
  294. //}
  295. return startPoint;
  296. }
  297. }