最近项目中需要实现这样一个功能:从当前位置,规划一条最优线路到附近多个工厂的最优线路。必须要有详细的路径坐标点信息。

思路:1.首先 使用汉密尔顿回路算法,求解出当前位置坐标点到附近工厂最短线路的路径。2.借助百度地图API,实现2点间坐标点的详细路径。话不多说,直接整代码:

项目使用的框架是springboot: 参数path格式为:40.465,116.314|40.232,116.352|40.121,116.453|41.121,118.453  经纬度直接用“,”隔开,2个坐标点之间用"|"隔开。这样做的目的是方便前端传值与后台取值。

@GetMapping("/dynamicProgramming")
public AjaxResult dynamicProgramming(HttpServletRequest request,@RequestParam("path") String path) throws Exception{//所有经纬度数组String[] strings = path.split("\\|");double  [] x = new double[strings.length];double [] y = new double[strings.length];for (int i = 0; i < strings.length; i++) {String str = strings[i];String latitude = str.substring(0, str.indexOf(","));String longitude = str.substring(str.lastIndexOf(",") + 1);x[i] = Double.parseDouble(latitude);y[i] = Double.parseDouble(longitude);}//汉密尔顿回路算法求解最短路线的最优路线List<Integer> sort = DynamicProgramming.sort(x, y, strings.length);;List<Map> list = new ArrayList<>();//将返回的规划路线分段调用百度地图api,获取详细坐标for (int i = 0; i < sort.size()-1; i++) {Map<String, Object> steps = new HashMap<>();int qidian = sort.get(i);int zongdian = sort.get(i+1);//出发地String origin = strings[qidian-1];//目的地String destination = strings[zongdian-1];//调用百度地图驾车路线api生成具体路径String url = " http://api.map.baidu.com/directionlite/v1/driving?" +"origin="+origin+"&destination="+destination+"&ak="+baiduAk;String result = BaiduHttpUtils.httpGet(url);List<Map> maps = BaiduHttpUtils.getResult(result);steps.put("step",maps);list.add(steps);}return success(list);
}

算法工具类:DynamicProgramming

