【问题标题】:Handle click on route处理点击路线
【发布时间】:2012-03-09 18:00:33
【问题描述】:

我正在尝试使用 google map API 验证可点击的路线功能。

我使用地图 API 在两个坐标之间建立了路线显示。

为了实现这一点,我使用了以下教程http://csie-tw.blogspot.com/2009/06/android-driving-direction-route-path.html, 它基本上解析 KML 文件(谷歌地图方向请求的响应)并使用自定义地图叠加层来绘制路线。

自定义叠加层:

package com.test.route;

import android.graphics.Bitmap;
import android.graphics.Canvas; 
import android.graphics.Color;
import android.graphics.Paint; 
import android.graphics.Point; 
import android.graphics.RectF; 
import android.util.Log;
import android.view.MotionEvent;

import com.google.android.maps.GeoPoint; 
import com.google.android.maps.MapView; 
import com.google.android.maps.Overlay; 
import com.google.android.maps.Projection;

public class MyOverLay extends Overlay 
{ 
  private GeoPoint gp1;
  private GeoPoint gp2;
  private int mRadius=6;
  private int mode=0;
  private int defaultColor;
  private String text="";
  private Bitmap img = null;


  public MyOverLay(GeoPoint gp1,GeoPoint gp2,int mode) //  GeoPoint is a int. (6E)
  { 

    this.gp1 = gp1; 
    this.gp2 = gp2;
    this.mode = mode;
    defaultColor = 999; // no defaultColor

  } 


  public MyOverLay(GeoPoint gp1,GeoPoint gp2,int mode, int defaultColor) 
  { 
    this.gp1 = gp1; 
    this.gp2 = gp2;
    this.mode = mode;
    this.defaultColor = defaultColor;
  } 

  public void setText(String t)
  {
      this.text = t;
  }

  public void setBitmap(Bitmap bitmap)
  {
      this.img = bitmap;
  }

  public int getMode()
  {
      return mode;
  }

  @Override 
  public boolean draw 
  (Canvas canvas, MapView mapView, boolean shadow, long when) 
  { 

    Projection projection = mapView.getProjection(); 
    if (shadow == false) 
    {      

      Paint paint = new Paint(); 
      paint.setAntiAlias(true); 


      Point point = new Point(); 
      projection.toPixels(gp1, point);
      // mode=1¡Gstart 
      if(mode==1)
      {
        if(defaultColor==999)
            paint.setColor(Color.BLUE);   
        else
            paint.setColor(defaultColor);   


        RectF oval=new RectF(point.x - mRadius, point.y - mRadius,  
                             point.x + mRadius, point.y + mRadius); 
        // start point
        canvas.drawOval(oval, paint); 
      }
      // mode=2¡Gpath 
      else if(mode==2)
      {
        if(defaultColor==999)
            paint.setColor(Color.RED);   
        else
            paint.setColor(defaultColor);   

        Point point2 = new Point(); 
        projection.toPixels(gp2, point2);
        paint.setStrokeWidth(5);
        paint.setAlpha(120);       
        canvas.drawLine(point.x, point.y, point2.x,point2.y, paint);       
      }
      /* mode=3¡Gend */
      else if(mode==3)
      {
        /* the last path */

        if(defaultColor==999)
            paint.setColor(Color.GREEN);   
        else
            paint.setColor(defaultColor);   

        Point point2 = new Point(); 
        projection.toPixels(gp2, point2);
        paint.setStrokeWidth(5);
        paint.setAlpha(120);
        canvas.drawLine(point.x, point.y, point2.x,point2.y, paint);


        RectF oval=new RectF(point2.x - mRadius,point2.y - mRadius,  
                             point2.x + mRadius,point2.y + mRadius); 
        /* end point */
        paint.setAlpha(255);
        canvas.drawOval(oval, paint);
      }
      /* mode=4¡Gcar */
      else if(mode==4)
      {

        if(defaultColor==999)
            paint.setColor(Color.GREEN);   
        else
            paint.setColor(defaultColor);   

        Point point2 = new Point(); 
        projection.toPixels(gp2, point2); 
        paint.setTextSize(20);
        paint.setAntiAlias(true); 
        canvas.drawBitmap(img, point2.x, point2.y,paint);      
        canvas.drawText(this.text, point2.x, point2.y, paint);
      }

      else if(mode==5)
      {

        if(defaultColor==999)
            paint.setColor(Color.GREEN);   
        else
            paint.setColor(defaultColor);   

        Point point2 = new Point(); 
        projection.toPixels(gp2, point2); 
        paint.setTextSize(20);
        paint.setAntiAlias(true); 
        canvas.drawBitmap(img, point2.x, point2.y,paint);

      }



    } 
    return super.draw(canvas, mapView, shadow, when); 
  }

