当前位置: 移动技术网 > 移动技术>移动开发>Android > 百度地图实现小车规划路线后平滑移动功能

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

2020年03月09日  | 移动技术网移动技术  | 我要评论

文章目的

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

实现效果

代码下载


下面是实现的关键步骤

集成百度地图

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

规划线路

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

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网