文章目的
项目开发所需,所以结合百度地图提供的小车平滑轨迹移动,自己写的demo
实现效果
代码下载
下载链接
下面是实现的关键步骤
集成百度地图
怎么集成自然是看百度地图开发平台提供的文档。
文档连接
规划线路
看百度地图的文档,写一个规划线路的工具类(驾车的)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
package com.wzhx.car_smooth_move_demo.utils; import android.util.Log; import com.baidu.mapapi.search.route.BikingRouteResult; import com.baidu.mapapi.search.route.DrivingRoutePlanOption; import com.baidu.mapapi.search.route.DrivingRouteResult; import com.baidu.mapapi.search.route.IndoorRouteResult; import com.baidu.mapapi.search.route.MassTransitRouteResult; import com.baidu.mapapi.search.route.OnGetRoutePlanResultListener; import com.baidu.mapapi.search.route.PlanNode; import com.baidu.mapapi.search.route.RoutePlanSearch; import com.baidu.mapapi.search.route.TransitRouteResult; import com.baidu.mapapi.search.route.WalkingRouteResult; import com.wzhx.car_smooth_move_demo.listener.OnGetDrivingResultListener; public class RoutePlanUtil { private RoutePlanSearch mRoutePlanSearch = RoutePlanSearch.newInstance(); private OnGetDrivingResultListener getDrivingResultListener; private OnGetRoutePlanResultListener getRoutePlanResultListener = new OnGetRoutePlanResultListener() { @Override public void onGetWalkingRouteResult(WalkingRouteResult walkingRouteResult) { } @Override public void onGetTransitRouteResult(TransitRouteResult transitRouteResult) { } @Override public void onGetMassTransitRouteResult(MassTransitRouteResult massTransitRouteResult) { } @Override public void onGetDrivingRouteResult(DrivingRouteResult drivingRouteResult) { Log.e( "测试" , drivingRouteResult.error + ":" + drivingRouteResult.status); getDrivingResultListener.onSuccess(drivingRouteResult); } @Override public void onGetIndoorRouteResult(IndoorRouteResult indoorRouteResult) { } @Override public void onGetBikingRouteResult(BikingRouteResult bikingRouteResult) { } }; public RoutePlanUtil(OnGetDrivingResultListener getDrivingResultListener) { this .getDrivingResultListener = getDrivingResultListener; this .mRoutePlanSearch.setOnGetRoutePlanResultListener( this .getRoutePlanResultListener); } public void routePlan(PlanNode startNode, PlanNode endNode){ mRoutePlanSearch.drivingSearch(( new DrivingRoutePlanOption()) .from(startNode).to(endNode) .policy(DrivingRoutePlanOption.DrivingPolicy.ECAR_TIME_FIRST) .trafficPolicy(DrivingRoutePlanOption.DrivingTrafficPolicy.ROUTE_PATH_AND_TRAFFIC)); } } |
规划线路后需要将实时路况索引保存,为后面画图需要
1
2
3
4
5
6
7
8
9
10
|
// 设置路段实时路况索引 List<DrivingRouteLine.DrivingStep> allStep = selectedRouteLine.getAllStep(); mTrafficTextureIndexList.clear(); for ( int j = 0 ; j < allStep.size(); j++) { if (allStep.get(j).getTrafficList() != null && allStep.get(j).getTrafficList().length > 0 ) { for ( int k = 0 ; k < allStep.get(j).getTrafficList().length; k++) { mTrafficTextureIndexList.add(allStep.get(j).getTrafficList()[k]); } } } |
要将路线规划的路线上的路段再细分(切割),这样小车移动才会平滑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
/** * 将规划好的路线点进行截取 * 参考百度给的小车平滑轨迹移动demo实现。(循环的算法不太懂) * @param routeLine * @param distance * @return */ private ArrayList<LatLng> divideRouteLine(ArrayList<LatLng> routeLine, double distance) { // 截取后的路线点的结果集 ArrayList<LatLng> result = new ArrayList<>(); mNewTrafficTextureIndexList.clear(); for ( int i = 0 ; i < routeLine.size() - 1 ; i++) { final LatLng startPoint = routeLine.get(i); final LatLng endPoint = routeLine.get(i + 1 ); double slope = getSlope(startPoint, endPoint); // 是不是正向的标示 boolean isYReverse = (startPoint.latitude > endPoint.latitude); boolean isXReverse = (startPoint.longitude > endPoint.longitude); double intercept = getInterception(slope, startPoint); double xMoveDistance = isXReverse ? getXMoveDistance(slope, distance) : - 1 * getXMoveDistance(slope, distance); double yMoveDistance = isYReverse ? getYMoveDistance(slope, distance) : - 1 * getYMoveDistance(slope, distance); ArrayList<LatLng> temp1 = new ArrayList<>(); for ( double j = startPoint.latitude, k = startPoint.longitude; !((j > endPoint.latitude) ^ isYReverse) && !((k > endPoint.longitude) ^ isXReverse); ) { LatLng latLng = null ; if (slope == Double.MAX_VALUE) { latLng = new LatLng(j, k); j = j - yMoveDistance; } else if (slope == 0.0 ) { latLng = new LatLng(j, k - xMoveDistance); k = k - xMoveDistance; } else { latLng = new LatLng(j, (j - intercept) / slope); j = j - yMoveDistance; } final LatLng finalLatLng = latLng; if (finalLatLng.latitude == 0 && finalLatLng.longitude == 0 ) { continue ; } mNewTrafficTextureIndexList.add(mTrafficTextureIndexList.get(i)); temp1.add(finalLatLng); } result.addAll(temp1); if (i == routeLine.size() - 2 ) { result.add(endPoint); // 终点 } } return result; } |
最后是开启子线程,对小车状态进行更新(车头方向和小车位置)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
/** * 循环进行移动逻辑 */ public void moveLooper() { moveThread = new Thread() { public void run() { Thread thisThread = Thread.currentThread(); while (!exit) { for ( int i = 0 ; i < latLngs.size() - 1 ; ) { if (exit) { break ; } for ( int p = 0 ; p < latLngs.size() - 1 ; p++) { // 这是更新索引的条件,这里总是为true // 实际情况可以是:当前误差小于5米 DistanceUtil.getDistance(mCurrentLatLng, latLngs.get(p)) <= 5) // mCurrentLatLng 这个小车的当前位置得自行获取得到 if ( true ) { // 实际情况的索引更新 mIndex = p; mIndex++; // 模拟就是每次加1 runOnUiThread( new Runnable() { @Override public void run() { Toast.makeText(mContext, "当前索引:" + mIndex, Toast.LENGTH_SHORT).show(); } }); break ; } } // 改变循环条件 i = mIndex + 1 ; if (mIndex >= latLngs.size() - 1 ) { exit = true ; break ; } // 擦除走过的路线 int len = mNewTrafficTextureIndexList.subList(mIndex, mNewTrafficTextureIndexList.size()).size(); Integer[] integers = mNewTrafficTextureIndexList.subList(mIndex, mNewTrafficTextureIndexList.size()).toArray( new Integer[len]); int [] index = new int [integers.length]; for ( int x = 0 ; x < integers.length; x++) { index[x] = integers[x]; } if (index.length > 0 ) { mPolyline.setIndexs(index); mPolyline.setPoints(latLngs.subList(mIndex, latLngs.size())); } // 这里是小车的当前点和下一个点,用于确定车头方向 final LatLng startPoint = latLngs.get(mIndex); final LatLng endPoint = latLngs.get(mIndex + 1 ); mHandler.post( new Runnable() { @Override public void run() { // 更新小车的位置和车头的角度 if (mMapView == null ) { return ; } mMoveMarker.setPosition(startPoint); mMoveMarker.setRotate(( float ) getAngle(startPoint, endPoint)); } }); try { // 控制线程更新时间间隔 thisThread.sleep(TIME_INTERVAL); } catch (InterruptedException e) { e.printStackTrace(); } } } } }; // 启动线程 moveThread.start(); } |
原文链接:https://blog.csdn.net/weixin_29210367/article/details/104004293