仿滴滴打车 车辆运动
2016-08-01 15:14
691 查看
因工作需要, 写了一份类似于滴滴打车 车辆运动的 demo;
功能:1.可以实现车辆位移变化及车辆车头转向;2.集成了百度地图;实现了地理坐标反取;
代码:
MapActivity.class
package com.example.dididache;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BaiduMap.OnMapStatusChangeListener;
import com.baidu.mapapi.map.BaiduMap.OnMarkerDragListener;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.core.SearchResult;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult;
public class MapActivity extends Activity implements OnGetGeoCoderResultListener, OnClickListener {
private MapView mMapView = null;
private GeoCoder mSearch = null;
private BaiduMap mBaiduMap = null;
private Marker carMarker;
private BitmapDescriptor bdA;
private MarkerOptions ooA;
}
//还有一个车辆信息bean;CarRunInfo.class
package com.example.dididache;
import com.baidu.mapapi.model.LatLng;
public class CarRunInfo {
}
功能:1.可以实现车辆位移变化及车辆车头转向;2.集成了百度地图;实现了地理坐标反取;
代码:
MapActivity.class
package com.example.dididache;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BaiduMap.OnMapStatusChangeListener;
import com.baidu.mapapi.map.BaiduMap.OnMarkerDragListener;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.core.SearchResult;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult;
public class MapActivity extends Activity implements OnGetGeoCoderResultListener, OnClickListener {
private MapView mMapView = null;
private GeoCoder mSearch = null;
private BaiduMap mBaiduMap = null;
private Marker carMarker;
private BitmapDescriptor bdA;
private MarkerOptions ooA;
private LatLng latlng0 = new LatLng(39.977552, 116.320331); // 人民大学;左上 private LatLng latlng1 = new LatLng(39.977552, 116.460036); // 香河园街道 右上 private LatLng latlng2 = new LatLng(39.855805, 116.320331); // 左下 private LatLng latlng3 = new LatLng(39.855805, 116.460036); // 右下; private List<LatLng> latlngsTop = new ArrayList<LatLng>(); private List<LatLng> latlngsLeft = new ArrayList<LatLng>(); private List<LatLng> latlngsRight = new ArrayList<LatLng>(); private List<LatLng> latlngsBottom = new ArrayList<LatLng>(); private CarRunInfo carInfo; private Thread t; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SDKInitializer.initialize(getApplicationContext()); setContentView(R.layout.activity_main); mMapView = (MapView) findViewById(R.id.bmapView); findViewById(R.id.btn_car_run).setOnClickListener(this); bdA = BitmapDescriptorFactory.fromResource(R.drawable.xiaoche1); mBaiduMap = mMapView.getMap(); MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(12.0f); mBaiduMap.setMapStatus(msu); mSearch = GeoCoder.newInstance(); mSearch.setOnGetGeoCodeResultListener(this); mBaiduMap.setOnMapStatusChangeListener(new OnMapStatusChangeListener() { @Override public void onMapStatusChangeStart(MapStatus arg0) { } @Override public void onMapStatusChangeFinish(MapStatus arg0) { LatLng ptCenter = mBaiduMap.getMapStatus().target; mSearch.reverseGeoCode(new ReverseGeoCodeOption().location(ptCenter)); } @Override public void onMapStatusChange(MapStatus arg0) { } }); initOverlay(); initCarInfo(); getPointData(); } private void initCarInfo() { carInfo = new CarRunInfo(); } /** * 服务器返回 车辆的 实时坐标。 */ private void getPointData() { latlngsTop = computEdgepoints(latlng0, latlng1, latlngsTop, Edge.Top); latlngsLeft = computEdgepoints(latlng0, latlng2, latlngsLeft, Edge.Left); latlngsRight = computEdgepoints(latlng1, latlng3, latlngsRight, Edge.Right); latlngsBottom = computEdgepoints(latlng2, latlng3, latlngsBottom, Edge.Bottom); } enum Edge { Top, Left, Right, Bottom; } /** * 计算添加模拟数据; * * @param latlng1 * @param latlng2 * @param latlngs * @param edge * @return */ public List<LatLng> computEdgepoints(LatLng latlng1, LatLng latlng2, List<LatLng> latlngs, Edge edge) { // 每边采集300个点,每秒采集10个点; double distance = 0; if (edge == Edge.Top) { distance = latlng2.longitude - latlng1.longitude; for (int i = 0; i < 300; i++) { latlngs.add(new LatLng(latlng1.latitude, latlng1.longitude + (i + 1) * (distance / 300))); } } else if (edge == Edge.Left) { distance = latlng1.latitude - latlng2.latitude; for (int i = 0; i < 300; i++) { latlngs.add(new LatLng(latlng2.latitude + (i + 1) * (distance / 300), latlng2.longitude)); } } else if (edge == Edge.Right) { distance = latlng2.latitude - latlng1.latitude; for (int i = 0; i < 300; i++) { latlngs.add(new LatLng(latlng1.latitude + (i + 1) * (distance / 300), latlng2.longitude)); } } else if (edge == Edge.Bottom) { distance = latlng1.longitude - latlng2.longitude; for (int i = 0; i < 300; i++) { latlngs.add(new LatLng(latlng1.latitude, latlng2.longitude + (i + 1) * (distance / 300))); } } return latlngs; } /** * 转向 * * @param latlng1 * @param latlng2 * @param carMarker * @param errorRange * 误差范围, 大于 errorRange 值 可视为 转向有效值; */ public void changeCarOrientation(LatLng latlng1, LatLng latlng2, Marker carMarker, double errorRange) { if (latlng1.latitude == latlng2.latitude && latlng1.longitude == latlng2.longitude) { } else { // 获取下一个车头朝向; double nextOrientation = getNextOrientation(latlng1, latlng2); // 获取当前车头朝向; double currentAngle = carInfo.getAngle(); // 逆时针 角度为负值; if (Math.abs(nextOrientation - currentAngle) > errorRange) { carInfo.setAngle(nextOrientation); System.out.println("nextOrientation:" + nextOrientation + ",currentAngle:" + currentAngle); float computAngle = (float) computRotateAngle(currentAngle, nextOrientation); carMarker.setRotate(carMarker.getRotate() + computAngle);// 逆时针; System.out.println("computAngle:" + computAngle); } } } // 负值--顺时针旋转; private double computRotateAngle(double currentAngle, double nextAngle) { return nextAngle - currentAngle; } /** * 获取下一个车的方向; * * @param latlng1 * @param latlng2 * @return */ public double getNextOrientation(LatLng latlng1, LatLng latlng2) { double angle; // 求出三边边长; double a, b, c, a1, b1; a1 = latlng2.latitude - latlng1.latitude; b1 = latlng2.longitude - latlng1.longitude; double latitudeDif = Math.abs(a1); double longitudeDif = Math.abs(b1); a = latitudeDif;// 纬度; b = longitudeDif; c = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2)); if (a == 0) { // 车头朝向 0或 180; // 纬度共有90度。赤道为0度,向两极排列,圈子越小,度数越大。 if ((latlng2.longitude - latlng1.longitude) < 0) {// 经度; angle = 180; } else { angle = 0; } } else if (b == 0) { if ((latlng2.latitude - latlng1.latitude) < 0) {// 纬度; angle = 270; } else { angle = 90; } } else { System.out.println("a1:" + a1 + ",b1:" + b1); System.out.println((a1 > 0) + "," + (b1 > 0)); angle = Math.toDegrees(Math.acos(b / c)); if (a1 < 0 && b1 > 0) { angle = 360 - angle; } else if (a1 > 0 4000 && b1 > 0) { } else if (a1 > 0 && b1 < 0) { angle = 180 - angle; } else if (a1 < 0 && b1 < 0) { angle = 180 + angle; } } return angle; } private boolean isRun = false; public void carRun() { if (!isRun) { t = new Thread(new Runnable() { @Override public void run() { isRun = true; SystemClock.sleep(200); runPoints(latlngsTop); runPoints(latlngsRight); runPoints(latlngsBottom); runPoints(latlngsLeft); isRun = false; } }); t.start(); } } private void runPoints(List<LatLng> latlngs) { try { for (int i = 0; i < latlngs.size(); i++) { Thread.sleep(50); changeCarPosition(latlngs, i); } } catch (InterruptedException e) { e.printStackTrace(); } } /** * 改变车辆位移及朝向 * * @param latlngs * @param i */ private void changeCarPosition(List<LatLng> latlngs, int i) { if (i < latlngs.size() - 1) { changeCarOrientation(latlngs.get(i), latlngs.get(i + 1), carMarker, 2); } carMarker.setPosition(latlngs.get(i)); } @Override public void onGetGeoCodeResult(GeoCodeResult result) { MapStatusUpdate status = MapStatusUpdateFactory.newLatLng(result.getLocation()); mBaiduMap.animateMapStatus(status); Toast.makeText(MapActivity.this, result.getAddress(), Toast.LENGTH_LONG).show(); } @Override public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) { if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) { Toast.makeText(MapActivity.this, "unknow", Toast.LENGTH_LONG).show(); return; } mBaiduMap.setMapStatus(MapStatusUpdateFactory.newLatLng(result.getLocation())); Toast.makeText(MapActivity.this, result.getAddressDetail().city + " " + result.getAddressDetail().district + " " + result.getAddressDetail().street + result.getAddressDetail().streetNumber, Toast.LENGTH_LONG).show(); } public void initOverlay() { // add marker overlay LatLng llA = new LatLng(latlng0.latitude, latlng0.longitude); ooA = new MarkerOptions().position(llA).icon(bdA).zIndex(9).draggable(false); carMarker = (Marker) (mBaiduMap.addOverlay(ooA)); mBaiduMap.setOnMarkerDragListener(new OnMarkerDragListener() { public void onMarkerDrag(Marker marker) { } public void onMarkerDragEnd(Marker marker) { Toast.makeText(MapActivity.this, "拖拽结束,新位置:" + marker.getPosition().latitude + ", " + marker.getPosition().longitude, Toast.LENGTH_LONG).show(); } public void onMarkerDragStart(Marker marker) { } }); } @Override public void onClick(View v) { carRun(); } @Override protected void onDestroy() { super.onDestroy(); mMapView.onDestroy(); } @Override protected void onResume() { super.onResume(); mMapView.onResume(); } @Override protected void onPause() { super.onPause(); mMapView.onPause(); }
}
//还有一个车辆信息bean;CarRunInfo.class
package com.example.dididache;
import com.baidu.mapapi.model.LatLng;
public class CarRunInfo {
private LatLng carPosition = new LatLng(39.977552, 116.320331); private double angle = 270; public LatLng getCarPosition() { return carPosition; } public void setCarPosition(LatLng carPosition) { this.carPosition = carPosition; } public double getAngle() { return angle; } public void setAngle(double angle) { this.angle = angle; }
}
相关文章推荐
- openlayers入门之使用openlayers描述车辆运动轨迹
- sumo生成的车辆运动文件导入ns3的方法。
- 光流法用于车辆运动检测
- Android开发实现距离位置变化(类似滴滴打车附件的车辆)
- unity3d车辆按照自己设置的标记点运动
- 打车软件监管争论:谁大约握有车辆主导权?
- 百度地图车辆运动轨迹
- 百度地图车辆运动轨迹
- 运动车辆检测
- opencv学习 级联分类器检测运动车辆 demo
- JS高级运动实例分析
- 运动目标检测--基于直方图匹配的鬼影消除
- SwitchViewGroup:垂直运动的活动条
- unity3d 经像模糊特效 适用于高速运动物体的运动模糊
- 运动类计算公式----卡路里计算
- opencv之clahe限制对比对自适应均衡之后检测车辆
- 缓冲运动效果
- 车辆定位系统
- 小球沿不同轨迹运动时水平方向速度的比较
- JQueryUI-拖动(Draggable)-在DOM 元素中约束运动