package com.chaosting.kiwifruit.web.utils.weixin;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;/*** @Author: zhangweixia* @Description:  汉密尔顿回路算法最短路径动态规划* @Date:Created in 10:35 2020/4/3* @Modified:*/
public class DynamicProgramming {private int citynumbers;//城市数目double s = 0;//总距离int path[];//存放路径,方便计算距离private double[][] distance;private double[][] optimalvalue;//阶段最短路径值矩阵private int[][] optimalchoice;//阶段最优策略矩阵public DynamicProgramming(int citynumbers) {this.citynumbers = citynumbers;}public void readData(double [] x,double [] y) throws IOException {//  int [] x = {2066,935,1270,1389,984,2253};// int [] y = {2333,1304,200,700,2810,478};distance = new double[citynumbers][citynumbers];//距离矩阵//计算距离矩阵for (int i = 0; i < citynumbers; i++) {for (int j = 0; j < citynumbers; j++) {distance[i][j] = Math.sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));//计算欧式距离}}int h = (int) Math.pow(2, citynumbers - 1);optimalvalue = new double[citynumbers][h];optimalchoice = new int[citynumbers][h];}public List solve() {double min = Double.MAX_VALUE;//确保会更新int mink = 0;//计算第一列地值for (int i = 0; i < citynumbers; i++) {optimalvalue[i][0] = distance[i][0];}for (int i = 1; i < (Math.pow(2, citynumbers - 1)); i++) {for (int j = 1; j < citynumbers; j++) {int k = 0;if (judge(i, j) == 0) {//确定j不包含在i代表的集合中String a = com.chaosting.fireStation.service.util.DynamicProgramming.binary(i, citynumbers - 1);for (int w = a.length(); w > 0; w--) {k = a.charAt(a.length() - w) - 48;//k为0或者1if (k == 1) {k = k * w;//此时的k为选择的集合中的某个值double y = (distance[j][k] + optimalvalue[k][(int) (i - Math.pow(2, k - 1))]);if (y < min) {min = (distance[j][k] + optimalvalue[k][(int) (i - Math.pow(2, k - 1))]);mink = k;}}}if (min < Double.MAX_VALUE) {//确定min是否变化,有变化再写入矩阵optimalvalue[j][i] = min;optimalchoice[j][i] = mink;min = Double.MAX_VALUE;}}}}min = Double.MAX_VALUE;//更新minint i = (int) (Math.pow(2, citynumbers - 1) - 1);//更新最后一列for (int k = citynumbers - 1; k > 0; k--) {double x = (distance[0][k] + optimalvalue[k][(int) (i - Math.pow(2, k - 1))]);if (x < min) {min = x;mink = k;}}optimalvalue[0][i] = min;optimalchoice[0][i] = mink;path = new int[citynumbers + 1];path[0] = 1;int c = 1;for (int j = 0; i > 0; ) {j = optimalchoice[j][i];i = (int) (i - Math.pow(2, j - 1));path[c++] = j + 1;}path[c++] = 1;List<Integer> list = new ArrayList<>();for (i = 0; i < citynumbers; i++) {//System.out.print(path[i] + "->");list.add(path[i]);s = s + distance[path[i] - 1][path[i + 1] - 1];}return list;}//判断j是否在i表示的集合中public int judge(int i, int j) {String a = com.chaosting.fireStation.service.util.DynamicProgramming.binary(i, citynumbers - 1);int b = a.charAt(a.length() - j) - 48;return b;}//给定一个十进制数,输出一个指定位数的二进制形式字符串public static String binary(int decNum, int digit) {String binStr = "";for (int i = digit - 1; i >= 0; i--) {binStr += (decNum >> i) & 1;}return binStr;}public static void main(String[] args) throws Exception {double [] x = {0,93.568};double [] y = {0,13.865};List sort = sort(x, y, 2);System.out.println(sort);}public static List<Integer> sort(double [] x,double [] y,int number) throws Exception{com.chaosting.fireStation.service.util.DynamicProgramming tsp = new com.chaosting.fireStation.service.util.DynamicProgramming(number);//建立对象tsp.readData(x,y);List<Integer> list = tsp.solve();return list;}
}

百度工具类:BaiduHttpUtils