  @Override
  public boolean onTouchEvent(MotionEvent event, MapView mapView) 
  {   
      Log.i("Map", "Clicked");
      return false;
  }
}

测试地图活动:

package com.test.route;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;

import com.dailymates.carmate.utils.MyOverLay;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;

public class TestMap extends MapActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.map);
        MapView mapView = (MapView) findViewById(R.id.mapview);
        /* 
         * Defining the starting and end point of the route (latitude / longitude)
         * Oh Paris 
         * 
         */
        final double src_lat = 48.847378;
        final double src_long = 2.340417;
        final double dest_lat = 48.931466;
        final double dest_long = 2.504525;

        GeoPoint srcGeoPoint = new GeoPoint((int) (src_lat * 1E6),
                (int) (src_long * 1E6));
        GeoPoint destGeoPoint = new GeoPoint((int) (dest_lat * 1E6),
                (int) (dest_long * 1E6));

        DrawPath(srcGeoPoint, destGeoPoint, Color.GREEN, mapView);

        mapView.getController().animateTo(srcGeoPoint);
        mapView.getController().setZoom(12);

    }

    protected boolean isRouteDisplayed() {
        return false;
    }

    private void DrawPath(GeoPoint src, GeoPoint dest, int color, MapView mMapView01) {

        StringBuilder urlString = new StringBuilder();
        urlString.append("http://maps.google.com/maps?f=d&hl=en");
        urlString.append("&saddr=");
        urlString.append(Double.toString((double) src.getLatitudeE6() / 1.0E6));
        urlString.append(",");
        urlString.append(Double.toString((double) src.getLongitudeE6() / 1.0E6));
        urlString.append("&daddr=");// to
        urlString.append(Double.toString((double) dest.getLatitudeE6() / 1.0E6));
        urlString.append(",");
        urlString.append(Double.toString((double) dest.getLongitudeE6() / 1.0E6));
        urlString.append("&ie=UTF8&0&om=0&output=kml");

        Log.d("xxx", "URL=" + urlString.toString());

        Document doc = null;
        HttpURLConnection urlConnection = null;
        URL url = null;
        try {
            url = new URL(urlString.toString());
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.connect();

            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            doc = db.parse(urlConnection.getInputStream());

            if (doc.getElementsByTagName("GeometryCollection").getLength() > 0) {

                String path = doc.getElementsByTagName("GeometryCollection")
                        .item(0).getFirstChild().getFirstChild()
                        .getFirstChild().getNodeValue();

                Log.d("xxx", "path=" + path);

                String[] pairs = path.split(" ");
                String[] lngLat = pairs[0].split(","); 

                // lngLat[0]=longitude
                // lngLat[1]=latitude
                // lngLat[2]=height

                GeoPoint startGP = new GeoPoint((int) (Double.parseDouble(lngLat[1]) * 1E6),
                        (int) (Double.parseDouble(lngLat[0]) * 1E6));
                mMapView01.getOverlays().add(new MyOverLay(startGP, startGP, 1));

                GeoPoint gp1;
                GeoPoint gp2 = startGP;
                for (int i = 1; i < pairs.length; i++)
                {
                    lngLat = pairs[i].split(",");
                    gp1 = gp2;
                    gp2 = new GeoPoint(
                            (int) (Double.parseDouble(lngLat[1]) * 1E6),
                            (int) (Double.parseDouble(lngLat[0]) * 1E6));
                    mMapView01.getOverlays().add(
                            new MyOverLay(gp1, gp2, 2, color));

                    Log.d("xxx", "pair:" + pairs[i]);

                }
                mMapView01.getOverlays().add(new MyOverLay(dest, dest, 3));
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();

        } catch (SAXException e) {

            e.printStackTrace();
        }

    }
}

