Question

What I want : My app requires plotting driving directions from source to destination, which is done.My problem is I need a directional arrow pointing from source to destination.

What have I done: I am able to draw an arrow, also I have calculated angle but don't know how to apply that angle to the code so that the arrow rotates... I have tried all code..nothing works,the arrow gets drawn at source but points in wrong direction.

PS: I have tried this Direction between two GeoPoints in Google map in android Didn't find solution I don't want to show google maps service.. I mean i don't want to use the URI.parse() thing.

Below is the code I am using :

  public class MapRouteActivity extends MapActivity {

    LinearLayout linearLayout;
    MapView mapView;
    private Road mRoad;
    public final double fromLat = 17.40531527709,
            fromLon = 78.46830368042, toLat = 17.42091669870207,
            toLon = 78.4507942199707;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mapView = (MapView) findViewById(R.id.mapview);
        mapView.setBuiltInZoomControls(true);

        new Thread() {
            @Override
            public void run() {

                String url = RoadProvider
                        .getUrl(fromLat, fromLon, toLat, toLon);
                InputStream is = getConnection(url);
                mRoad = RoadProvider.getRoute(is);
                mHandler.sendEmptyMessage(0);
            }
        }.start();
    }

    Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            TextView textView = (TextView) findViewById(R.id.description);
            textView.setText(mRoad.mName + " " + mRoad.mDescription);
            MapOverlay mapOverlay = new MapOverlay(mRoad, mapView);
            List<Overlay> listOfOverlays = mapView.getOverlays();
            listOfOverlays.clear();
            listOfOverlays.add(mapOverlay);
            mapView.getController().setZoom(14);
            mapView.invalidate();
        };
    };

    private InputStream getConnection(String url) {
        InputStream is = null;
        try {
            URLConnection conn = new URL(url).openConnection();
            is = conn.getInputStream();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return is;
    }

    @Override
    protected boolean isRouteDisplayed() {
        return true;
    }

    class MapOverlay extends com.google.android.maps.Overlay {
        Road mRoad;
        ArrayList<GeoPoint> mPoints;

        public MapOverlay(Road road, MapView mv) {
            mRoad = road;
            if (road.mRoute.length > 0) {
                mPoints = new ArrayList<GeoPoint>();
                for (int i = 0; i < road.mRoute.length; i++) {
                    mPoints.add(new GeoPoint(
                            (int) (road.mRoute[i][1] * 1000000),
                            (int) (road.mRoute[i][0] * 1000000)));
                }
                int moveToLat = (mPoints.get(0).getLatitudeE6() + (mPoints.get(
                        mPoints.size() - 1).getLatitudeE6() - mPoints.get(0)
                        .getLatitudeE6()) / 2);
                int moveToLong = (mPoints.get(0).getLongitudeE6() + (mPoints
                        .get(mPoints.size() - 1).getLongitudeE6() - mPoints
                        .get(0).getLongitudeE6()) / 2);
                GeoPoint moveTo = new GeoPoint(moveToLat, moveToLong);

                MapController mapController = mv.getController();
                mapController.animateTo(moveTo);
                mapController.setZoom(7);
            }
        }

        @Override
        public boolean draw(Canvas canvas, MapView mv, boolean shadow, long when) {
            super.draw(canvas, mv, shadow);
            drawPath(mv, canvas);
            return true;
        }

        public void drawPath(MapView mv, Canvas canvas) {
            int x1 = -1, y1 = -1, x2 = -1, y2 = -1;
            Paint paint = new Paint();
            paint.setColor(Color.GREEN);
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(3);
            for (int i = 0; i < mPoints.size(); i++) {
                Point point = new Point();
                mv.getProjection().toPixels(mPoints.get(i), point);
                x2 = point.x;
                y2 = point.y;
                if (i > 0) {
                    canvas.drawLine(x1, y1, x2, y2, paint);
                }
                x1 = x2;
                y1 = y2;
            }


            Point pointFrom = new Point();
            GeoPoint gp1 = new GeoPoint((int) (fromLat * 1E6),
                    (int) (fromLon * 1E6));
            Point pointTo = new Point();
            GeoPoint gp2 = new GeoPoint((int) (toLat * 1E6),
                    (int) (toLon * 1E6));
            Projection projection = mapView.getProjection();
            projection.toPixels(gp1, pointFrom);
            projection.toPixels(gp2, pointTo);
            Bitmap bmp = BitmapFactory.decodeResource(getResources(),R.drawable.arrow1);
            double dlon = gp2.getLongitudeE6() - gp1.getLongitudeE6();
            double dlat = gp2.getLatitudeE6() - gp1.getLatitudeE6();
            double angle = getDegrees(fromLat, fromLon, toLat, toLon, 15);
            Matrix matrix = new Matrix();
            matrix.postTranslate(-25, -25);
            matrix.postRotate((float)Math.toRadians(angle));
            matrix.postTranslate(pointFrom.x, pointFrom.y);       
            paint.setAntiAlias(true);
            paint.setFilterBitmap(true);
            canvas.drawBitmap(bmp, matrix, paint);
        }
    }

    double getDegrees(double lat1, double long1, double lat2, double long2, double headX) {

        double dLat =  Math.toRadians(lat2-lat1);
        double dLon =  Math.toRadians(long2-long1);

        lat1 = Math.toRadians(lat1);
        lat2 =  Math.toRadians(lat2);

        double y = Math.sin(dLon) * Math.cos(lat2);
        double x = Math.cos(lat1)*Math.sin(lat2) -
                Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
        double brng = Math.toDegrees(Math.atan2(y, x));

        // fix negative degrees
        if(brng<0) {
            brng=360-Math.abs(brng);
        }

        return brng - headX;
    }
}

