转自:http://blog.youkuaiyun.com/f_season/article/details/9171523
如何在Android显示小车的行进路线并且当遇到重要事物时在地图上标记?前面一篇文章已经讲了两台手机的socket双向通信,这里就以此进行数据信息的传输。
我以小车上的手机作为server,以手上的手机作为client,server用于陀螺仪和磁力计信息和图像信息(摄像头获取QR码和是否找到小球的信息)发送给client,client根据获得的信息绘制出小车的行进路线图和标记图标。
首先说说server发给client的数据格式,是四位数组 String[] a ={"S","0","0","0"},至于如何发送请看上一篇,我就不累犊了……
a[0]中S表示停止,F表示前进,B表示后退
a[1]存的是陀螺仪角度,和小车初始方向角处理得到当前小车朝向
a[2]存的是磁力角角度,确定小车初始方向角
a[3]记录发现的物体,比如 "ball" 和QR码
client部分绘制路线图,具体思路是:借用google map为小车路线图,server获得磁力计的角度,确定小车初始位置。然后根据陀螺仪角度实时获得小车方位,从而在地图上画出具有方向性的路线图。当小车获取QR码并发送给client,地图上将标记出QR码,点击就可以获取QR信息。同理,当找到小球时,地图上也会出现图标告诉你小车是在哪找到小球的。下面是client的绘图部分:
- appState = ((RosminState)getApplicationContext());
- mapView =(MapView)findViewById(R.id.map);
- mapcontroller = mapView.getController();
- originMaker = getResources().getDrawable(R.drawable.origin);//起点图标
- currMaker = getResources().getDrawable(R.drawable.sign); //当前位置图标
- ballMaker = getResources().getDrawable(R.drawable.goal); //发现小球图标
- lat1 = 0;
- lng1 = 0;
- //画出起点,小车路线原理就是画出两点并连线,周而复始
- points.add(new GeoPoint((int) (lat1 * 1000000),(int) (lng1 * 1000000)));
- //添加自定义的图层
- PathOverLay polyline = new PathOverLay(points); //添加polyline图层,负责画出路线
- mapView.getOverlays().add(polyline);
- mapView.invalidate();
- mapView.setBuiltInZoomControls(true);
- //设置中心和放大倍数
- GeoPoint point=new GeoPoint((int) (lat1 * 1000000),(int) (lng1 * 1000000));
- mapcontroller.setCenter(point);
- mapcontroller.setZoom(15);
- //这个图层负责添加图标,这里添加“起点”图标
- myOverlay = new MapOverlay(originMaker);
- myOverlay.setItem(point);
- myOverlay.setQR("起点");
- mapView.getOverlays().add(myOverlay);
- mapcontroller.animateTo(point);
下面具体方法,放入thread实时进行:
- //在地图上画出路线以及做出标记
- Thread time = new Thread(new Runnable()
- {
- public void run() {
- long t1 = 0,t2 = 0 ;
- while(true){
- while(!Control.a[0].equals("F") && !Control.a[0].equals("B"))//未获得行动命令就等待
- {
- if(!Control.a[3].equals("0") && !Control.a[3].equals("ball"))
- {
- break;
- }
- if(Control.a[3].equals("ball"))
- {
- break;
- }
- }
- t1 = System.currentTimeMillis();
- if(!Control.a[3].equals("0") && !Control.a[3].equals("ball"))
- //发现QR码并保存,在地图上标记
- {
- QRmsg = Control.a[3];
- getQR =true;
- addMarker();
- }
- if(Control.a[3].equals("ball"))
- //发现小球,在地图上标记
- {
- findBALL=true;
- addMarker();
- }
- try
- {
- Thread.sleep(50);
- }
- catch (InterruptedException e)
- {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- t2 = System.currentTimeMillis();
- moveTimeGap = t2 -t1 ;
- Handler01.post(rDraw);
- }
- }//run
- });
- time.start();
- /**画图部分,这里使用经纬度来表示小车朝向与行进路线
- * 最初用磁力计得到方向角,然后与陀螺仪得到的角度进行处理得到当前小车朝向
- * */
- private Runnable rDraw = new Runnable()
- {
- public void run()
- {
- if(ori)
- {
- oriAngle = Integer.parseInt(Control.a[2]);
- ori = false;
- }
- gyroAngle = Integer.parseInt( Control.a[1] );
- if(Control.a[0].equals("F"))
- {
- lat1 += (moveTimeGap*0.000001)*Math.cos((oriAngle-gyroAngle)*0.017452);
- lng1 += (moveTimeGap*0.000001)*Math.sin((oriAngle-gyroAngle)*0.017452);
- points.add(new GeoPoint((int) (lat1 * 1000000),(int) (lng1 * 1000000)));
- }
- if(Control.a[0].equals("B"))
- {
- lat1 -= (moveTimeGap*0.000001)*Math.cos((oriAngle-gyroAngle)*0.017452);
- lng1 -= (moveTimeGap*0.000001)*Math.sin((oriAngle-gyroAngle)*0.017452);
- points.add(new GeoPoint((int) (lat1 * 1000000),(int) (lng1 * 1000000)));
- }
- }
- };
- private void addMarker() {
- if(getQR) //发现QR码后,存储坐标,显示图标,记录QR信息
- {
- GeoPoint myGeoPoint = new GeoPoint((int) (lat1 * 1000000),(int) (lng1 * 1000000));
- myOverlay = new MapOverlay(currMaker);
- myOverlay.setItem(myGeoPoint);
- myOverlay.setQR(QRmsg);
- mapView.getOverlays().add(myOverlay);
- getQR = false;
- }
- if(findBALL) //发现球后,存储坐标,显示图标,记录球信息
- {
- GeoPoint myGeoPoint = new GeoPoint((int) (lat1 * 1000000),(int) (lng1 * 1000000));
- myOverlay = new MapOverlay(ballMaker);
- myOverlay.setItem(myGeoPoint);
- myOverlay.setQR("发现小球");
- mapView.getOverlays().add(myOverlay);
- findBALL = false;
- }
- }
- public class MapOverlay extends ItemizedOverlay<OverlayItem> {
- private List<GeoPoint> mItems = new ArrayList<GeoPoint>();
- public List<String> QRmessage = new ArrayList<String>();
- public MapOverlay(Drawable marker) {
- super(boundCenterBottom(marker));
- }
- public void setItems(ArrayList<GeoPoint> items) {
- mItems = items;
- populate();
- }
- public void setItem(GeoPoint item) {
- mItems.add(item);
- populate();
- }
- public void setQR(String s) {
- QRmessage.add(s);
- populate();
- }
- @Override
- protected OverlayItem createItem(int i) {
- return new OverlayItem(mItems.get(i), null, null);
- }
- @Override
- public int size() {
- return mItems.size();
- }
- @Override
- protected boolean onTap(int i) {
- Toast.makeText(Map.this, "获得信息\n "+ QRmessage, Toast.LENGTH_SHORT).show();
- return true;
- }
- }
- public class PathOverLay extends Overlay {
- List<GeoPoint> points;
- Paint paint;
- /**
- * 构造函数,使用GeoPoint List构造Polyline
- *
- * @param points
- * GeoPoint点List
- */
- public PathOverLay(List<GeoPoint> points) {
- this.points = points;
- paint = new Paint();
- paint.setColor(Color.rgb(59,88,235));
- paint.setAlpha(150);
- paint.setAntiAlias(true);
- paint.setStyle(Paint.Style.FILL_AND_STROKE);
- paint.setStrokeWidth(4);
- }
- /**
- * 使用GeoPoint点List和Paint对象来构造Polyline
- *
- * @param points
- * GeoPoint点List,所有的拐点
- * @param paint
- * Paint对象,用来控制划线样式
- */
- public PathOverLay(List<GeoPoint> points, Paint paint) {
- this.points = points;
- this.paint = paint;
- }
- /**
- * 真正将线绘制出来 只需将线绘制到canvas上即可,主要是要转换经纬度到屏幕坐标
- */
- @Override
- public void draw(Canvas canvas, MapView mapView, boolean shadow) {
- int i;
- if (!shadow) {// 不是绘制shadow层
- Projection projection = mapView.getProjection();
- if (points != null) {
- if (points.size() >= 2) {
- Point start = projection.toPixels(points.get(0), null);// 需要转换坐标
- for ( i = 1; i < points.size(); i++) {
- Point end = projection.toPixels(points.get(i), null);
- canvas.drawLine(start.x, start.y, end.x, end.y, paint);// 绘制到canvas上即可
- start = end;
- if(i == points.size()-1)
- {
- paint.setColor(Color.rgb(250,20,85));
- end = projection.toPixels(points.get(i), null);
- canvas.drawCircle(end.x, end.y, 6, paint);
- paint.setColor(Color.rgb(59,88,235));
- }
- }
- }
- }
- }
- }
- }
PS:google map因为是google的核心技术,所以看源代码就别想了,接口的调用需要慢慢熟悉。原先google map有地图解析什么的,这是真实地图用的,我这里只是借用google map来绘制小车路线而已,所以只用了2个图层和点点连线的绘图方式,然后借用经度纬度反应出小车的具体方向。