Обрабатывать клик по маршруту - PullRequest
0 голосов
/ 18 февраля 2012

Я пытаюсь проверить работоспособность интерактивного маршрута с помощью API карты Google.

Я установил отображение маршрута между двумя координатами с помощью API карты.

Чтобы реализовать это, я использовал следующееучебное пособие http://csie -tw.blogspot.com / 2009/06 / android-driving-direction-route-path.html , которое в основном анализирует файл KML (ответ на запрос направления карты Google) ииспользуйте пользовательское наложение карты для рисования маршрута.

Пользовательское наложение:

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, мы можем получитьгеопункт, связанный с кликом.
  • Затем мы попытаемся установить, является ли выбранный геопункт частью сегмента маршрута.

Последняя информация: на карте будет нарисовано несколько маршрутов.в тот же момент, поэтому щелчок должен быть связан с уникальным маршрутом, а не со всеми.

Спасибо.

1 Ответ

1 голос
/ 13 января 2013

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

Имея это расстояние, вы можете установить фиксированные правила для оценки того, находится ли точка рядом с маршрутом, с учетом уровня масштабирования карты (каждому уровню масштабирования соответствует максимальный допуск на расстояние).

...