欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2022-06-17 14:10:33
文章目的 项目开发所需,所以结合百度地图提供的小车平滑轨迹移动,自己写的demo 实现效果 代码下载 下面是实现的关键步骤 集成百度地图 怎么集成自然是...

文章目的

项目开发所需,所以结合百度地图提供的小车平滑轨迹移动,自己写的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();
  }