FireSimulation.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. //仿真时间单独计时
  2. using System.IO;
  3. public class Fire
  4. {
  5. public class Aircraft
  6. {
  7. public string f_model { get; set; } //机型
  8. public string f_type { get; set; } //飞机种类
  9. public double f_zsl { get; set; } //载水量;前端给出
  10. public double f_mhd { get; set; } //灭火弹数量;前端给出
  11. public double f_mhdarea { get; set; } //单个灭火弹喷洒面积;前端给出
  12. }
  13. public class FireGrid
  14. {
  15. public double Time;
  16. public double FireGrids;
  17. public double FiredGrids;
  18. }
  19. //随机数X:0到1
  20. public static double GenerateRandomNumber()
  21. {
  22. Random random = new Random();
  23. double randomNumber = random.NextDouble();
  24. return randomNumber;
  25. }
  26. //小型直升机洒水概率(IP*POS)
  27. public static double SAirProbability(double sigma = 1)
  28. {
  29. double x = GenerateRandomNumber();
  30. double exponent = -Math.Pow(x, 2) / (2 * Math.Pow(sigma, 2));
  31. double POS = 0.72 + 0.01 * Math.Exp(exponent);
  32. double result = POS * 1;
  33. return POS;
  34. }
  35. //中型直升机洒水概率
  36. public static double MAirProbability(double sigma = 1)
  37. {
  38. double x = GenerateRandomNumber();
  39. double exponent = -Math.Pow(x, 2) / (2 * Math.Pow(sigma, 2));
  40. double POS = 0.8 + 0.1 * Math.Exp(exponent);
  41. double result = POS * 0.93;
  42. return POS;
  43. }
  44. //大型直升机
  45. public static double LAirProbability(double sigma = 1)
  46. {
  47. double x = GenerateRandomNumber();
  48. double exponent = -Math.Pow(x, 2) / (2 * Math.Pow(sigma, 2));
  49. double POS = 0.62 + 0.2 * Math.Exp(exponent);
  50. double result = POS * 0.87;
  51. return POS;
  52. }
  53. //多引擎水陆两栖飞机
  54. public static double MultiAirProbability(double sigma = 1)
  55. {
  56. double x = GenerateRandomNumber();
  57. double exponent = -Math.Pow(x, 2) / (2 * Math.Pow(sigma, 2));
  58. double POS = 0.72 + 0.16 * Math.Exp(exponent);
  59. double result = POS * 1;
  60. return POS;
  61. }
  62. //单引擎水陆两栖飞机
  63. public static double AmAirProbability(double sigma = 1)
  64. {
  65. double x = GenerateRandomNumber();
  66. double exponent = -Math.Pow(x, 2) / (2 * Math.Pow(sigma, 2));
  67. double POS = 0.88 + 0.02 * Math.Exp(exponent);
  68. double result = POS * 1;
  69. return POS;
  70. }
  71. //单引擎灭火飞机
  72. public static double SEAirProbability(double sigma = 1)
  73. {
  74. double x = GenerateRandomNumber();
  75. double exponent = -Math.Pow(x, 2) / (2 * Math.Pow(sigma, 2));
  76. double POS = 0.53 + 0.27 * Math.Exp(exponent);
  77. double result = POS * 0.8;
  78. return POS;
  79. }
  80. //大型灭火飞机
  81. public static double LFAirProbability(double sigma = 1)
  82. {
  83. double x = GenerateRandomNumber();
  84. double exponent = -Math.Pow(x, 2) / (2 * Math.Pow(sigma, 2));
  85. double POS = 0.53 + 0.27 * Math.Exp(exponent);
  86. double result = POS * 0.74;
  87. return POS;
  88. }
  89. //超大型灭火飞机
  90. public static double ULFAirProbability(double sigma = 1)
  91. {
  92. double x = GenerateRandomNumber();
  93. double exponent = -Math.Pow(x, 2) / (2 * Math.Pow(sigma, 2));
  94. double POS = 0.53 + 0.27 * Math.Exp(exponent);
  95. double result = POS * 0.76;
  96. return POS;
  97. }
  98. //灭火弹有效洒水面积
  99. public static double grenadeArea(double f_mhd, double f_mhdarea)
  100. {
  101. double _grenadeArea = f_mhd * f_mhdarea * 0.9;
  102. return _grenadeArea;
  103. }
  104. //吊桶水箱有效洒水面积
  105. public static double SprinklerArea(string type, double f_zsl, double sigma = 1)
  106. {
  107. double _f_zsl = 0;
  108. double _sprinklerArea = 0;
  109. switch (type)
  110. {
  111. case "大型直升机":
  112. double probability1 = LAirProbability(sigma) * AirdropAccuracy.GetIpForType(type);
  113. _f_zsl = f_zsl * probability1;
  114. _sprinklerArea = _f_zsl / 1.8;
  115. break;
  116. case "中型直升机":
  117. double probability2 = MAirProbability(sigma) * AirdropAccuracy.GetIpForType(type);
  118. _f_zsl = f_zsl * probability2;
  119. _sprinklerArea = _f_zsl / 1.8;
  120. break;
  121. case "小型直升机":
  122. double probability3 = SAirProbability(sigma) * AirdropAccuracy.GetIpForType(type);
  123. _f_zsl = f_zsl * probability3;
  124. _sprinklerArea = _f_zsl / 1.8;
  125. break;
  126. case "多引擎水陆两栖飞机":
  127. double probability4 = MultiAirProbability(sigma) * AirdropAccuracy.GetIpForType(type);
  128. _f_zsl = f_zsl * probability4;
  129. _sprinklerArea = _f_zsl / 1.8;
  130. break;
  131. case "单引擎水陆两栖飞机":
  132. double probability5 = AmAirProbability(sigma) * AirdropAccuracy.GetIpForType(type);
  133. _f_zsl = f_zsl * probability5;
  134. _sprinklerArea = _f_zsl / 1.8;
  135. break;
  136. case "单引擎灭火飞机":
  137. double probability6 = SEAirProbability(sigma) * AirdropAccuracy.GetIpForType(type);
  138. _f_zsl = f_zsl * probability6;
  139. _sprinklerArea = _f_zsl / 1.8;
  140. break;
  141. case "大型灭火飞机":
  142. double probability7 = LFAirProbability(sigma) * AirdropAccuracy.GetIpForType(type);
  143. _f_zsl = f_zsl * probability7;
  144. _sprinklerArea = _f_zsl / 1.8;
  145. break;
  146. case "超大型灭火飞机":
  147. double probability8 = ULFAirProbability(sigma) * AirdropAccuracy.GetIpForType(type);
  148. _f_zsl = f_zsl * probability8;
  149. _sprinklerArea = _f_zsl / 1.8;
  150. break;
  151. default:
  152. break;
  153. }
  154. return _sprinklerArea;
  155. }
  156. //地面人员灭火有效面积
  157. //任务开始后,每一批次人员相当于一架飞机,每半小时灭火面积相当于一次洒水面积
  158. //地面部署人员、机降人员到达时间、介入人数(王子涵传入)
  159. public static double groundPersonnelWater(int num)
  160. {
  161. // 灭火火线长度
  162. double PL;
  163. // 10分钟洒水火线长度
  164. PL = 0.16 * num * 55;
  165. // 10分钟灭火面积
  166. double result = PL * 5;
  167. return result;
  168. }
  169. public class CountArea
  170. {
  171. public double burncount { get; set; } //火焰蔓延网格数
  172. public double burnarea { get; set; } //火焰蔓延面积
  173. }
  174. /// <summary>
  175. /// 火焰蔓延计算方法,第一次洒水前是仿真时间
  176. /// </summary>
  177. /// <param name="wind">风速</param>
  178. /// <param name="slope">坡度</param>//与风向相关
  179. /// <param name="vegetation">植被类型</param> //1~11
  180. /// <param name="Weather_T">天气温度</param> //前端给出
  181. /// <param name="time">飞机仿真时间/s</param>
  182. /// <param name="burnarea">上一次洒水后的面积</param>
  183. /// <param name="tn">本次洒水时间</param>
  184. /// <param name="tn_1">上一次洒水时间</param>
  185. /// <param name="InitialArea">初始输入火场面积</param>
  186. /// <returns></returns>
  187. ///"1 针叶林","2 针阔叶混交林","3 阔叶林", "4 灌丛", "5 荒漠","6 草原", "7 草丛","8 草甸","9 沼泽","10 高山植被","11 栽培植被","0 无植被"
  188. ///
  189. public class VegetationCalculator
  190. {
  191. // 定义一个字典来存储每个 vegetation 数值对应的 KS 和 KW 计算公式
  192. private static readonly Dictionary<int, Func<double, double, (double KS, double KW)>> vegetationFormulas =
  193. new Dictionary<int, Func<double, double, (double KS, double KW)>>()
  194. {
  195. { 1, (radians, wind) => (0.1127 * Math.Pow(Math.Tan(radians), 2), 0.8*0.422 * Math.Pow((3.284 * wind), 0.381)) },
  196. { 2, (radians, wind) => (0.1127 * Math.Pow(Math.Tan(radians), 2), 0.9*0.422 * Math.Pow((3.284 * wind), 0.381)) },
  197. { 3, (radians, wind) => (0.1127 * Math.Pow(Math.Tan(radians), 2), 0.422 * Math.Pow((3.284 * wind), 0.381)) },
  198. { 4, (radians, wind) => (0.1127 * Math.Pow(Math.Tan(radians), 2), 0.5*0.422 * Math.Pow((3.284 * wind), 0.381)) },
  199. { 5, (radians, wind) => (0,0) },
  200. { 6, (radians, wind) => (0.1127 * Math.Pow(Math.Tan(radians), 2), 0.3*0.422 * Math.Pow((3.284 * wind), 0.381)) },
  201. { 7, (radians, wind) => (0.1127 * Math.Pow(Math.Tan(radians), 2), 0.3*0.422 * Math.Pow((3.284 * wind), 0.381)) },
  202. { 8, (radians, wind) => (0.1127 * Math.Pow(Math.Tan(radians), 2), 0.3*0.422 * Math.Pow((3.284 * wind), 0.381)) },
  203. { 9, (radians, wind) => (0,0) },
  204. { 10, (radians, wind) => (0.1127 * Math.Pow(Math.Tan(radians), 2), 0.85*0.422 * Math.Pow((3.284 * wind), 0.381)) },
  205. { 11, (radians, wind) => (0.1127 * Math.Pow(Math.Tan(radians), 2), 0.4*0.422 * Math.Pow((3.284 * wind), 0.381)) },
  206. { 0, (radians, wind) => (0,0) }
  207. };
  208. public static (double KS, double KW) Calculate(int vegetation, double radians, double wind)
  209. {
  210. if (vegetationFormulas.TryGetValue(vegetation, out var formula))
  211. {
  212. return formula(radians, wind);
  213. }
  214. else
  215. {
  216. throw new ArgumentException("Invalid vegetation value");
  217. }
  218. }
  219. }
  220. //输入初始火场面积,计算已蔓延时间
  221. public static double InitialburnTime(double wind, double slope, int vegetation, double Weather_T, double InitialArea)
  222. {
  223. double count = InitialArea / 400;
  224. double radians = slope * (Math.PI / 180); // 将角度转换为弧度
  225. // 根据 vegetation 计算 KS 和 KW
  226. var (KS, KW) = VegetationCalculator.Calculate(vegetation, radians, wind);
  227. double time = (count / (0.04 * Weather_T * KS * KW) + 9.06) / 0.3052;
  228. return time ;
  229. }
  230. public static CountArea burnCalculate(double wind, double slope, int vegetation, double Weather_T, double time, double burnarea, double tn, double tn_1, double InitialArea)
  231. {
  232. double x = GenerateRandomNumber();
  233. if (wind == 0) wind = 1;
  234. if (slope < 16) slope = 16;
  235. if (slope > 45) slope = 45;
  236. if (burnarea == 0)
  237. {
  238. if (InitialArea > 0) time = InitialburnTime(wind, slope, vegetation, Weather_T, InitialArea) + time;
  239. }
  240. else
  241. {
  242. //上一次洒水后面积计算得到的时间,加上两次洒水间隔
  243. time = InitialburnTime(wind, slope, vegetation, Weather_T, burnarea) + (tn - tn_1);
  244. }
  245. double radians = slope * (Math.PI / 180); // 将角度转换为弧度
  246. var (KS, KW) = VegetationCalculator.Calculate(vegetation, radians, wind);
  247. double count = 0.04 * Weather_T * KS * KW * (0.3052 * time - 9.06);
  248. double area = count * 400;
  249. return new CountArea { burncount = count, burnarea = area };
  250. }
  251. /// <summary>
  252. /// 燃尽面积计算输出公式
  253. /// </summary>
  254. /// <param name="wind">风速</param>
  255. /// <param name="slope">坡度</param>//与风向相关
  256. /// <param name="vegetation">植被类型</param> //1~11
  257. /// <param name="Weather_T1">初始天气温度</param> //前端给出
  258. /// <param name="Weather_T_ave">从开始到结束的天气温度均值</param> //数据库读取
  259. /// <param name="time">任务耗时</param>
  260. /// <param name="InitialArea">初始输入火场面积</param>
  261. /// <returns></returns>
  262. /// "1 针叶林","2 针阔叶混交林","3 阔叶林", "4 灌丛", "5 荒漠","6 草原", "7 草丛","8 草甸","9 沼泽","10 高山植被","11 栽培植被","0 无植被"
  263. public class VegetationCalculatored
  264. {
  265. // 定义一个字典来存储每个 vegetation 数值对应的 KS 和 KW 计算公式
  266. private static readonly Dictionary<int, Func<double, double, (double KS, double KW)>> vegetationFormulas =
  267. new Dictionary<int, Func<double, double, (double KS, double KW)>>()
  268. {
  269. { 1, (radians, wind) => (0.8*0.0648 * Math.Pow(Math.Tan(radians), 2), 0.8*0.8*0.438 * Math.Pow((3.284 * wind), 0.381)) },
  270. { 2, (radians, wind) => (0.8*0.0648 * Math.Pow(Math.Tan(radians), 2), 0.9*0.8*0.438 * Math.Pow((3.284 * wind), 0.381)) },
  271. { 3, (radians, wind) => (0.8*0.0648 * Math.Pow(Math.Tan(radians), 2), 0.8*0.438 * Math.Pow((3.284 * wind), 0.381)) },
  272. { 4, (radians, wind) => (0.8*0.0648 * Math.Pow(Math.Tan(radians), 2), 0.5*0.8*0.438 * Math.Pow((3.284 * wind), 0.381)) },
  273. { 5, (radians, wind) => ((0,0)) },
  274. { 6, (radians, wind) => (0.8*0.0648 * Math.Pow(Math.Tan(radians), 2), 1.5*0.8*0.438 * Math.Pow((3.284 * wind), 0.381)) },
  275. { 7, (radians, wind) => (0.8*0.0648 * Math.Pow(Math.Tan(radians), 2), 1.5*0.8*0.438 * Math.Pow((3.284 * wind), 0.381)) },
  276. { 8, (radians, wind) => (0.8*0.0648 * Math.Pow(Math.Tan(radians), 2), 1.5*0.8*0.438 * Math.Pow((3.284 * wind), 0.381)) },
  277. { 9, (radians, wind) => (0,0) },
  278. { 10, (radians, wind) => (0.8*0.0648 * Math.Pow(Math.Tan(radians), 2), 0.85*0.8*0.438 * Math.Pow((3.284 * wind), 0.381)) },
  279. { 11, (radians, wind) => (0.8*0.0648 * Math.Pow(Math.Tan(radians), 2), 1.3*0.8*0.438 * Math.Pow((3.284 * wind), 0.381)) },
  280. { 0, (radians, wind) => (0,0) }
  281. };
  282. public static (double KS, double KW) Calculate(int vegetation, double radians, double wind)
  283. {
  284. if (vegetationFormulas.TryGetValue(vegetation, out var formula))
  285. {
  286. return formula(radians, wind);
  287. }
  288. else
  289. {
  290. throw new ArgumentException("Invalid vegetation value");
  291. }
  292. }
  293. }
  294. //每小时都更新天气的火场燃尽面积
  295. public static CountArea burnedCalculate(double wind, double slope, int vegetation, double Weather_T_ave, double Weather_T1, double time, double InitialArea)
  296. {
  297. double x = GenerateRandomNumber();
  298. if (wind == 0) wind = 1;
  299. if (slope < 16) slope = 16;
  300. if (InitialArea > 0) time += InitialburnTime(wind, slope, vegetation, Weather_T1, InitialArea);
  301. double radians = slope * (Math.PI / 180); // 将角度转换为弧度
  302. // 根据 vegetation 计算 KS 和 KW
  303. var (KS, KW) = VegetationCalculatored.Calculate(vegetation, radians, wind);
  304. double count = 0.04 * Weather_T_ave * KS * KW * (2.5458 * time - 2999);
  305. double area = (count) * 400;
  306. return new CountArea { burncount = count, burnarea = area };
  307. }
  308. /// <summary>
  309. /// 过火面积
  310. /// </summary>
  311. /// <param name="wind">风速</param>
  312. /// <param name="slope">破度</param>
  313. /// <param name="vegetation">植被类型</param>
  314. /// <param name="Weather_T_ave">平均温度值</param>
  315. /// <param name="Weather_T1">初始温度值</param>
  316. /// <param name="time">时间</param>
  317. /// <param name="InitialArea">初始面积</param>
  318. /// <param name="waterArea">累计洒水面积</param>
  319. /// <returns></returns>
  320. public static double fireCalculate(double wind, double slope, int vegetation, double Weather_T_ave, double Weather_T1, double time, double InitialArea, double waterArea)
  321. {
  322. double FireArea = 0;
  323. CountArea burnedArea = burnedCalculate(wind, slope, vegetation, Weather_T_ave, Weather_T1, time, InitialArea);
  324. FireArea = burnedArea.burnarea + waterArea;
  325. return FireArea;
  326. }
  327. }