百度地图实现小车规划路线后平滑移动

文章目的

项目开发所需,所以结合百度地图提供的小车平滑轨迹移动,自己写的demo

实现效果

演示gif

代码下载

下载链接
下面是实现的关键步骤

集成百度地图

怎么集成自然是看百度地图开发平台提供的文档。
文档连接

规划线路

看百度地图的文档,写一个规划线路的工具类(驾车的)

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

规划线路后需要将实时路况索引保存,为后面画图需要

// 设置路段实时路况索引
                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]);
                        }
                    }
                }

要将路线规划的路线上的路段再细分(切割),这样小车移动才会平滑

/**
     * 将规划好的路线点进行截取
     * 参考百度给的小车平滑轨迹移动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;
    }

最后是开启子线程,对小车状态进行更新(车头方向和小车位置)

 /**
     * 循环进行移动逻辑
     */
    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();
    }
发布了4 篇原创文章 · 获赞 2 · 访问量 353

猜你喜欢

转载自blog.csdn.net/weixin_29210367/article/details/104004293
今日推荐