Java实现林火蔓延路径算法

本文涉及的产品
云原生网关 MSE Higress,422元/月
可观测监控 Prometheus 版,每月50GB免费额度
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
简介: 记录正在进行的森林防火项目中林火蔓延功能,本篇文章可以较好的实现森林防火蔓延,但还存在很多不足,如:很多参数只能使用默认值,所以蔓延范围仅供参考。(如果底层设备获取的数据充足,那当我没说)。注:因林火蔓延涉及因素太多,如静可燃物载量、矿质阻尼系数等存在估值,所以得出的结果仅供参考。

 ✨重磅!盹猫的个人小站正式上线啦~诚邀各位技术大佬前来探秘!✨

这里有:

  • 硬核技术干货:编程技巧、开发经验、踩坑指南,带你解锁技术新姿势!
  • 趣味开发日常:代码背后的脑洞故事、工具测评,让技术圈不再枯燥~
  • 独家资源分享:开源项目、学习资料包,助你打怪升级快人一步!

👉 点击直达→ 盹猫猫的个人小站 👈

🌟 来逛逛吧,说不定能挖到你正在找的技术宝藏哦~

目录

一、写作目的

二、参数说明

三、代码方法

1.计算风速修正系数

2.计算坡度修正系数

3.计算火焰强度

4.计算坐标

5.计算蔓延速度

6.经纬度转换

7.主方法调用


欢迎来到 盹猫(>^ω^<)的博客

本篇文章主要介绍了

[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 坡度

三、代码方法

1.计算风速修正系数

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;
}

image.gif

2.计算坡度修正系数

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;
}

image.gif

3.计算火焰强度

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;
}

image.gif

4.计算坐标

 

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;
    }

image.gif

5.计算蔓延速度

 

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));
    }

image.gif

6.经纬度转换

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; }

image.gif

7.主方法调用

 

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; }
    }

image.gif

注:因林火蔓延涉及因素太多,如静可燃物载量、矿质阻尼系数等存在估值,所以得出的结果仅供参考。


如果你对区块链内容感兴趣可以查看我的专栏:小试牛刀-区块链

感谢您的关注和收藏!!!!!!

image.gif 编辑

目录
相关文章
|
1月前
|
机器学习/深度学习 算法 C++
【DFS/回溯算法】2016年蓝桥杯真题之路径之谜详解
题目要求根据城堡北墙和西墙箭靶上的箭数,推断骑士从西北角到东南角的唯一路径。每步移动时向正北和正西各射一箭,同一格不重复经过。通过DFS回溯模拟“拔箭”过程,验证路径合法性。已知箭数约束路径唯一,最终按编号输出行走顺序。
|
2月前
|
传感器 机器学习/深度学习 编解码
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
190 3
|
3月前
|
算法 机器人 定位技术
【VRPTW】基于matlab秃鹰算法BES求解带时间窗的骑手外卖配送路径规划问题(目标函数:最优路径成本 含服务客户数量 服务时间 载量 路径长度)(Matlab代码实现)
【VRPTW】基于matlab秃鹰算法BES求解带时间窗的骑手外卖配送路径规划问题(目标函数:最优路径成本 含服务客户数量 服务时间 载量 路径长度)(Matlab代码实现)
112 0
|
29天前
|
设计模式 算法 搜索推荐
Java 设计模式之策略模式:灵活切换算法的艺术
策略模式通过封装不同算法并实现灵活切换,将算法与使用解耦。以支付为例,微信、支付宝等支付方式作为独立策略,购物车根据选择调用对应支付逻辑,提升代码可维护性与扩展性,避免冗长条件判断,符合开闭原则。
252 35
|
1月前
|
存储 算法 搜索推荐
《数据之美》:Java数据结构与算法精要
本系列深入探讨数据结构与算法的核心原理及Java实现,涵盖线性与非线性结构、常用算法分类、复杂度分析及集合框架应用,助你提升程序效率,掌握编程底层逻辑。
|
2月前
|
机器学习/深度学习 传感器 算法
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
193 2
|
2月前
|
机器学习/深度学习 传感器 算法
基于全局路径的无人地面车辆的横向避让路径规划研究[蚂蚁算法求解](Matlab代码实现)
基于全局路径的无人地面车辆的横向避让路径规划研究[蚂蚁算法求解](Matlab代码实现)
197 8
|
1月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
2月前
|
算法 数据挖掘 区块链
基于遗传算法的多式联运车辆路径网络优优化研究(Matlab代码实现)
基于遗传算法的多式联运车辆路径网络优优化研究(Matlab代码实现)
104 2
|
2月前
|
存储 算法 数据可视化
基于禁忌搜索算法的TSP问题最优路径搜索matlab仿真
本程序基于禁忌搜索算法解决旅行商问题(TSP),旨在寻找访问多个城市的最短路径。使用 MATLAB 2022A 编写,包含城市坐标生成、路径优化及结果可视化功能。通过禁忌列表、禁忌长度与藐视准则等机制,提升搜索效率与解的质量,适用于物流配送、路径规划等场景。