NullPointerException
NullPointerException

Reputation: 37607

How to represent direction in a route in google maps?

In a project I'm displaying a route using PolylineOptions for drawing rects from one POI to the next POI.

Also in each POI I'm drawing a circle.

The objective is to represent the direction of the route in some way, for example, drawing an arrow in the middle of each PolylineOptions rect. The problem is that I can't find how to do this.

This is my code:

    PolylineOptions rectOptions = new PolylineOptions();
    float[] prevHSV = new float[3];
    Color.colorToHSV(getResources().getColor(R.color.colorPrimary), prevHSV);
    rectOptions.color(Color.HSVToColor(255, prevHSV));

    String[][] routeInformation = ((MyApplication)getApplication()).getLineInformation(line);
    ArrayList<Double[]> routeStops = Util.getFullRouteFromLine(this, line);
    final LatLngBounds.Builder builder = new LatLngBounds.Builder();

    for (int i=0; i<routeInformation.length; i++){
        LatLng latlng = new LatLng(Double.parseDouble(routeInformation[i][0]),Double.parseDouble(routeInformation[i][1]));
        builder.include(latlng);
        mMap.addCircle(new CircleOptions().center(latlng).radius(15).strokeColor(Color.HSVToColor(255, prevHSV)).fillColor(Color.HSVToColor(255, prevHSV)).zIndex(7777));            
    }

    for (Double[] pos : routeStops){
        rectOptions.add(new LatLng(pos[0],pos[1])).width(5);
    }
    mMap.addPolyline(rectOptions);

Is there a easy way to represent the direction of a route?

Something similar to this, but this is for the web version of google maps, not for the android version: http://jsfiddle.net/nX8U8/2/

Upvotes: 0

Views: 371

Answers (1)

Andrii Omelchenko
Andrii Omelchenko

Reputation: 13343

IMHO easiest way is to use flat "north-oriented" direction marker (arrow) like that:

Direction marker

created via vector drawable ic_arrow_up.xml:

<vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:viewportHeight="560"
    android:viewportWidth="560"
    android:height="24dp"
    android:width="24dp"
    >
    <path android:fillColor="#0000FF"
        android:pathData="M0,559.43C0,557.943 279.994,-0.561 280.458,0C282.014,1.884 560.512,559.569 559.999,559.776C559.665,559.911 496.562,532.823 419.77,499.581C419.77,499.581 280.15,439.14 280.15,439.14C280.15,439.14 140.756,499.57 140.756,499.57C64.089,532.807 1.056,560 0.681,560C0.307,560 0,559.743 0,559.43C0,559.43 0,559.43 0,559.43Z"
    />
</vector>

placed on each path polyline segment middle point with angle calculated on segment bearing. Both polyline segment middle and bearing you can determine via SphericalUtil class of Google Maps Android API Utility Library . Bearing can be found via SphericalUtil.computeHeading() with first and second points of segment as arguments and LatLng of segment middle point - via SphericalUtil.interpolate() also with first and second points of segment as arguments from and to and constant 0.5 (half) as fraction argument.

So, with source like this:

...
@Override
public void onMapReady(GoogleMap googleMap) {
    mGoogleMap = googleMap;
    mGoogleMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
        @Override
        public void onMapLoaded() {
            List<LatLng> sourcePoints = new ArrayList<>();
            PolylineOptions polyLineOptions;

            sourcePoints.add(new LatLng(-35.27801,149.12958));
            sourcePoints.add(new LatLng(-35.28032,149.12907));
            sourcePoints.add(new LatLng(-35.28099,149.12929));
            sourcePoints.add(new LatLng(-35.28144,149.12984));
            sourcePoints.add(new LatLng(-35.28194,149.13003));
            sourcePoints.add(new LatLng(-35.28282,149.12956));
            sourcePoints.add(new LatLng(-35.28302,149.12881));
            sourcePoints.add(new LatLng(-35.28473,149.12836));

            polyLineOptions = new PolylineOptions();
            polyLineOptions.addAll(sourcePoints);
            polyLineOptions.width(10);
            polyLineOptions.color(Color.BLUE);
            mGoogleMap.addPolyline(polyLineOptions);
            mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(sourcePoints.get(0), 15));

            for (int i = 0; i < sourcePoints.size() - 1; i++) {
                // get first and second points of polyline segment
                LatLng segmentP1 = sourcePoints.get(i);
                LatLng segmentP2 = sourcePoints.get(i+1);

                // calculate middle point
                LatLng segmentMiddlePoint = SphericalUtil.interpolate(segmentP1, segmentP2, 0.5);
                // calculate bearing
                float segmentBearing = (float) SphericalUtil.computeHeading(segmentP1, segmentP2);

                // add flat marker at segment middle
                addDirectionMarker(segmentMiddlePoint, segmentBearing);
            }

    });

}
...
public void addDirectionMarker(LatLng latLng, float angle) {
    Drawable circleDrawable = ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_arrow_up);
    BitmapDescriptor markerIcon = getMarkerIconFromDrawable(circleDrawable, 30, 30);

    mGoogleMap.addMarker(new MarkerOptions()
            .position(latLng)
            .anchor(0.5f, 0.5f)
            .rotation(angle)
            .flat(true)
            .icon(markerIcon)
    );
}

you'll got something like that:

Path with direction markers

Also you can change size of arrows markers by set other values than 30, 30 in

BitmapDescriptor markerIcon = getMarkerIconFromDrawable(circleDrawable, 30, 30);

line.

Upvotes: 2

Related Questions