欢迎来到 盹猫(>^ω^<)的博客 本篇文章主要介绍了 [Java实现林火蔓延路径算法] ❤博主广交技术好友,喜欢文章的可以关注一下❤
记录正在进行的森林防火项目中林火蔓延功能,本篇文章可以较好的实现森林防火蔓延,但还存在很多不足,如:很多参数只能使用默认值,所以蔓延范围仅供参考。(如果底层设备获取的数据充足,那当我没说)。
参数名 | 解释 |
---|---|
x1 | 经度 |
x2 | 纬度 |
sj | 风向偏移量(代码中这个要>n才会调用蔓延算法) |
n | n = 0:表示风向角度范围在 225 度左右。 n = 1:表示风向角度范围在 270 度左右。 n = 2:表示风向角度范围在 315 度左右。 n = 3:表示风向角度范围在 0 度左右。 n = 4:表示风向角度范围在 45 度左右。 n = 5:表示风向角度范围在 90 度左右。 n = 6:表示风向角度范围在 135 度左右。 n = 7:表示风向角度范围在 180 度左右 |
Winddir | 风向 |
Time | 时间 |
s | 矿质阻尼系数(不太懂,默认设为0) |
v | 理想反应速度:快速燃烧(50) 中等燃烧(10) 缓慢燃烧(1) |
speed | 风速 |
Wn | 静可燃物载量(就是有多少东西可供燃烧),估值或直接用下面的值 小型树木或灌木(500千克) 中型树木(5000千克) 大型树木(50万千克) |
h | 可燃物烩值 (木材:17) |
q | 修正系数 (默认1) |
density | 密度修正系数 (默认1) |
a | 修正系数 (默认1) |
Qi | 密度(默认1) |
p | 修正参数 (默认1) |
slope | 坡度 |
private double CalWindCorr(double speed, double p) {
// 计算⻛速修正系数
double Qw; //⻛速修正系数
double B;
double C;
double E;
double b; //燃料最佳紧密度
double c; //最有可能的压缩⽐
c = 1.2;
E = 0.715 * (Math.pow(Math.E, (-0.01094 * p)));
C = 7.47 * (Math.pow(Math.E, (-0.8711 * Math.pow(p, 0.55))));
B = 0.15988 * Math.pow(p, 0.54);
b = 0.20395 * Math.pow(p, -0.8189);
Qw = C * Math.pow(3.284 * speed, B) * Math.pow(c / b, -E);
return Qw;
}
public double CalSlopeCorr(double slope, double p) {
// 计算坡度修正系数 p
double Qs;
Qs = 5.275 * Math.pow(p, -0.3) * (Math.tan(slope * Math.PI / 180)) * (Math.tan(slope * Math.PI / 180));
return Qs;
}
private double CalIr(double v, double Wn, double h, double m, double s) {
// 计算⽕焰强度
// 理想反应速度 v
// 可燃物烩值 h
// 净可燃物载量 Wn
// 湿度阻尼系数 m
// 矿质阻尼系数 s
double Ir;
Ir = v * Wn * h * m * s;
return Ir;
}
public XY GetNextFeature(double x, double y, double s, int n,int sj,double fengxiang) {
double s1;
int m;
XY c1 = new XY();
int number = 80;
switch (n) {
case 0: { s1 = s * Math.sin((Math.PI) / 4); m = (int)(s1 / 80); if (fengxiang > 0 && fengxiang < 90) { c1.setX((x - m * 80 - 0.1 - number * sj)); c1.setY((y + m * 80 + 0.1 + number * sj)); }else if (fengxiang > 90 && fengxiang < 180) { c1.setX((x - m * 80 - 0.1 - number * sj-80*2));
c1.setY(y + m * 80 + 0.1 + number * sj+80*2); }else if (fengxiang > 180 && fengxiang < 270) { c1.setX(x - m * 80 - 0.1 - number * sj - 80 * 3); c1.setY(y + m * 80 + 0.1 + number * sj + 80 * 3); }else if (fengxiang > 270 && fengxiang < 360) { c1.setX(x - m * 80 - 0.1 - number * sj-80*1); c1.setY(y + m * 80 + 0.1 + number * sj+80*1); }else if (fengxiang == 0|| fengxiang == 360) { c1.setX(x - m * 80 - 0.1 - number * sj); c1.setY(y + m * 80 + 0.1 + number * sj); }else if (fengxiang == 90) { c1.setX(x - m * 80 - 0.1 - number * sj); c1.setY(y + m * 80 + 0.1 + number * sj); }else if (fengxiang == 180) { c1.setX(x - m * 80 - 0.1 - number * sj-80*1); c1.setY(y + m * 80 + 0.1 + number * sj+80*1); }else if (fengxiang == 270) { c1.setX(x - m * 80 - 0.1 - number * sj - 80*2); c1.setY(y + m * 80 + 0.1 + number * sj + 80*2); }break; }
case 1: { s1 = s; m = (int)(s1 / 80); if (fengxiang > 0 && fengxiang < 90) { c1.setX(x - 0.1-80); c1.setY(y + m * 80 + number * sj + 0.1); }else if (fengxiang > 90 && fengxiang < 180) { c1.setX(x - 0.1 - 80); c1.setY(y + m * 80 + number * sj + 0.1+80*1); }else if (fengxiang > 180 && fengxiang < 270) { c1.setX(x - 0.1 - 80); c1.setY(y + m * 80 + number * sj + 0.1+ 80 * 2); }else if (fengxiang > 270 && fengxiang < 360) { c1.setX(x - 0.1 - 80); c1.setY(y + m * 80 + number * sj + 0.1 +80 * 2); }
else if (fengxiang == 0 || fengxiang == 360) { c1.setX(x - 0.1 - 80); c1.setY(y + m * 80 + number * sj + 0.1+80); }else if (fengxiang == 90) { c1.setX(x - 0.1 - 80); c1.setY(y + m * 80 + number * sj + 0.1); }else if (fengxiang == 180) { c1.setX(x - 0.1 - 80); c1.setY(y + m * 80 + number * sj + 0.1); }else if (fengxiang == 270) { c1.setX(x - 0.1 - 80); c1.setY(y + m * 80 + number * sj + 0.1+80*3); }break; }
case 2: { s1 = s * Math.sin((Math.PI) / 4); m = (int)(s1 / 80); // c1.X = (x + m * 80 + number * sj + 0.1); // c1.Y = (y + m * 80 + number * sj + 0.1);
if (fengxiang > 0 && fengxiang < 90) { c1.setX((x + m * 80 + number * sj + 0.1)); c1.setY(y + m * 80 + number * sj + 0.1); }else if (fengxiang > 90 && fengxiang < 180) { c1.setX(x + m * 80 + number * sj + 0.1-80*2); c1.setY(y + m * 80 + number * sj + 0.1-80*2); }else if (fengxiang > 180 && fengxiang < 270) { c1.setX(x + m * 80 + number * sj + 0.1 - 80 * 1); c1.setY(y + m * 80 + number * sj + 0.1 - 80 * 1); }else if (fengxiang > 270 && fengxiang < 360) { c1.setX(x + m * 80 + number * sj + 0.1+80*5); c1.setY(y + m * 80 + number * sj + 0.1+80*5); }else if (fengxiang == 0 || fengxiang == 360) { c1.setX(x + m * 80 + number * sj + 0.1 + 80*3); c1.setY(y + m * 80 + number * sj + 0.1 + 80*3); }else if (fengxiang == 90) { c1.setX(x + m * 80 + number * sj + 0.1 + 80); c1.setY(y + m * 80 + number * sj + 0.1 + 80); }
else if (fengxiang == 180) { c1.setX(x + m * 80 + number * sj + 0.1); c1.setY(y + m * 80 + number * sj + 0.1); }else if (fengxiang == 270) { c1.setX(x + m * 80 + number * sj + 0.1 + 80*2); c1.setY(y + m * 80 + number * sj + 0.1 + 80*2); }break; }
case 3: { s1 = s; m = (int)(s1 / 80); if (fengxiang > 0 && fengxiang < 90) { c1.setX(x + m * 80 + 0.1 + number * sj + 80 * 2); c1.setY(y + 0.1 +80); }else if (fengxiang > 90 && fengxiang < 180) { c1.setX(x + m * 80 + 0.1 + number * sj); c1.setY(y + 0.1 + 80); }else if (fengxiang > 180 && fengxiang < 270) { c1.setX(x + m * 80 + 0.1 + number * sj); c1.setY(y + 0.1 + 80); }else if (fengxiang > 270 && fengxiang < 360) { c1.setX(x + m * 80 + 0.1 + number * sj+80 * 2); c1.setY(y + 0.1 + 80); }else if (fengxiang == 0 || fengxiang == 360) { c1.setX(x + m * 80 + 0.1 + number * sj + 80 * 3); c1.setY(y + 0.1 + 80); }else if (fengxiang == 90) { c1.setX(x + m * 80 + 0.1 + number * sj + 80 * 1); c1.setY(y + 0.1 + 80); }else if (fengxiang == 180) { c1.setX(x + m * 80 + 0.1 + number * sj); c1.setY(y + 0.1 + 80); }else if (fengxiang == 270) { c1.setX(x + m * 80 + 0.1 + number * sj + 80 *1); c1.setY(y + 0.1 + 80); }break; }
case 4: { s1 = s * Math.sin((Math.PI) / 4); m = (int)((s1 / 80)); if (fengxiang > 0 && fengxiang < 90) { c1.setX(x + m * 80 + number * sj + 80 * 3); c1.setY(y - m * 80 - number * sj - 80 * 3); }else if (fengxiang > 90 && fengxiang < 180) { c1.setX(x + m * 80 + number * sj + 0.1); c1.setY(y - m * 80 - number * sj - 0.1); }else if (fengxiang > 180 && fengxiang < 270) { c1.setX(x + m * 80 + number * sj + 0.1); c1.setY(y - m * 80 - number * sj - 0.1); }else if (fengxiang > 270 && fengxiang < 360) { c1.setX(x + m * 80 + number * sj + 0.1); c1.setY(y - m * 80 - number * sj - 0.1); }else if (fengxiang == 0 || fengxiang == 360) { c1.setX(x + m * 80 + number * sj + 80 * 2); c1.setY(y - m * 80 - number * sj - 80 * 2); }else if (fengxiang == 90) { c1.setX(x + m * 80 + number * sj + 80 * 2); c1.setY(y - m * 80 - number * sj - 80 * 2); }else if (fengxiang == 180) { c1.setX(x + m * 80 + number * sj + 0.1); c1.setY(y - m * 80 - number * sj - 0.1); }else if (fengxiang == 270) { c1.setX(x + m * 80 + number * sj + 0.1); c1.setY(y - m * 80 - number * sj - 0.1); }break; }
case 5: { s1 = s; m = (int)(s1 / 80); if (fengxiang > 0 && fengxiang < 90) { c1.setX(x + 0.1 + 80); c1.setY(y - m * 80 - number * sj - 0.1- 80 * 2); }else if (fengxiang > 90 && fengxiang < 180) { c1.setX(x + 0.1 + 80);
c1.setY(y - m * 80 - number * sj - 0.1 - 80 * 1); }else if (fengxiang > 180 && fengxiang < 270) { c1.setX(x + 0.1 + 80); c1.setY(y - m * 80 - number * sj - 0.1); ; }else if (fengxiang > 270 && fengxiang < 360) { c1.setX(x + 0.1 + 80); c1.setY(y - m * 80 - number * sj - 0.1); }else if (fengxiang == 0 || fengxiang == 360) { c1.setX(x + 0.1 + 80); c1.setY(y - m * 80 - number * sj - 0.1 - 80 * 1); }else if (fengxiang == 90) { c1.setX(x + 0.1 + 80); c1.setY(y - m * 80 - number * sj - 0.1 - 80 * 3); }else if (fengxiang == 180) { c1.setX(x + 0.1 + 80); c1.setY(y - m * 80 - number * sj - 0.1 - 80 * 1); }else if (fengxiang == 270) { c1.setX(x + 0.1 + 80); c1.setY(y - m * 80 - number * sj - 0.1); }break; }
case 6: { s1 = s * Math.sin((Math.PI) / 4); m = (int)((s1 / 80)); // c1.X = (x - m * 80 - 0.1 - number * sj); //c1.Y = (y - m * 80 - 0.1 - number * sj);
if (fengxiang > 0 && fengxiang < 90) { c1.setX(x - m * 80 - 0.1 - number * sj); c1.setY(y - m * 80 - 0.1 - number * sj); }else if (fengxiang > 90 && fengxiang < 180) { c1.setX(x - m * 80 - 0.1 - number * sj - 80 * 3); c1.setY(y - m * 80 - 0.1 - number * sj - 80 * 3); }else if (fengxiang > 180 && fengxiang < 270) { c1.setX(x - m * 80 - 0.1 - number * sj- 80 * 1); c1.setY(y - m * 80 - 0.1 - number * sj-80 * 1); }else if (fengxiang > 270 && fengxiang < 360) { c1.setX(x - m * 80 - 0.1 - number * sj);
c1.setY(y - m * 80 - 0.1 - number * sj); }else if (fengxiang == 0 || fengxiang == 360) { c1.setX(x - m * 80 - 0.1 - number * sj); c1.setY(y - m * 80 - 0.1 - number * sj); }else if (fengxiang == 90) { c1.setX(x - m * 80 - 0.1 - number * sj - 80 * 2); c1.setY(y - m * 80 - 0.1 - number * sj - 80 * 2); }else if (fengxiang == 180) { c1.setX(x - m * 80 - 0.1 - number * sj - 80 * 1); c1.setY(y - m * 80 - 0.1 - number * sj - 80 * 1); }else if (fengxiang == 270) { c1.setX(x - m * 80 - 0.1 - number * sj); c1.setY(y - m * 80 - 0.1 - number * sj); }break; }
case 7: { s1 = s; m = (int)(s1 / 80);
if (fengxiang > 0 && fengxiang < 90) { c1.setX(x - m * 80 - number * sj); c1.setY(y - 0.1-80); }
else if (fengxiang > 90 && fengxiang < 180) { c1.setX(x - m * 80 - number * sj- 80 * 3);c1.setY(y - 0.1 - 80); }
else if (fengxiang > 180 && fengxiang < 270) { c1.setX(x - m * 80 - number * sj - 80 * 2); c1.setY(y - 0.1 - 80); }
else if (fengxiang > 270 && fengxiang < 360) { c1.setX(x - m * 80 - number * sj); c1.setY(y - 0.1 - 80); }
else if (fengxiang == 0 || fengxiang == 360) { c1.setX(x - m * 80 - number * sj); c1.setY(y - 0.1 - 80); }
else if (fengxiang == 90) { c1.setX(x - m * 80 - number * sj - 80 * 1); c1.setY(y - 0.1 - 80);}
else if (fengxiang == 180) { c1.setX(x - m * 80 - number * sj - 80 * 3); c1.setY(y - 0.1 - 80); }
else if (fengxiang == 270) { c1.setX(x - m * 80 - number * sj- 80 * 1); c1.setY(y - 0.1 - 80); }
break;
}
}
return c1;
}
public double SpreadSpeed(double n, double Winddir,double v,double Wn,double h,double m,double q,double density,double a,double Qi,double p,double slope,double speed ,double s) {
double angle = 0;
double Ir;
double R;
double K=1;
if (n == 0) {
angle = Math.abs(Winddir - 225);
return K * (16 + 16 * (Math.cos(angle * Math.PI / 180))); }
if (n == 1) { angle = Math.abs(Winddir - 270);
return K * (15 + 15 * (Math.cos(angle * Math.PI / 180))); }
if (n == 2) { angle = Math.abs(Winddir - 315) + 180; }if (n == 3) { angle = Math.abs(Winddir); }
if (n == 4) { angle = Math.abs(Winddir - 45); }
if (n == 5) { angle = Math.abs(Winddir - 90); }
if (n == 6) { angle = Math.abs(Winddir - 135); return K * (12 + 12 * (Math.abs(angle * Math.PI / 180))); }
if (n == 7) { angle = Math.abs(Winddir - 180); return K * (13 + 13 * (Math.cos(angle * Math.PI / 180))); }
double speed_dy = CalWindCorr(speed,p);
//⻛速修正系数
double slop_dy = CalSlopeCorr(slope,p);
Ir=CalIr(v,Wn,h,m,s);
R = (Ir * q * (1 + speed_dy + slop_dy)) / (density * a * Qi);
return K * (R + R * Math.cos(angle * Math.PI / 180));
}
public XY lonLat2Mercator(double lon,double lat) { XY c1 = new XY(); c1.setX(lon * 20037508.34 / 180); double Y2 = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180); c1.setY(Y2 * 20037508.34 / 180); return c1; }
public XY Mercator2lonLat(double x, double y) { XY c1 = new XY(); c1.setX(x / 20037508.34 * 180); double Y2 = y / 20037508.34 * 180; c1.setY(180 / Math.PI * (2 * Math.atan(Math.exp(Y2 * Math.PI / 180)) - Math.PI / 2)); return c1; }
public XY HuygenSpread(double x1, double y1, int sj, int n, double Winddir, double Time, double s, double v, double speed, double Wn, double h, double q, double density, double a, double Qi, double p, double slope) {
if (n< sj) {
double huoyanspeed = SpreadSpeed(n,Winddir,v,Wn,h,n,q,density,a,Qi,p,slope,speed,s);
System.err.println("huoyanspeed:"+huoyanspeed);
double vtime = huoyanspeed * Time;
System.err.println("vtime:"+vtime);
XY c2 ; c2 = lonLat2Mercator(x1, y1);
XY c1 = GetNextFeature(c2.getX(), c2.getY(), 1.4 * vtime, n,sj,Winddir);
c1 = Mercator2lonLat(c1.getX(), c1.getY());
return c1; }
else { XY c3 = new XY(); c3.setX(x1); c3.setY(y1);
return c3; }
}
注:因林火蔓延涉及因素太多,如静可燃物载量、矿质阻尼系数等存在估值,所以得出的结果仅供参考。