package com.chaosting.kiwifruit.web.utils.weixin;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.util.StringUtils;import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;/*** @Author: zhangweixia* @Description:  请求百度开发接口工具类* @Date:Created in 14:34 2020/2/26* @Modified:*/
public class BaiduHttpUtils {/*** GET请求*/public static String httpGet(String httpUrl) throws Exception {//创建一个url对象URL url = new URL(httpUrl);//打开链接,强转为httpUrlConnectionHttpURLConnection connection = (HttpURLConnection) url.openConnection();//设置链接方式connection.setRequestMethod("GET");//设置超时时间connection.setConnectTimeout(3000);//设置读取超时时间connection.setReadTimeout(5000);//发送请求connection.connect();//获取输入流InputStream inputStream = connection.getInputStream();//封装输入流BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));//接收返回的数据StringBuffer stringBuffer = new StringBuffer();String line = null;while ((line = bufferedReader.readLine()) != null){stringBuffer.append(line);}//关流bufferedReader.close();inputStream.close();//关闭链接connection.disconnect();return stringBuffer.toString();}/*** 百度驾车路径解析*/public static List<Map> getResult(String baiduResult){JSONObject jsonObject = JSON.parseObject(baiduResult);//0.获得结果集json对象Object result = jsonObject.get("result");JSONObject resultJsonObject = JSON.parseObject(result.toString());//4.获得第一页路线routesString routes = resultJsonObject.getString("routes");JSONArray routesArray = JSON.parseArray(routes);System.out.println("routes总共有="+routesArray.size());//默认取第一条路线JSONObject routeJsonObject = JSON.parseObject(routesArray.get(0).toString());//本条路线有几个step 步骤String steps = routeJsonObject.getString("steps");JSONArray stepsArray = JSON.parseArray(steps);System.out.println("steps总共有="+stepsArray.size());List<Map> maps = new ArrayList<>();for (int i = 0; i < stepsArray.size(); i++) {Map map1 = new HashMap();JSONObject jsonStep = JSON.parseObject(stepsArray.get(i).toString());String start_location = jsonStep.getString("start_location");JSONObject startObject = JSON.parseObject(start_location);String longitude = startObject.getString("lng");String latitude = startObject.getString("lat");map1.put("latitude",latitude);map1.put("longitude",longitude);maps.add(map1);}return maps;}/*** 百度地址解析*/public static Map getJson(String baiduResult) {JSONObject jsonObject = JSON.parseObject(baiduResult);String status = jsonObject.getString("status");//0String message = jsonObject.getString("message");//成功Map<Object, Object> hashMap = new HashMap<>();hashMap.put("status", status);hashMap.put("message", message);if (!"0".equals(status)) return hashMap;//0.获得结果集json对象Object result = jsonObject.get("result");JSONObject resultJsonObject = JSON.parseObject(result.toString());//1.获得出发地城市名称Object origin = resultJsonObject.get("origin");JSONObject originJsonObject = JSON.parseObject(origin.toString());String origin_city_name = originJsonObject.get("city_name").toString();//2.获得目的地城市名称Object destination = resultJsonObject.get("destination");JSONObject destinationJsonObject = JSON.parseObject(destination.toString());String destination_city_name = destinationJsonObject.getString("city_name");//3.获得所有路线的总数String total = resultJsonObject.getString("total");//计算总页数int totalInt = Integer.parseInt(total);//4.获得第一页路线routesString routes = resultJsonObject.getString("routes");JSONArray routesArray = JSON.parseArray(routes);Map<String, Object> map = new LinkedHashMap<>();Map<String, Object> dataMap = new LinkedHashMap<>();dataMap.put("total", totalInt);//当前页数量dataMap.put("pageSize", routesArray.size());dataMap.put("origin", origin_city_name);dataMap.put("destination", destination_city_name);map.put("status", status);map.put("message", message);//5.解析第一页的所有路线List<Map> routeList = new ArrayList<>();for (int i = 0; i < routesArray.size(); i++) {int m = 1;//Map<String, String> sunMap = new HashMap<>();Map<String, Object> routeMap = new LinkedHashMap<>();Map sunMap = new LinkedHashMap<String, String>();List<Map> sunMapList = new ArrayList<>();JSONObject routeJsonObject = JSON.parseObject(routesArray.get(i).toString());//本条路线的总距离(米)String distanceType = routeJsonObject.getString("distance");//将米转换成公里,保留小数点后一位,四舍五入String distance = getKM(distanceType);//本条路线的总耗时(秒)String duration = routeJsonObject.getString("duration");//将秒转换成时分秒duration = DateUtil.getDuratiom(duration);routeMap.put("distance", distance);routeMap.put("duration", duration);//6.本条路线的总票价String price = routeJsonObject.getString("price");routeMap.put("price", price);//本条路线有几个step 步骤String steps = routeJsonObject.getString("steps");JSONArray stepsArray = JSON.parseArray(steps);//System.out.println("第"+i+"条路线:"+"总距离="+distance+"。总耗时="+duration+"。步骤="+steps);//每个子步骤的具体方案for (int j = 0; j < stepsArray.size(); j++) {//每个子步骤 schemesString schemes = stepsArray.get(j).toString();//解析每个子步骤下面的孙子步骤JSONArray schemesArray = JSON.parseArray(schemes);for (int k = 0; k < schemesArray.size(); k++) {String sun = schemesArray.get(k).toString();JSONObject sunJsonObject = JSON.parseObject(sun);//1.获取孙子步骤的描述信息String instructions = sunJsonObject.getString("instructions");//2.孙子步骤的距离String sunDistanceType = sunJsonObject.getString("distance");String sunDistance = getKM(sunDistanceType);//3.孙子步骤的耗时String sunDuration = sunJsonObject.getString("duration");sunDuration = DateUtil.getDuratiom(sunDuration);//.交通方式String vehicle_info = sunJsonObject.getString("vehicle_info");JSONObject vehicleJsonObject = JSON.parseObject(vehicle_info);String type = vehicleJsonObject.getString("type");//存入步骤信息,因机场有些描述信息没有,但还是有步骤,当没描述信息就不存了,跳出此次循环if (StringUtils.isEmpty(instructions)) {break;}//type为1是火车,type为2是飞机if (Integer.parseInt(type) == 1 || Integer.parseInt(type) == 2) {String detail = vehicleJsonObject.getString("detail");JSONObject detailJsonObject = JSON.parseObject(detail);//火车车次String name = detailJsonObject.getString("name");//总票价String detailPrice = detailJsonObject.getString("price");//上车火车站名String departureStation = detailJsonObject.getString("departure_station");//下火车站名String arriveStation = detailJsonObject.getString("arrive_station");//发车时间String departureTime = detailJsonObject.getString("departure_time");//到站时间String arriveTime = detailJsonObject.getString("arrive_time");sunMap.put("第" + m + "步", instructions + "|距离=" + sunDistance + "|耗时=" + sunDuration + "|班次" + name + "|出发时间=" + departureTime + "|到达时间=" + arriveTime);} else {sunMap.put("第" + m + "步", instructions + "|距离=" + sunDistance + "|耗时=" + sunDuration);}System.out.println("第" + (i + 1) + "条路线:" + "第" + m + "步=" + instructions);m++;}}sunMapList.add(sunMap);routeMap.put("route", sunMapList);routeList.add(routeMap);}dataMap.put("routes", routeList);map.put("result", dataMap);return map;}/*** 米转换成公里,保留小数点后一位*/public static String getKM(String distance) {//换算成公里,保留小数点后一位,四舍五入double distanceDouble = Double.parseDouble(distance);double b = Math.rint(distanceDouble / 100) / 10;distance = b + "公里";return distance;}}

返回给前端的路径格式:

"code": 0,

"data": [

{

"step": [

{

"latitude": "40.479965606385",

"longitude": "116.31932607972"

},

{

"latitude": "40.479900370146",

"longitude": "116.32667969845"

}

]

},

{

"step": [

{

"latitude": "41.129388293691",

"longitude": "118.447649255"

},

{

"latitude": "41.122830549249",

"longitude": "118.43334984823"

}

]

},

{

"step": [

{

"latitude": "40.120992095059",

"longitude": "116.45298917858"

},

{

"latitude": "40.124614014625",

"longitude": "116.45278705984"

}

]

}

]

 

定位当前位置(坐标点)到 附近多个位置(坐标点)最短路径动态规划(汉密尔顿回路算法整合百度地图API)相关推荐

