您的位置:首页 > 其它

仿滴滴打车 车辆运动

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;

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


}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息