百度地图绘制实时路线以及最短线路规划
如何使用百度地圖繪制實(shí)時(shí)路線以及最短線路規(guī)劃
最近在做百度地圖的實(shí)時(shí)路線繪制,發(fā)現(xiàn)一些問題,比如由于定位漂移帶來的路線繪制偏差,還有由于定位漂移,導(dǎo)致人未走動(dòng)時(shí),也會(huì)繪制路線等。百度鷹眼的線路糾偏個(gè)人感覺很一般啊。而且有限漂移了兩百米的點(diǎn)他也沒有糾正過來。所以最后還是決定自己寫一個(gè)糾偏吧。而且百度地圖官方的dome和示例代碼真的很示例啊。然人摸不著頭腦。ok進(jìn)入正題,思路是這樣的,因?yàn)閷?shí)時(shí)繪制線路都是在室外,所以只采用gps定位,不采用無線網(wǎng)絡(luò)定位。這樣漂移一兩百米的點(diǎn)基本不會(huì)出現(xiàn)。第二當(dāng)人在等紅綠燈時(shí),人是靜止的,但是定位有可能會(huì)漂移,所以這部分我們采用手機(jī)感應(yīng)器進(jìn)行判斷是否移動(dòng)。ok大體方向確定了,接下來就是進(jìn)行功能劃分然后開發(fā)了。功能模塊主要涉及以下幾點(diǎn)
需要項(xiàng)目源碼的請(qǐng)移步到此下載
 http://download.csdn.net/detail/zero172/9588471