  1. 【百度地图API·javascriptapi】地图定位、创建自定义图标、获取用户点击位置

    引言 地图在网页上的应用远不止于展示,我们可以借助百度地图定位用户的当前位置,在地图上创建自定义的标记,或者在用户点击地图的时候,获取用户点击位置的经纬度. 定位 百度地图给用户提供了专门的定位api ...

  2. vue调用百度地图API实现点击相应位置切换地图定位

    vue调用百度地图API实现点击相应位置切换地图定位 1.需求分析 在页面显示地图,初始状态显示上海市,地图上有特定地点的标注. 左侧为建筑(地点)列表,点击某个地点右侧地图定位到其地理位置并显示具体 ...

  3. 百度地图API,定位您的当前位置

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到网站 1.介绍 利用百度地图的API来定位您的所属位置,这个位置返回的是经纬度,而不是具体的汉字位置.利用经 ...

  4. 使用百度地图api搜索两点位置、连线、计算距离、ip定位

    欢迎大家点一个关注,支持我的原创文章,谢谢! 正文 现在在企业做web项目时,偶尔会用到地图功能,而当前最流行的无疑是百度地图了,百度地图API为应用开发者提供了强大的功能,以下就介绍关于本人在做项目 ...

  5. 百度地图API后台持续定位、指南针改变位置问题