Code in Road.java

 public class Road {
    public String mName;
    public String mDescription;
    public int mColor;
    public int mWidth;
    public double[][] mRoute = new double[][] {};
    public Point[] mPoints = new Point[] {};
}

Code in Point.java

package com.abhi.maproute;

public class Point {
    String mName;
    String mDescription;
    String mIconUrl;
    double mLatitude;
    double mLongitude;
}

Code in RoadProvider.java

package com.abhi.maproute;

/**
 * @author asadafale
 *
 */
import java.io.IOException;
import java.io.InputStream;
import java.util.Stack;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class RoadProvider {

    public static Road getRoute(InputStream is) {
        KMLHandler handler = new KMLHandler();
        try {
            SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
            parser.parse(is, handler);
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return handler.mRoad;
    }

    public static String getUrl(double fromLat, double fromLon, double toLat,
            double toLon) {// connect to map web service
        StringBuffer urlString = new StringBuffer();
        urlString.append("http://maps.google.com/maps?f=d&hl=en");
        urlString.append("&saddr=");// from
        urlString.append(Double.toString(fromLat));
        urlString.append(",");
        urlString.append(Double.toString(fromLon));
        urlString.append("&daddr=");// to
        urlString.append(Double.toString(toLat));
        urlString.append(",");
        urlString.append(Double.toString(toLon));
        urlString.append("&ie=UTF8&0&om=0&output=kml");
        System.out.println("url..."+urlString.toString());
        return urlString.toString();
    }
}

class KMLHandler extends DefaultHandler {
    Road mRoad;
    boolean isPlacemark;
    boolean isRoute;
    boolean isItemIcon;
    private Stack<String> mCurrentElement = new Stack<String>();
    private String mString;

    public KMLHandler() {
        mRoad = new Road();
    }

    public void startElement(String uri, String localName, String name,
            Attributes attributes) throws SAXException {
        mCurrentElement.push(localName);
        if (localName.equalsIgnoreCase("Placemark")) {
            isPlacemark = true;
            mRoad.mPoints = addPoint(mRoad.mPoints);
        } else if (localName.equalsIgnoreCase("ItemIcon")) {
            if (isPlacemark)
                isItemIcon = true;
        }
        mString = new String();
    }

    public void characters(char[] ch, int start, int length)
            throws SAXException {
        String chars = new String(ch, start, length).trim();
        mString = mString.concat(chars);
    }

    public void endElement(String uri, String localName, String name)
            throws SAXException {
        if (mString.length() > 0) {
            if (localName.equalsIgnoreCase("name")) {
                if (isPlacemark) {
                    isRoute = mString.equalsIgnoreCase("Route");
                    if (!isRoute) {
                        mRoad.mPoints[mRoad.mPoints.length - 1].mName = mString;
                    }
                } else {
                    mRoad.mName = mString;
                }
            } else if (localName.equalsIgnoreCase("color") && !isPlacemark) {
                mRoad.mColor = Integer.parseInt(mString, 16);
            } else if (localName.equalsIgnoreCase("width") && !isPlacemark) {
                mRoad.mWidth = Integer.parseInt(mString);
            } else if (localName.equalsIgnoreCase("description")) {
                if (isPlacemark) {
                    String description = cleanup(mString);
                    if (!isRoute)
                        mRoad.mPoints[mRoad.mPoints.length - 1].mDescription = description;
                    else
                        mRoad.mDescription = description;
                }
            } else if (localName.equalsIgnoreCase("href")) {
                if (isItemIcon) {
                    mRoad.mPoints[mRoad.mPoints.length - 1].mIconUrl = mString;
                }
            } else if (localName.equalsIgnoreCase("coordinates")) {
                if (isPlacemark) {
                    if (!isRoute) {
                        String[] xyParsed = split(mString, ",");
                        double lon = Double.parseDouble(xyParsed[0]);
                        double lat = Double.parseDouble(xyParsed[1]);
                        mRoad.mPoints[mRoad.mPoints.length - 1].mLatitude = lat;
                        mRoad.mPoints[mRoad.mPoints.length - 1].mLongitude = lon;
                    } else {
                        String[] coodrinatesParsed = split(mString, " ");
                        int lenNew = coodrinatesParsed.length;
                        int lenOld = mRoad.mRoute.length;
                        double[][] temp = new double[lenOld + lenNew][2];
                        for (int i = 0; i < lenOld; i++) {
                            temp[i] = mRoad.mRoute[i];
                        }
                        for (int i = 0; i < lenNew; i++) {
                            String[] xyParsed = split(coodrinatesParsed[i], ",");
                            for (int j = 0; j < 2 && j < xyParsed.length; j++)
                                temp[lenOld + i][j] = Double
                                        .parseDouble(xyParsed[j]);
                        }
                        mRoad.mRoute = temp;
                    }
                }
            }
        }
        mCurrentElement.pop();
        if (localName.equalsIgnoreCase("Placemark")) {
            isPlacemark = false;
            if (isRoute)
                isRoute = false;
        } else if (localName.equalsIgnoreCase("ItemIcon")) {
            if (isItemIcon)
                isItemIcon = false;
        }
    }

    private String cleanup(String value) {
        String remove = "<br/>";
        int index = value.indexOf(remove);
        if (index != -1)
            value = value.substring(0, index);
        remove = "&#160;";
        index = value.indexOf(remove);
        int len = remove.length();
        while (index != -1) {
            value = value.substring(0, index).concat(
                    value.substring(index + len, value.length()));
            index = value.indexOf(remove);
        }
        return value;
    }

    public Point[] addPoint(Point[] points) {
        Point[] result = new Point[points.length + 1];
        for (int i = 0; i < points.length; i++)
            result[i] = points[i];
        result[points.length] = new Point();
        return result;
    }

    private static String[] split(String strString, String strDelimiter) {
        String[] strArray;
        int iOccurrences = 0;
        int iIndexOfInnerString = 0;
        int iIndexOfDelimiter = 0;
        int iCounter = 0;
        if (strString == null) {
            throw new IllegalArgumentException("Input string cannot be null.");
        }
        if (strDelimiter.length() <= 0 || strDelimiter == null) {
            throw new IllegalArgumentException(
                    "Delimeter cannot be null or empty.");
        }
        if (strString.startsWith(strDelimiter)) {
            strString = strString.substring(strDelimiter.length());
        }
        if (!strString.endsWith(strDelimiter)) {
            strString += strDelimiter;
        }
        while ((iIndexOfDelimiter = strString.indexOf(strDelimiter,
                iIndexOfInnerString)) != -1) {
            iOccurrences += 1;
            iIndexOfInnerString = iIndexOfDelimiter + strDelimiter.length();
        }
        strArray = new String[iOccurrences];
        iIndexOfInnerString = 0;
        iIndexOfDelimiter = 0;
        while ((iIndexOfDelimiter = strString.indexOf(strDelimiter,
                iIndexOfInnerString)) != -1) {
            strArray[iCounter] = strString.substring(iIndexOfInnerString,
                    iIndexOfDelimiter);
            iIndexOfInnerString = iIndexOfDelimiter + strDelimiter.length();
            iCounter += 1;
        }

        return strArray;
    }
}
Was it helpful?

Solution

A new option (released at Google I/O 2012) is symbols (including arrows) on polylines, the directions renderer can create a polyline.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top