Skip to content Skip to sidebar Skip to footer

Plotting Coordinates On Route In Gmap (Google Maps Android API)

I'm currently working on one Android application using Google map. My requirement is to draw a route between source-destination and plot markers at every 500 meters on that route.

Solution 1:

Objectives

The objective is getting a list of LatLng coordinates along the route returned by the Directions API web service at every N meters. Later we can create markers for this list of coordinates.

Solution

The solution has two steps. The first one is getting a list of LatLng that form a route returned by Directions API. You can use a Java Client for Google Maps Services to execute Directions API request and extract a list of LatLng. Have a look at private List<LatLng> getDirectionsPathFromWebService(String origin, String destination) method in my example. This method calls Directions API and loop through legs and steps of the route object to get a complete list of LatLng that form a route.

The second step is implemented in the method private List<LatLng> getMarkersEveryNMeters(List<LatLng> path, double distance). It loops through all LatLng from the first step and creates a list of LatLng at every N meters where N is a distance in meters passed as a second parameter of the method. This method uses internally SphericalUtil class from the Google Maps Android API Utility Library. Have a look at comment to figure out what is happening in this method.

Finally, I create markers from the list that was obtained in second step.

Code snippet

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private GoogleMap mMap;
    private String TAG = "so47784512";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        String origin = "Avinguda Diagonal, 101, 08005 Barcelona, Spain";
        String destination = "Carrer de París, 67, 08029 Barcelona, Spain";

        LatLng center = new LatLng(41.391942,2.179413);

        //Define list to get all latlng for the route
        List<LatLng> path = this.getDirectionsPathFromWebService(origin, destination);

        //Draw the polyline
        if (path.size() > 0) {
            PolylineOptions opts = new PolylineOptions().addAll(path).color(Color.BLUE).width(5);
            mMap.addPolyline(opts);
        }

        List<LatLng> markers = this.getMarkersEveryNMeters(path, 500.0);

        if (markers.size() > 0) {
            for (LatLng m : markers) {
                MarkerOptions mopts = new MarkerOptions().position(m);
                mMap.addMarker(mopts);
            }
        }

        mMap.getUiSettings().setZoomControlsEnabled(true);

        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(center, 13));
    }

    private List<LatLng> getDirectionsPathFromWebService(String origin, String destination) {
        List<LatLng> path = new ArrayList();


        //Execute Directions API request
        GeoApiContext context = new GeoApiContext.Builder()
                .apiKey("AIzaSyBrPt88vvoPDDn_imh-RzCXl5Ha2F2LYig")
                .build();
        DirectionsApiRequest req = DirectionsApi.getDirections(context, origin, destination);
        try {
            DirectionsResult res = req.await();

            //Loop through legs and steps to get encoded polylines of each step
            if (res.routes != null && res.routes.length > 0) {
                DirectionsRoute route = res.routes[0];

                if (route.legs !=null) {
                    for(int i=0; i<route.legs.length; i++) {
                        DirectionsLeg leg = route.legs[i];
                        if (leg.steps != null) {
                            for (int j=0; j<leg.steps.length;j++){
                                DirectionsStep step = leg.steps[j];
                                if (step.steps != null && step.steps.length >0) {
                                    for (int k=0; k<step.steps.length;k++){
                                        DirectionsStep step1 = step.steps[k];
                                        EncodedPolyline points1 = step1.polyline;
                                        if (points1 != null) {
                                            //Decode polyline and add points to list of route coordinates
                                            List<com.google.maps.model.LatLng> coords1 = points1.decodePath();
                                            for (com.google.maps.model.LatLng coord1 : coords1) {
                                                path.add(new LatLng(coord1.lat, coord1.lng));
                                            }
                                        }
                                    }
                                } else {
                                    EncodedPolyline points = step.polyline;
                                    if (points != null) {
                                        //Decode polyline and add points to list of route coordinates
                                        List<com.google.maps.model.LatLng> coords = points.decodePath();
                                        for (com.google.maps.model.LatLng coord : coords) {
                                            path.add(new LatLng(coord.lat, coord.lng));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch(Exception ex) {
            Log.e(TAG, ex.getLocalizedMessage());
        }

        return path;
    }

    private List<LatLng> getMarkersEveryNMeters(List<LatLng> path, double distance) {
        List<LatLng> res = new ArrayList();

        LatLng p0 = path.get(0);
        res.add(p0);
        if (path.size() > 2) {
            //Initialize temp variables for sum distance between points and
            //and save the previous point
            double tmp = 0;
            LatLng prev = p0;
            for (LatLng p : path) {
                //Sum the distance
                tmp += SphericalUtil.computeDistanceBetween(prev, p);
                if (tmp < distance) {
                    //If it is less than certain value continue sum
                    prev = p;
                    continue;
                } else {
                    //If distance is greater than certain value lets calculate
                    //how many meters over desired value we have and find position of point
                    //that will be at exact distance value
                    double diff = tmp - distance;
                    double heading = SphericalUtil.computeHeading(prev, p);

                    LatLng pp = SphericalUtil.computeOffsetOrigin(p, diff, heading);

                    //Reset sum set calculated origin as last point and add it to list
                    tmp = 0;
                    prev = pp;
                    res.add(pp);
                    continue;
                }
            }

            //Add the last point of route
            LatLng plast = path.get(path.size()-1);
            res.add(plast);
        }

        return res;
    }
}

Conclusion

You can see a result of sample code in the following screenshot

enter image description here

The sample project can be found on GitHub:

https://github.com/xomena-so/so47784512

Do not forget to replace an API key with your's.

I hope this helps!


Post a Comment for "Plotting Coordinates On Route In Gmap (Google Maps Android API)"