java使用Dijkstra算法实现地图最短路径模型

最近甲方国企因为换领导要裁撤所有外包员工(听来的早的同事说他们每隔一两年换一波外包,全裁后再根据需求招,满满的套路),我TM才干了四个月,回来西安的第一份工作就这么坑,西安的软件环境真是没得说,还是怀念北京老东家的那伙人,好吧,不得已又得开始找工作,各种工具框架什么的看着真是没劲啊,所谓的java基础是复习了一遍又一遍,忘了一边又一遍,之前勤快的时候敲了N多遍没事看个源码,现在懒了最多也是看看面试题。说起复习技术,最不喜欢看的就是工具,容器中间件等,跟着教程走,记着哪里怎么弄,原理是什么,出现问题怎么处理,话说出现问题大部分人又能怎么处理,现学看看原理+百度+灵活思辨处理呗怎么处理,都是遇到问题主要靠摸索攒经验而已,但这些问题平时基本不会遇到,遇到了也都是现学现用,真是么得意思。再就是框架(特别讨厌面试时问框架原理的三流面试官,这纯粹是在考验记忆力,跟编程没有毛线关系),框架有什么可以问的:大到场景应用,小到灵活巧用,无非就这稍有点用,它也就是个标准工具而已,也么意思的很。相对比个人还是更喜欢场景题,提出场景,怎么设计怎么优化怎么解决,没有标准答案,这多有意思,沟通-思考-商议-设计-开发,多有意思,哈哈。

        说了好多,不过说起技术,个人更喜欢深究摸索算法类的,实现某个模型功能,优化提升效率等等。这篇文章内容是两年半前在上家公司做的,当时拿到的需求就五百字的word文档(关于应急疏散的最优策略和最短路径的设计,吧啦吧啦),写了些看不懂的公式和描述(最后发现是公司领导在网上抄的,他也看不懂),其他就没了。至于这玩意要做啥,做成什么样,没人说也没人会,老板说:“你自己就看着弄,我们项目是应急项目,应急疏散功能是合同上有的,只要最后有这个功能就行,具体什么样你自己定”。

       好吧,万事开头难,既然要做那最起码得差不多点,自此,开启现学现用模式,个人的设计不讲究多复杂,拷贝地图软件最短路径的思路呗,项目有用到GIS地图,那就基于地图做最短路径,然后搜资料文档,摸索实现方案,最后就整了这么一套。

        进入正文:该方式基于地图中路口和路线作为建模数据,在地图中找到一片样本区域,基于这片区域标注出所有的路口节点和路线,在百度API提供的接口中获取标注路口节点的经纬度;针对样本区域中的曲线路段或非路口拐点,将曲线颗粒化为多个直线,再依次获取每个直线截取点(未作为路段起始或结束点的节点),如下图中的黄色点,因为地图上是根据经纬度标绘直线的,曲线或拐点的路段需要分段成多个点标绘。我截取的区域如下:

为什么要这么设计呢,主要还是根据Dijkstra算法的数据需要,Dijkstra算法的详细讲解可以百度了解。根据Dijkstra算法的特点我们得先有符合算法的结构数据:每个点可到达的其他点的集合,集合中可到达的点信息包含点ID和距离,如下:

// 点2: {点3:110 ,点8:100 }
// 点3:{点2:110}
// 点8:{点2:100 ,点9:120}
// 点9:{点8:120 , 点10:90 , 点13:89}
// 点10:{点9:90 ,...}
// 点13:{点9:89 ,... }

准备:

一、表的设计如下,总共两张表:

1.节点表(id,节点名称,经度,维度,是否为路口节点,是否为事故点,是否为安置点,所在路段ID);

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value = "CeNodeConfig对象", description = "路口节点信息表")
public class CeNodeConfig  implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键")
    @TableId(value = "ID", type = IdType.AUTO)
    private Integer id;

    @ApiModelProperty(value = "路口名称")
    private String name;

    @ApiModelProperty(value = "经度(负值表示西经,正值为东经)")
    private String longitude;

    @ApiModelProperty(value = "纬度(负值为南纬,正值为北纬)")
    private String latitude;

    @ApiModelProperty(value = "事故爆发点最近节点  0:不是,1:是")
    private Integer sceneOfAction;

    @ApiModelProperty(value = "安置点最近节点  0:不是,1:是")
    private Integer temporaryShelter;

    @ApiModelProperty(value = "路口节点(0:不是,1:是)")
    private Integer crossingNode;

    @ApiModelProperty(value = "所在路线ID(非路口节点)")
    private Integer sectionId;
}

2.路段表(id,路段名称,路段物理距离,路段阻抗值,路段起始节点ID,路段结束节点ID,是否为双向路段);

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value = "CeSectionConfig对象", description = "路段信息表")
public class CeSectionConfig  implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键")
    @TableId(value = "ID", type = IdType.AUTO)
    private Integer id;

    @ApiModelProperty(value = "路段名")
    private String name;

    @ApiModelProperty(value = "路段物理距离")
    private Double physicalDistance;

    @ApiModelProperty(value = "风险阻抗值")
    private Double riskImpedanceValue;

    @ApiModelProperty(value = "路段起始节点ID")
    private Integer startNodeId;

    @ApiModelProperty(value = "路段结束节点ID")
    private Integer endNodeId;

    @ApiModelProperty(value = "是否为双向路段  0:不是,1:是")
    private Integer bothway;
}

二、数据准备:

使用百度坐标系获取上图中这些节点的经纬度,依次给这些节点定义名称;节点与节点之间的蓝色线为路段,定义路段名称,根据百度API或经纬度计算方法计算每个路段的长度;

将节点和路段的相关数据插入到节点表和路段表中(之前公司的项目,现在只有代码连不到数据库,建表语句离职退了电脑没了,数据就不贴了);

三、数据准备工作完成,开始实现

Dijkstra算法需要的是当前点到其他点以及距离的集合数据,那么先需要数据封装,将我们的节点数据和路段数据封装成算法需要的:

1.先查询节点网数据,根据路段表递归查询并关联获取所有路段数据数据,查询sql如下:

/**
     * 查询指定点可关联到的节点网集合:
     * 1.指定节点作为结束节点递归查出符合双向路段条件的根节点,如果没有根节点则指定节点为根节点;
     * 2.根据根节点查出所有子节点关联的路段信息;
     * 3.根据路段关联查询对应的起始和结束节点数据
     * @Param id 指定点ID
     * @return  关联的节点网集合
     */
    @Select("select d.ID cId, d.NAME cName, d.LONGITUDE cLongi, d.LATITUDE cLati, " +
            " c.ID pId, c.NAME pName, c.LONGITUDE pLongi, c.LATITUDE pLati, " +
            " a.ID sId, a.NAME sName, a.PHYSICAL_DISTANCE sDistance, " +
            " a.RISK_IMPEDANCE_VALUE sRisk, a.BOTHWAY sBothway " +
            " from CE_SECTION_CONFIG a  " +
            " right join ( " +
            " SELECT distinct(ID) id " +
            &
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值