所以,正如我所说,我正确地得到了路线图。 但是我如何处理那些绘制路线上的点击事件呢?

关于信息,我正在考虑一些可能效率低下的事情,但我会告诉它,我们永远不知道 :)

由于路线建立基本上是两个地理点(段)之间的一系列绘图,我们可以预先处理路线点击:

  • 使用地图叠加层的onTouchEvent 方法,我们可以获得与点击关联的地理点。
  • 然后我们尝试确定单击的地理点是否是路段的一部分。

最后一条信息:地图上将同时绘制多条路线,因此点击必须与唯一的路线相关联,而不是全部。

谢谢。

【问题讨论】:

    标签: android map routes click overlay


    【解决方案1】:

    10 个月后,我正在提供我使用的工作(10 个月前),谁知道呢,也许它会对某人有所帮助:)。

    为了处理地图路线上的点击/触摸,一种方法可以是估计点击的点是否位于显示的路线附近。

    使用 OnTouchEvent 方法,您应该计算点击的点是否靠近路段(路线部分)。

    路线可以表示为段列表。

    下面的方法让你计算点和线段之间的距离(来自Java java.awt.geom.Line2D):

    /**
     * Get the closest distance between a point and a segment
     * 
     * @param x1 , x coordinate of the 1st segment point
     * @param y1 , y coordinate of the 1st segment point
     * @param x2 , x coordinate of the 2st segment point
     * @param y2 , y coordinate of the 2st segment point
     * @param x , x coordinate of the point from which distance will be calculated
     * @param y , y coordinate of the point from which distance will be calculated
     * 
     * @return the distance
     * 
     */
    public static float ptSegDistSq(float x1, float y1, float x2, float y2, float px, float py){
        // Adjust vectors relative to x1,y1
        // x2,y2 becomes relative vector from x1,y1 to end of segment
        x2 -= x1;
        y2 -= y1;
        // px,py becomes relative vector from x1,y1 to test point
        px -= x1;
        py -= y1;
        float dotprod = px * x2 + py * y2;
        float projlenSq;
        if (dotprod <= 0.0) {
            // px,py is on the side of x1,y1 away from x2,y2
            // distance to segment is length of px,py vector
            // "length of its (clipped) projection" is now 0.0
            projlenSq = (float) 0.0;
        } else {
            // switch to backwards vectors relative to x2,y2
            // x2,y2 are already the negative of x1,y1=>x2,y2
            // to get px,py to be the negative of px,py=>x2,y2
            // the dot product of two negated vectors is the same
            // as the dot product of the two normal vectors
            px = x2 - px;
            py = y2 - py;
            dotprod = px * x2 + py * y2;
            if (dotprod <= 0.0) {
                // px,py is on the side of x2,y2 away from x1,y1
                // distance to segment is length of (backwards) px,py vector
                // "length of its (clipped) projection" is now 0.0
                projlenSq = (float) 0.0;
            } else {
                // px,py is between x1,y1 and x2,y2
                // dotprod is the length of the px,py vector
                // projected on the x2,y2=>x1,y1 vector times the
                // length of the x2,y2=>x1,y1 vector
                projlenSq = dotprod * dotprod / (x2 * x2 + y2 * y2);
            }
        }
        // Distance to line is now the length of the relative point
        // vector minus the length of its projection onto the line
        // (which is zero if the projection falls outside the range
        //  of the line segment).
        float lenSq = px * px + py * py - projlenSq;
        if (lenSq < 0) {
            lenSq = 0;
        }
        return lenSq;
    }
    

    有了这个距离,您可以建立固定规则来估计该点是否在路线附近,同时考虑地图缩放级别(每个缩放级别对应一个最大距离容差)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-26
      • 2016-01-20
      • 2012-03-07
      • 1970-01-01
      • 2015-02-06
      • 1970-01-01
      • 2021-07-07
      • 2013-11-17
      相关资源
      最近更新 更多