    最近的需要用到后台持续定位,项目中又是用的百度地图API,遇到点麻烦: 1.进入后台,手机静置,定位持续16分钟左右就停止了,但是还是无限后台效果:但如果一直运动,让定位持续更新,定位服务一直保持 其 ...

  6. Vue 百度地图API实现定位用户位置功能

    一.进入百度地图 百度地图开放平台 | 百度地图API SDK | 地图开发 (baidu.com) 1.1注册登录 1.2进入控制台 应用管理->我的应用->创建应用 1.3创建应用 填 ...

  7. 百度地图利用位置提供服务器,利用百度地图API获取当前位置信息的实例

    利用百度地图API可以做很多事情,个人感觉最核心也是最基础的就是定位功能了.这里分享一个制作的JS可以实现登录网页后定位: var map; var gpsPoint; var baiduPoint; ...

  8. 【百度地图api】之获取当前用户地理位置-浏览器定位

    1.通过html5 获取当前gps坐标,不过这种一般PC网页很多都不适用,一般用作手机网页 HTML5 Geolocation API (地理位置应用程序接口) 目前PC浏览器支持情况: Firefo ...

  9. 【百度地图API】如何在地图上添加标注?——另有:坐标拾取工具+打车费用接口介绍

    一.如何进行标注 1.首先,我们需要找准标注的位置.比如,我想标注"中央民族大学"附近的网球场.那么,我转到坐标拾取工具页面,请点击http://openapi.baidu.com ...

最新文章

  1. 中文扩增子分析视频教程推荐
  2. SAP ABAP 点滴记录
  3. 记一则Hadoop DataNode OOM故障,以及解决方案
  4. 架构,框架,模式,模块、组件、插件的含义和区别
  5. 一个逼格很低的appium自动化测试框架
  6. 经济危机拒绝穷潇洒 试水充电战危机
  7. MVC4中EasyUI Tree异步加载JSON数据生成树
  8. 滑动cell的时候执行动画效果
  9. [20171220]toad plsql显示整形的bug.txt
  10. django和mysql
  11. JAVA——网络编程
  12. 【Python】numpy矩阵运算大全
  13. 基于 软件体系结构(第3版)考试重点和复习指南
  14. Python修改图片大小
  15. python爬取英雄联盟所有皮肤_python爬取lol英雄皮肤
  16. 《蜗居》的经典台词(转载)二
  17. 深圳市福田高中2021年高考成绩查询,2020年深圳高中梯队排行一览!2021年十大或有新格局?...
  18. 职场28岁现象:最好的关于职业规划的文章
  19. STM32F105RCT6使用CubeMX初始化工程——3:初始化ADC采样
  20. must,must_not,should组合关系以及OR和AND

热门文章

  1. 钉钉消息防撤回功能研究与实现-可查看历史消息[文件/图文/管理员/链接 撤回拦截]
  2. RGB颜色对照表#FFFFFF
  3. 33 | MySQL全表扫描会将内存打爆?(看了这篇你就赚)
  4. sumsung s4 i959 刷回官方包 救砖
  5. 【有利可图网】PS实战系列:学会了这个调色小技巧,你也能点石成金
  6. Windows 10 无法访问共享文件夹
  7. Tomcat手动部署Web项目详细步骤
  8. 股票市场周期波动分析的MATLAB实现(1)
  9. 网上商业模式优缺点分析
  10. H5调用微信原生扫码能力 (uniapp版本)