- 地圖定位
- 繪制當(dāng)前位置
- 獲取位置進(jìn)行糾偏
- 判斷是否移動(dòng)
- 繪制線路
- 線路規(guī)劃
程序流程圖凸顯
Created with Rapha?l 2.2.0開始獲取gps位置不是第一個(gè)?不是前10個(gè)?手機(jī)是否處于運(yùn)動(dòng)?兩點(diǎn)間距離是否大于1米?兩點(diǎn)間距離是否小于90米?保存位置繪制線路拋棄位置保存位置yesnoyesnoyesnoyesnoyesno下面是完整代碼
這里貼出的代碼是基于各位亦有一定百度地圖開發(fā)基礎(chǔ)為參照,如果看不懂可留下郵箱我每晚發(fā)送源代碼給各位,我是用jar包是3.7.3版的,各位如果使用其他版本的包,可能會(huì)出現(xiàn)百度地圖初始化失敗的現(xiàn)象。對(duì)我被坑過。
package com.example.baidutext;import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List;import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.graphics.Color; import android.hardware.Sensor; import android.hardware.SensorManager; import android.os.Bundle; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast;import com.baidu.location.BDLocation; import com.baidu.location.BDLocationListener; import com.baidu.location.LocationClient; import com.baidu.location.LocationClientOption; import com.baidu.mapapi.SDKInitializer; import com.baidu.mapapi.map.BaiduMap; import com.baidu.mapapi.map.BaiduMap.OnMapLongClickListener; 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.MarkerOptions; import com.baidu.mapapi.map.OverlayOptions; import com.baidu.mapapi.map.PolylineOptions; import com.baidu.mapapi.model.LatLng; import com.baidu.mapapi.search.route.BikingRouteResult; import com.baidu.mapapi.search.route.DrivingRouteResult; 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.WalkingRoutePlanOption; import com.baidu.mapapi.search.route.WalkingRouteResult; import com.baidu.mapapi.utils.DistanceUtil;public class MainActivity extends Activity {/*** 百度地圖視圖*/private MapView map_v=null;/*** 百度地圖管理器*/private BaiduMap BaiDuMap;// /**// * 位置管理器// */// private LocationManager locationManager;/*** 位置客戶端*/private LocationClient locationClient = null;/*** 獲取位置時(shí)間間隔單位(秒)*/private final int time= 1000*9;// /**// * 定位數(shù)據(jù) // */// private MyLocationData locData;/*** 構(gòu)建Marker圖標(biāo) */private BitmapDescriptor bitmap,StartBitmap,EndBitmap; /***判斷是否第一次定位*/private boolean isFirstLoc=true;/*** 是否處于路線規(guī)劃*/private boolean isGetRoute=false;/*** 是否獲取新路線*/private boolean isGetNewRoute=true;/*** 定位位置數(shù)據(jù)* 多線程在修改本數(shù)據(jù),需要增加一個(gè)鎖;*/private List<LatLng> pointList = new ArrayList<LatLng>();/** // * 判斷是否處于暫停 // */// private boolean isPause=false;/*** 描述地圖將要發(fā)生的變化*/protected MapStatusUpdate msUpdate = null;/*** 覆蓋物*/protected OverlayOptions overlay,StartOverlay,EndOverlay;/*** 路線覆蓋物*/private PolylineOptions polyline = null;/*** 手機(jī)加速度感應(yīng)器服務(wù)注冊(cè)*/private SensorManager sm = null;private Acc acc=new Acc();/*** 最大距離單位(米)*/private final Double MaxDistance=90.00;/*** 最小距離單位(米)*/private final Double MinDistance=2.0;/*** 電源鎖*/public static WakeLock wakeLock=null;private PowerReceiver powerReceiver = new PowerReceiver();/***最近位置信息*/private LatLng latLng;/*** 因距離太大丟失的點(diǎn)數(shù)*/private int LostLoc=0;/*** 第一次定位丟失的點(diǎn)數(shù)*/private int FLostLoc=0;/*** 程序名稱*/private final String APP_FOLDER_NAME = "LocationDemo";/*** 路線規(guī)劃監(jiān)聽*/private RoutePlanSearch mSearch;/*** 當(dāng)前位置,終點(diǎn)位置*/private LatLng ll,EndLL;/*** 路線規(guī)劃等待進(jìn)度框*/private ProgressDialog progressDialog;/*** 獲取位置距離常量*/private int constant=0;/* (non-Javadoc)* @see android.app.Activity#onCreate(android.os.Bundle)*/@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);sm = (SensorManager) getSystemService(SENSOR_SERVICE);SDKInitializer.initialize(getApplicationContext());// activityList.add(this);setContentView(R.layout.activity_main);init();//設(shè)置定位監(jiān)聽locationClient.registerLocationListener(new BDLocationListener(){@Overridepublic void onReceiveLocation(BDLocation location) {// TODO Auto-generated method stub// locData = new MyLocationData.Builder() // .accuracy(0) // // 此處設(shè)置開發(fā)者獲取到的方向信息,順時(shí)針0-360 // .direction(0).latitude(location.getLatitude()) // .longitude(location.getLongitude()).build(); // // 設(shè)置定位數(shù)據(jù) // BaiDuMap.setMyLocationData(locData); ll = new LatLng(location.getLatitude(),location.getLongitude());progressDialog.dismiss();if(isFirstLoc||isGetRoute){if(!isGetRoute){MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll);BaiDuMap.animateMapStatus(u);}// MyLocationConfiguration config = new MyLocationConfiguration(LocationMode.NORMAL, true, bitmap);//普通(LocationMode.NORMAL)、跟隨(LocationMode.FOLLOWING)、羅盤(LocationMode.COMPASS)// BaiDuMap.setMyLocationConfigeration(config);isFirstLoc=false;if(constant<pointList.size()){if(DistanceUtil.getDistance(pointList.get(constant),ll)>DistanceUtil.getDistance(pointList.get(constant+1),ll)){save("距離: "+DistanceUtil.getDistance(pointList.get(constant+1),ll)+" 時(shí)間: "+getStringDate()+" 點(diǎn)數(shù): "+constant);if(DistanceUtil.getDistance(pointList.get(constant+1),ll)>100&&isGetNewRoute){IsGetNewRoute();}constant++;}else{save("距離: "+DistanceUtil.getDistance(pointList.get(constant),ll)+" 時(shí)間: "+getStringDate()+" 點(diǎn)數(shù): "+constant);if(DistanceUtil.getDistance(pointList.get(constant),ll)>100&&isGetNewRoute){IsGetNewRoute();}}}drawRealtimePoint(ll);}else{showRealtimeTrack(location);}}});locationClient.start();//路線規(guī)劃回調(diào)OnGetRoutePlanResultListener listener = new OnGetRoutePlanResultListener(){@Overridepublic void onGetBikingRouteResult(BikingRouteResult arg0) {// TODO Auto-generated method stub}@Overridepublic void onGetDrivingRouteResult(DrivingRouteResult arg0) {// TODO Auto-generated method stub}@Overridepublic void onGetTransitRouteResult(TransitRouteResult arg0) {// TODO Auto-generated method stub}@Overridepublic void onGetWalkingRouteResult(WalkingRouteResult WalkingRoute) {// TODO Auto-generated method stubif(WalkingRoute.getRouteLines()!=null){constant =0;isGetNewRoute=true;for(int i=0;i<WalkingRoute.getRouteLines().get(0).getAllStep().size();i++){pointList.addAll(WalkingRoute.getRouteLines().get(0).getAllStep().get(i).getWayPoints());}save("時(shí)間: "+getStringDate()+" 總點(diǎn)數(shù): "+pointList.size());}else // Toast.makeText(MainActivity.this, "獲取線路失敗", 3000).show();System.out.println("ccccccccccccccccccc");}};mSearch.setOnGetRoutePlanResultListener(listener);//長按地圖監(jiān)聽BaiDuMap.setOnMapLongClickListener(new OnMapLongClickListener() {@Overridepublic void onMapLongClick(LatLng arg0) {// TODO Auto-generated method stubEndLL=arg0;StartRoutePlan();}}); // mSearch.destroy();Toast.makeText(this, "正在定位....", 3000).show();}/*** 初始化資源*/protected void init(){map_v=(MapView)findViewById(R.id.bmapView);bitmap = BitmapDescriptorFactory.fromResource(R.drawable.map_d);StartBitmap= BitmapDescriptorFactory.fromResource(R.drawable.start_bitmap);EndBitmap= BitmapDescriptorFactory.fromResource(R.drawable.end_bitmap);// locationManager = (LocationManager) getSystemService(this.LOCATION_SERVICE);BaiDuMap=map_v.getMap();locationClient = new LocationClient(this);LocationClientOption option = new LocationClientOption();option.setOpenGps(true); //是否打開GPSoption.setCoorType("bd09ll"); //設(shè)置返回值的坐標(biāo)類型。bd09ll百度加密經(jīng)緯度坐標(biāo),bd09百度加密墨卡托坐標(biāo),gcj02國測局加密經(jīng)緯度坐標(biāo)option.setPriority(LocationClientOption.GpsOnly); //設(shè)置定位優(yōu)先級(jí),只取gps定位;option.setProdName(APP_FOLDER_NAME); //設(shè)置產(chǎn)品線名稱。option.setScanSpan(time); //設(shè)置定時(shí)定位的時(shí)間間隔。單位毫秒locationClient.setLocOption(option);BaiDuMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);//普通地圖模式 ;MAP_TYPE_SATELLITE為衛(wèi)星地圖;MAP_TYPE_NONE空白地圖;BaiDuMap.setTrafficEnabled(false);//不開啟交通視圖;map_v.showZoomControls(false);//不開啟底部放大縮小 圖標(biāo);BaiDuMap.animateMapStatus(MapStatusUpdateFactory.zoomTo(18));//設(shè)置地圖縮放BaiDuMap.setMyLocationEnabled(true);//開啟定位圖層BaiDuMap.setMaxAndMinZoomLevel(18.0f,1.0f);mSearch = RoutePlanSearch.newInstance();progressDialog=new ProgressDialog(this);}@Overrideprotected void onStart() {// TODO Auto-generated method stubsuper.onStart();}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();map_v.onDestroy();BaiDuMap.setMyLocationEnabled(false);locationClient.stop();map_v = null;releaseWakeLock();sm.unregisterListener(acc);mSearch.destroy();saveArray();}@Overrideprotected void onPause() {// TODO Auto-generated method stubsuper.onPause();map_v.onPause();}@Overridepublic boolean onMenuItemSelected(int featureId, MenuItem item) {// TODO Auto-generated method stubif(item.getItemId()==R.id.action_settings){progressDialog.setTitle("路線規(guī)劃");progressDialog.setMessage("正在清除路線請(qǐng)稍后。。");progressDialog.show();isGetRoute=false;if(pointList!=null||pointList.size()>0)pointList.clear();if(StartOverlay!=null)StartOverlay=null;if(EndOverlay!=null)EndOverlay=null;}return super.onMenuItemSelected(featureId, item);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// TODO Auto-generated method stubreturn super.onCreateOptionsMenu(menu);}/** 將數(shù)據(jù)臨時(shí)保存到xml文件*/private boolean saveArray() { deleteXML();SharedPreferences sp= getSharedPreferences("lat", Context.MODE_APPEND); Editor mEdit1= sp.edit(); mEdit1.remove("Status_size");mEdit1.putInt("Status_size",pointList.size());for(int i=0;i<pointList.size();i++) { mEdit1.remove("lat_" + i); mEdit1.putString("lat_" + i,pointList.get(i).latitude+"");mEdit1.remove("lon_" + i); mEdit1.putString("lon_" + i,pointList.get(i).longitude+"");} return mEdit1.commit(); }@Overrideprotected void onResume() {// TODO Auto-generated method stubsuper.onResume();map_v.onResume();sm.registerListener(acc, Sensor.TYPE_ACCELEROMETER ,SensorManager.SENSOR_DELAY_NORMAL);acquireWakeLock();// if(latLng!=null)// drawRealtimePoint(latLng);}// /*// * 讀取xml文件存儲(chǔ)數(shù)據(jù);// * @param mContext// */// protected void loadArray(Context mContext) { // SharedPreferences mSharedPreference1=getSharedPreferences("lat", Context.MODE_PRIVATE); // // pointList.clear(); // int size = mSharedPreference1.getInt("Status_size", 0); //// for(int i=0;i<size;i++) {// Double lat1=Double.valueOf(mSharedPreference1.getString("lat_"+i, null));// Double lon1=Double.valueOf(mSharedPreference1.getString("lat_"+i, null));// pointList.add(new LatLng(lat1, lon1)); // }// }/** 刪除xml文件*/private void deleteXML() {File file = new File("/data/data/" + getPackageName().toString() + "/shared_prefs", "lat.xml"); if (file.exists()) { file.delete(); }}/** 顯示實(shí)時(shí)軌跡* * @param realtimeTrack*/protected void showRealtimeTrack(BDLocation location) {double latitude = location.getLatitude();double longitude = location.getLongitude();if (Math.abs(latitude - 0.0) < 0.000001 && Math.abs(longitude - 0.0) < 0.000001) {Toast.makeText(this, "當(dāng)前無軌跡點(diǎn)", 3000).show();} else {latLng = new LatLng(latitude, longitude);if (IsMove(latLng,location)) {// 繪制實(shí)時(shí)點(diǎn)drawRealtimePoint(latLng);}}}/** 繪制實(shí)時(shí)點(diǎn)* * @param points*/private void drawRealtimePoint(LatLng point) {BaiDuMap.clear();polyline=null;MapStatus mMapStatus = new MapStatus.Builder().target(point).build();msUpdate = MapStatusUpdateFactory.newMapStatus(mMapStatus);overlay = new MarkerOptions().position(point).icon(bitmap).zIndex(9).draggable(true);if (pointList.size() >=2 && pointList.size() <= 100000) {// 添加路線(軌跡)polyline = new PolylineOptions().width(10).color(Color.RED).points(pointList);}addMarker();}/** 添加地圖覆蓋物*/protected void addMarker() {if (null != msUpdate) {BaiDuMap.setMapStatus(msUpdate);}// 路線覆蓋物if (null != polyline) {BaiDuMap.addOverlay(polyline);}// 實(shí)時(shí)點(diǎn)覆蓋物if (null != overlay) {BaiDuMap.addOverlay(overlay);}//起點(diǎn)覆蓋物if (null != StartOverlay) {BaiDuMap.addOverlay(StartOverlay);}// 終點(diǎn)覆蓋物if (null != EndOverlay) {BaiDuMap.addOverlay(EndOverlay);}}/**@author chenzheng_Java *保存用戶輸入的內(nèi)容到文件 */ private void save(String content) { try { /* 根據(jù)用戶提供的文件名,以及文件的應(yīng)用模式,打開一個(gè)輸出流.文件不存系統(tǒng)會(huì)為你創(chuàng)建一個(gè)的, * 至于為什么這個(gè)地方還有FileNotFoundException拋出,我也比較納悶。在Context中是這樣定義的 * public abstract FileOutputStream openFileOutput(String name, int mode) * throws FileNotFoundException; * openFileOutput(String name, int mode); * 第一個(gè)參數(shù),代表文件名稱,注意這里的文件名稱不能包括任何的/或者/這種分隔符,只能是文件名 * 該文件會(huì)被保存在/data/data/應(yīng)用名稱/files/chenzheng_java.txt * 第二個(gè)參數(shù),代表文件的操作模式 * MODE_PRIVATE 私有(只能創(chuàng)建它的應(yīng)用訪問) 重復(fù)寫入時(shí)會(huì)文件覆蓋 * MODE_APPEND 私有 重復(fù)寫入時(shí)會(huì)在文件的末尾進(jìn)行追加,而不是覆蓋掉原來的文件 * MODE_WORLD_READABLE 公用 可讀 * MODE_WORLD_WRITEABLE 公用 可讀寫 * */ content=content+"\n";FileOutputStream outputStream = openFileOutput("Log.log",Activity.MODE_APPEND); outputStream.write(content.getBytes()); outputStream.flush(); outputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** 獲取系統(tǒng)時(shí)間*/private String getStringDate() {Date currentTime = new Date();SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String dateString = formatter.format(currentTime);return dateString;}/** 判斷手機(jī)是否在運(yùn)動(dòng)*/private boolean IsMove(LatLng latLng,BDLocation location){if(pointList.size()>=1){Double dis=DistanceUtil.getDistance(pointList.get(pointList.size()-1),latLng);//判斷手機(jī)是否靜止,如果靜止,判定采集點(diǎn)無效,直接拋棄if(!acc.is_Acc&&acc.IsRun){acc.IsRun=false;return false;}//判斷是否是第一次定位置,如果是第一次定位并且因?yàn)榈谝淮螔仐壍奈恢脭?shù)量小于10個(gè)則判斷兩點(diǎn)間距離大小if(FLostLoc<10){FLostLoc=FLostLoc+1;if(dis>10&&FLostLoc<6){//距離大于十米,而且被拋棄數(shù)量少于5個(gè)則說明有可能是獲取位置失敗pointList.clear();pointList.add(latLng);//更新位置return false;}if(dis>0&&dis<10&&FLostLoc>=6)//如果距離在10米內(nèi),則表示客戶正在運(yùn)動(dòng),直接跳出FLostLoc=11;}//根據(jù)兩點(diǎn)間距離判斷是否發(fā)生定位漂移,如果漂移距離小于MinDistance則拋棄,如果漂移距離大于MaxDistance則取兩點(diǎn)的中間點(diǎn).if(dis<=MinDistance){if((dis<=MinDistance||dis>=MaxDistance)){return false;}if(LostLoc>=4){Double newlatitude=(latLng.latitude+pointList.get(pointList.size()-1).latitude)/2;Double newlongitude=(latLng.longitude+pointList.get(pointList.size()-1).longitude)/2;latLng = new LatLng(newlatitude, newlongitude);}else{LostLoc=LostLoc+1;return false;}}LostLoc=0;//重置丟失點(diǎn)的個(gè)數(shù)// pointList.add(latLng);acc.is_Acc=false;}pointList.add(latLng);return true;}/** 開始規(guī)劃線路*/private void StartRoutePlan() {// TODO Auto-generated method stubprogressDialog.setTitle("路線規(guī)劃");progressDialog.setMessage("正在規(guī)劃路線請(qǐng)稍后。。");progressDialog.show();if(pointList!=null||pointList.size()>0)pointList.clear();PlanNode stNode = PlanNode.withLocation(ll); StartOverlay=new MarkerOptions().position(ll).icon(StartBitmap).zIndex(9);PlanNode enNode = PlanNode.withLocation(EndLL);EndOverlay=new MarkerOptions().position(EndLL).icon(EndBitmap).zIndex(9);mSearch.walkingSearch((new WalkingRoutePlanOption()) .from(stNode) .to(enNode));isGetRoute=true;}/** 獲取新路線*/private void IsGetNewRoute() {// TODO Auto-generated method stubAlertDialog.Builder builder = new Builder(this);builder.setMessage("您已偏移路線,是否重新規(guī)劃路線?");builder.setTitle("路線偏移");builder.setPositiveButton("重新規(guī)劃", new OnClickListener() { @Overridepublic void onClick(DialogInterface dialog, int which) {StartRoutePlan();dialog.dismiss();}}); builder.setNegativeButton("按原規(guī)劃", new OnClickListener() { @Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();}});builder.create().show();isGetNewRoute=false;}/** 申請(qǐng)電源鎖 */private void acquireWakeLock() {if (null == wakeLock) {PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE,getClass().getName());}IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_SCREEN_ON);filter.addAction(Intent.ACTION_SCREEN_OFF);registerReceiver(powerReceiver, filter);}/** 釋放電源鎖*/private void releaseWakeLock() {unregisterReceiver(powerReceiver);} }##下面PowerReceiver文件的內(nèi)容
這里貼出的代碼主要是完成電源鎖的開啟和撤銷
package com.example.baidutext;import android.annotation.SuppressLint; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent;public class PowerReceiver extends BroadcastReceiver {@SuppressLint("Wakelock")@Overridepublic void onReceive(final Context context, final Intent intent) {final String action = intent.getAction();//按下電源鍵,關(guān)閉屏幕if (Intent.ACTION_SCREEN_OFF.equals(action)) {System.out.println("screen off,acquire wake lock!");if (null != MainActivity.wakeLock && !(MainActivity.wakeLock.isHeld())) {MainActivity.wakeLock.acquire();}//按下電源鍵,打開屏幕 } else if (Intent.ACTION_SCREEN_ON.equals(action)) {System.out.println("screen on,release wake lock!");if (null != MainActivity.wakeLock && MainActivity.wakeLock.isHeld()) {MainActivity.wakeLock.release();}}}}##下面Acc文件的內(nèi)容
這個(gè)文件主要是獲取加速感應(yīng)器的值,然后通過波峰和波谷的插值,以及兩個(gè)波峰之間的時(shí)間差來判斷手機(jī)是否處于移動(dòng)。關(guān)于詳細(xì)的大家可查找計(jì)步器原理。一下算法非本人原創(chuàng),但是一直找不到原創(chuàng)作者,如作者本人看到,可與我聯(lián)系
package com.example.baidutext;import android.hardware.Sensor; import android.hardware.SensorListener; /***根據(jù)加速度判斷手機(jī)是否處于靜止* @author Administrator**/ public class Acc implements SensorListener {// /**// * 手機(jī)加速度各方向狀態(tài)// */// private float F_Acc_x,F_Acc_y,F_Acc_z;// /**// * 上次獲取狀態(tài)時(shí)間// */// private long LastUpdateTime; // /**// * 兩次獲取狀態(tài)時(shí)間間隔單位(秒)// */// private final int UPTATE_INTERVAL_TIME = 1000*10; // /*** 當(dāng)前傳感器的值*/private float gravityNew = 0;/*** 上次傳感器的值*/private float gravityOld = 0;/*** 此次波峰的時(shí)間*/private long timeOfThisPeak = 0;/*** 上次波峰的時(shí)間*/private long timeOfLastPeak = 0;/*** 當(dāng)前的時(shí)間*/private long timeOfNow = 0;;/*** 波峰值*/private float peakOfWave = 0;/*** 波谷值*/private float valleyOfWave = 0;/*** 初始閾值*/private float ThreadValue = (float) 2.0;/*** 動(dòng)態(tài)閾值需要?jiǎng)討B(tài)的數(shù)據(jù),這個(gè)值用于這些動(dòng)態(tài)數(shù)據(jù)的閾值*/private final float initialValue = (float) 1.3;/*** 上一點(diǎn)的狀態(tài),上升還是下降*/private boolean lastStatus = false;/*** 是否上升的標(biāo)志位*/private boolean isDirectionUp = false;/*** 持續(xù)上升次數(shù)*/private int continueUpCount = 0;/*** 上一點(diǎn)的持續(xù)上升的次數(shù),為了記錄波峰的上升次數(shù)*/private int continueUpFormerCount = 0;public boolean is_Acc=false;// private int ACC=30;//手機(jī)感應(yīng)器波動(dòng)范圍,30以內(nèi)判定手機(jī)處于靜止private int tempCount = 0;private final int valueNum = 4;/*** 用于存放計(jì)算閾值的波峰波谷差值*/private float[] tempValue = new float[valueNum];/*** 記錄波峰數(shù)量*/private int CountValue = 0;/*** 判斷傳感器是否在運(yùn)行*/public boolean IsRun=false; public Acc(){// LastUpdateTime=System.currentTimeMillis();}@Overridepublic void onAccuracyChanged(int arg0, int arg1) {// TODO Auto-generated method stub}/*** 感應(yīng)器狀態(tài)改變時(shí)自動(dòng)調(diào)用此方法*/@Overridepublic void onSensorChanged(int arg0, float[] arg1) {// TODO Auto-generated method stubIsRun=true;if(arg0==Sensor.TYPE_ACCELEROMETER){// JIUjia(arg1);gravityNew = (float) Math.sqrt(arg1[0] * arg1[0]+ arg1[1] * arg1[1] + arg1[2] * arg1[2]);DetectorNewStep(gravityNew);}}// protected boolean JIUjia(float[] values) {// if(F_Acc_x!=0){// long currentUpdateTime = System.currentTimeMillis(); // long timeInterval = currentUpdateTime - LastUpdateTime; // if(timeInterval < UPTATE_INTERVAL_TIME)// return false;// LastUpdateTime=currentUpdateTime;// float tem0=values[0]-F_Acc_x;// float tem1=values[1]-F_Acc_y;// float tem2=values[2]-F_Acc_z;// System.out.println(Math.abs(tem0)+","+Math.abs(tem1)+","+Math.abs(tem2));// if(Math.abs(tem0)>ACC||Math.abs(tem1)>ACC||Math.abs(tem2)>ACC)// is_Acc=true;// // }// F_Acc_x=values[0];// F_Acc_y=values[1];// F_Acc_z=values[2];// return is_Acc;//// }/** 檢測步子* 1.傳入sersor中的數(shù)據(jù)* 2.如果檢測到了波峰,并且符合時(shí)間差以及閾值的條件,則判定為1步* 3.符合時(shí)間差條件,波峰波谷差值大于initialValue,則將該差值納入閾值的計(jì)算中* */public void DetectorNewStep(float values) {if (gravityOld == 0) {gravityOld = values;} else {if (DetectorPeak(values, gravityOld)) {timeOfLastPeak = timeOfThisPeak;timeOfNow = System.currentTimeMillis();if ((timeOfNow - timeOfLastPeak) >= 250&& (peakOfWave - valleyOfWave >= ThreadValue)) {timeOfThisPeak = timeOfNow;//兩步之間間隔大于4秒則不算if((timeOfNow-timeOfLastPeak)>40000)CountValue=0;elseCountValue++;//只有手機(jī)連續(xù)搖晃4下或者以上才判定為走路if(CountValue>=4)is_Acc=true;// mStepListeners.onStep();}if (timeOfNow - timeOfLastPeak >= 250&& (peakOfWave - valleyOfWave >= initialValue)) {timeOfThisPeak = timeOfNow;ThreadValue = Peak_Valley_Thread(peakOfWave - valleyOfWave);}}}gravityOld = values;}/** 檢測波峰* 以下四個(gè)條件判斷為波峰:* 1.目前點(diǎn)為下降的趨勢(shì):isDirectionUp為false* 2.之前的點(diǎn)為上升的趨勢(shì):lastStatus為true* 3.到波峰為止,持續(xù)上升大于等于4次* 4.波峰值大于20* 記錄波谷值* 1.觀察波形圖,可以發(fā)現(xiàn)在出現(xiàn)步子的地方,波谷的下一個(gè)就是波峰,有比較明顯的特征以及差值* 2.所以要記錄每次的波谷值,為了和下次的波峰做對(duì)比* */public boolean DetectorPeak(float newValue, float oldValue) {lastStatus = isDirectionUp;if (newValue >= oldValue) {isDirectionUp = true;continueUpCount++;} else {continueUpFormerCount = continueUpCount;continueUpCount = 0;isDirectionUp = false;}if (!isDirectionUp && lastStatus&& (continueUpFormerCount >= 4 || oldValue >= 20&&oldValue<=40)) {peakOfWave = oldValue;return true;} else if (!lastStatus && isDirectionUp) {valleyOfWave = oldValue;return false;} else {return false;}}/** 閾值的計(jì)算* 1.通過波峰波谷的差值計(jì)算閾值* 2.記錄4個(gè)值,存入tempValue[]數(shù)組中* 3.在將數(shù)組傳入函數(shù)averageValue中計(jì)算閾值* */public float Peak_Valley_Thread(float value) {float tempThread = ThreadValue;if (tempCount < valueNum) {tempValue[tempCount] = value;tempCount++;} else {tempThread = averageValue(tempValue, valueNum);for (int i = 1; i < valueNum; i++) {tempValue[i - 1] = tempValue[i];}tempValue[valueNum - 1] = value;}return tempThread;}/** 梯度化閾值* 1.計(jì)算數(shù)組的均值* 2.通過均值將閾值梯度化在一個(gè)范圍里* */public float averageValue(float value[], int n) {float ave = 0;for (int i = 0; i < n; i++) {ave += value[i];}ave = ave / valueNum;if (ave >= 8)ave = (float) 4.3;else if (ave >= 7 && ave < 8)ave = (float) 3.3;else if (ave >= 4 && ave < 7)ave = (float) 2.3;else if (ave >= 3 && ave < 4)ave = (float) 2.0;else {ave = (float) 1.3;}return ave;} }至此就全部結(jié)束了,各位如有其他問題可直接留言給我。
總結(jié)
以上是生活随笔為你收集整理的百度地图绘制实时路线以及最短线路规划的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Lua 闭包实现pairs和ipairs
- 下一篇: oracle数据库block、tigge
