对百度地图路径点进行密度细化处理

最近使用百度地图生成路径规划的路径。

在行驶的路径中有部分是直线,两个点的距离比较长(最长的大约在500左右)。

我这里处理是对超两个点距离超过300米的进行密度细化处理。

大致逻辑:

1.判断两个点的距离是否大于300米。

2.如果超过300米,对点进行细化。

因为处理的是中国地区的点,这里逻辑有不同的地方。

我们身处北半球,也就是北纬,东经地带。

大概分析,路线走向的4种情况。

 

经过实测,细化的点跟百度地图生成的点可以完全融合。

 

代码如下:

  1 /**
  2  * 地图工具
  3  *
  4  * @date 2019-09-04 13:51
  5  */
  6 public class MapUtil {
  7 
  8     /**
  9      * 地球半径 平均值,千米
 10      */
 11     public static final double EARTH_RADIUS = 6371.0;
 12 
 13     private MapUtil() {
 14     }
 15 
 16     /**
 17      * 给定的经度1,纬度1;经度2,纬度2. 计算2个经纬度之间的距离。
 18      *
 19      * @param lat1 经度1
 20      * @param lon1 纬度1
 21      * @param lat2 经度2
 22      * @param lon2 纬度2
 23      * @return 距离(公里、千米)
 24      */
 25     public static double distance(double lat1, double lon1, double lat2, double lon2) {
 26         // 用haversine公式计算球面两点间的距离。
 27         // 经纬度转换成弧度
 28         lat1 = convertDegreesToRadians(lat1);
 29         lon1 = convertDegreesToRadians(lon1);
 30         lat2 = convertDegreesToRadians(lat2);
 31         lon2 = convertDegreesToRadians(lon2);
 32         // 差值
 33         double vLon = Math.abs(lon1 - lon2);
 34         double vLat = Math.abs(lat1 - lat2);
 35         // h is the great circle distance in radians, great circle就是一个球体上的切面,它的圆心即是球心的一个周长最大的圆。
 36         double h = haverSin(vLat) + Math.cos(lat1) * Math.cos(lat2) * haverSin(vLon);
 37         return 2 * EARTH_RADIUS * Math.asin(Math.sqrt(h));
 38     }
 39 
 40     public static double haverSin(double theta) {
 41         double v = Math.sin(theta / 2);
 42         return v * v;
 43     }
 44 
 45     /**
 46      * 将角度换算为弧度。
 47      *
 48      * @param degrees 角度
 49      * @return 弧度
 50      */
 51     public static double convertDegreesToRadians(double degrees) {
 52         return degrees * Math.PI / 180;
 53     }
 54 
 55     /**
 56      * 弧度换算为角度
 57      *
 58      * @param radian 弧度
 59      * @return 角度
 60      */
 61     public static double convertRadiansToDegrees(double radian) {
 62         return radian * 180.0 / Math.PI;
 63     }
 64 
 65     /**
 66      * 对两个点做直线密度细化
 67      * 条件:北半球,北纬,东经
 68      *
 69      * @param lat1 经度1
 70      * @param lon1 纬度1
 71      * @param lat2 经度2
 72      * @param lon2 纬度2
 73      * @return 细化点
 74      */
 75     public static double[] averagePoint(double lat1, double lon1, double lat2, double lon2) {
 76         // 对经度进行偏差计算
 77         // 判断斜率
 78         // 经度斜率,纬度斜率
 79         boolean slopeLat = lat1 > lat2;
 80         boolean slopeLon = lon1 > lon2;
 81         // 斜率差
 82         double avLat;
 83         double avLon;
 84         // 第三个点的位置
 85         double lat3;
 86         double lon3;
 87         // -+
 88         if (slopeLat && slopeLon) {
 89             avLat = averageValue(lat1, lat2);
 90             avLon = averageValue(lon2, lon1);
 91             lat3 = format6(lat1 - avLat);
 92             lon3 = format6(lon1 + avLon);
 93         }
 94         // --
 95         else if (slopeLat && !slopeLon) {
 96             avLat = averageValue(lat1, lat2);
 97             avLon = averageValue(lon1, lon2);
 98             lat3 = format6(lat1 - avLat);
 99             lon3 = format6(lon1 - avLon);
100         }
101         // +-
102         else if (!slopeLat && slopeLon) {
103             avLat = averageValue(lat2, lat1);
104             avLon = averageValue(lon1, lon2);
105             lat3 = format6(lat1 + avLat);
106             lon3 = format6(lon1 - avLon);
107         }
108         // ++
109         else {
110             avLat = averageValue(lat2, lat1);
111             avLon = averageValue(lon2, lon1);
112             lat3 = format6(lat1 + avLat);
113             lon3 = format6(lon1 + avLon);
114         }
115         return new double[]{lat3, lon3};
116     }
117 
118     /**
119      * 计算两点平均差值
120      *
121      * @param d1 点1
122      * @param d2 点2
123      * @return 点差值
124      */
125     public static double averageValue(double d1, double d2) {
126         double d3 = d1 - d2;
127         // 除2,做平均差值
128         return format6(d3 / 2);
129     }
130 
131     /**
132      * 留六位小数
133      *
134      * @param value 小数
135      * @return 小数
136      */
137     public static double format6(double value) {
138         return (double) Math.round(value * 1000000) / 1000000;
139     }
140 }

 

posted @ 2019-09-04 15:31  Se7end  阅读(571)  评论(0编辑  收藏  举报