How to buffer a polyline in Android or draw a poly

2019-01-26 07:56发布

I am trying to put a buffer around a polyline in MapsV2 for android but I haven't find how to do it yet, I was thinking on drawing a polygon around the polyline but also haven't found anyone that have done that, is it possible?

4条回答
Lonely孤独者°
2楼-- · 2019-01-26 08:07

Do you want to draw Path on the map or Do you want to draw straight lines on the map.

In both cases you can follow below code

PolylineOptions polyLineOptions = new PolylineOptions();
ArrayList<LatLng> points = new ArrayList<>();

//Code to populate Latlng

polyLineOptions.addAll(points);
polyLineOptions.width(mActivity.getResources().getDimensionPixelSize(R.dimen._2sdp));
polyLineOptions.color(ContextCompat.getColor(mContext, Color_Resource_id));
if (polyLineOptions != null) {
    googleMap.addPolyline(polyLineOptions);
}

Above code is to draw only straight lines on Map.

Now if you wanna draw complete path on Map, You would probably need to use google direction api https://maps.googleapis.com/maps/api/directions/

You can use below class to parse response from the same to get total latlngs

public class PathJSONParser {

    public List<List<HashMap<String, String>>> parse(JSONObject jObject) {
        List<List<HashMap<String, String>>> routes = new ArrayList<>();
        JSONArray jRoutes;
        JSONArray jLegs;
        JSONArray jSteps;
        try {
            jRoutes = jObject.getJSONArray("routes");
            /** Traversing all routes */
            for (int i = 0; i < jRoutes.length(); i++) {
                jLegs = ((JSONObject) jRoutes.get(i)).getJSONArray("legs");
                List<HashMap<String, String>> path = new ArrayList<>();

                /** Traversing all legs */
                for (int j = 0; j < jLegs.length(); j++) {
                    jSteps = ((JSONObject) jLegs.get(j)).getJSONArray("steps");

                    /** Traversing all steps */
                    for (int k = 0; k < jSteps.length(); k++) {
                        String polyline;
                        polyline = (String) ((JSONObject) ((JSONObject) jSteps
                                .get(k)).get("polyline")).get("points");
                        List<LatLng> list = decodePoly(polyline);

                        /** Traversing all points */
                        for (int l = 0; l < list.size(); l++) {
                            HashMap<String, String> hm = new HashMap<>();
                            hm.put("lat",
                                    Double.toString(( list.get(l)).latitude));
                            hm.put("lng",
                                    Double.toString(( list.get(l)).longitude));
                            path.add(hm);
                        }
                    }
                    routes.add(path);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return routes;
    }

    /**
     * Method Courtesy :
     * jeffreysambells.com/2010/05/27
     * /decoding-polylines-from-google-maps-direction-api-with-java
     * */
    private List<LatLng> decodePoly(String encoded) {

        List<LatLng> poly = new ArrayList<>();
        int index = 0, len = encoded.length();
        int lat = 0, lng = 0;

        while (index < len) {
            int b, shift = 0, result = 0;
            do {
                b = encoded.charAt(index++) - 63;
                result |= (b & 0x1f) << shift;
                shift += 5;
            } while (b >= 0x20);
            int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
            lat += dlat;

            shift = 0;
            result = 0;
            do {
                b = encoded.charAt(index++) - 63;
                result |= (b & 0x1f) << shift;
                shift += 5;
            } while (b >= 0x20);
            int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
            lng += dlng;

            LatLng p = new LatLng((((double) lat / 1E5)),
                    (((double) lng / 1E5)));
            poly.add(p);
        }
        return poly;
    }
}

And finally you can use this in your class with below code

private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {

        @Override
        protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) {

            JSONObject jObject;
            List<List<HashMap<String, String>>> routes = new ArrayList<>();

            try {
                jObject = new JSONObject(jsonData[0]);
                PathJSONParser parser = new PathJSONParser();
                routes = parser.parse(jObject);
            } catch (Exception e) {
                e.printStackTrace();
            }

            return routes;
        }

        @Override
        protected void onPostExecute(List<List<HashMap<String, String>>> routes) {
            if (routes != null && routes.size() > 0) {
                new DrawPoly().execute(routes);
            }

        }
    }

    private class DrawPoly extends AsyncTask<List<List<HashMap<String, String>>>,
            PolylineOptions, PolylineOptions> {

        @Override
        protected PolylineOptions doInBackground(List<List<HashMap<String, String>>>... params) {
            PolylineOptions polyLineOptions = new PolylineOptions();
            ArrayList<LatLng> points;

            if (params[0] != null && params[0].size() > 0) {
                // traversing through routes
                for (int j = 0; j < params[0].size(); j++) {
                    points = new ArrayList<>();
                    polyLineOptions = new PolylineOptions();
                    try {
                        List<HashMap<String, String>> path = params[0].get(j);
                        for (int k = 0; k < path.size(); k++) {
                            HashMap<String, String> point = path.get(k);
                            double lat = Double.parseDouble(point.get("lat"));
                            double lng = Double.parseDouble(point.get("lng"));
                            LatLng position = new LatLng(lat, lng);
                            points.add(position);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    polyLineOptions.addAll(points);
                    polyLineOptions.width(mActivity.getResources().getDimensionPixelSize(R.dimen.five));
                    polyLineOptions.color(ContextCompat.getColor(mContext, R.color.red));
                }
            }
            return polyLineOptions;
        }

        @Override
        protected void onPostExecute(PolylineOptions polyLineOptions) {
            super.onPostExecute(polyLineOptions);
            if (polyLineOptions != null) {
                googleMap.addPolyline(polyLineOptions);
            }
        }
    }

You need to make sure you are putting it in asyncTask. I hope it will work for you.

查看更多
\"骚年 ilove
3楼-- · 2019-01-26 08:08

in Google's directions api (https://maps.googleapis.com/maps/api/directions/json?origin=75+9th+Ave+New+York,+NY&destination=MetLife+Stadium+1+MetLife+Stadium+Dr+East+Rutherford,+NJ+07073&key=YOUR_API_KEY ) you get one overview_polyline jsonObject, get encoded points From here, and decode it using this method:

private List<LatLng> decodePoly(String encoded) {

        List<LatLng> poly = new ArrayList<>();
        int index = 0, len = encoded.length();
        int lat = 0, lng = 0;

        while (index < len) {
            int b, shift = 0, result = 0;
            do {
                b = encoded.charAt(index++) - 63;
                result |= (b & 0x1f) << shift;
                shift += 5;
            } while (b >= 0x20);
            int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
            lat += dlat;

            shift = 0;
            result = 0;
            do {
                b = encoded.charAt(index++) - 63;
                result |= (b & 0x1f) << shift;
                shift += 5;
            } while (b >= 0x20);
            int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
            lng += dlng;

            LatLng p = new LatLng((((double) lat / 1E5)),
                    (((double) lng / 1E5)));
            poly.add(p);
        }
        return poly;
    }

You get List of latitude and longitude, now, using google map's getMapAsync Method add this latlng in your map :

googleMap.addPolyline(new PolylineOptions().geodesic(true).addAll(latLngList));
查看更多
4楼-- · 2019-01-26 08:27

I have found a way to add the polylines to the map.

From the above link you need three classes from google maps android util. MathUtil, PolyUtil ans SpheriacalUtil.

I made a function and use Retrofit for connection to Google

public void drawMapPath (String origin, String destination, String travel){

    RestInterface restInterface = ApiClient.getClient().create(RestInterface.class);
    Call<GoogleDirections> call = restInterface.getDirections(origin, destination, travel, AppConfig.API_GOOGLEMAPS);
    call.enqueue(new Callback<GoogleDirections>(){
        @Override
        public void onResponse(Call<GoogleDirections> call, Response<GoogleDirections> response){
           if (response.isSuccessful()){
               Routes[] route = response.body().getRoutes();
               /** get bounds to set map after completion */
               LatLngBounds.Builder mapBounds = new LatLngBounds.Builder();
               LatLng northEast = new LatLng(Double.parseDouble(route[0].getBounds().getNortheast().getLat()),Double.parseDouble(route[0].getBounds().getNortheast().getLng()));
               mapBounds.include(northEast);
               LatLng southWest = new LatLng(Double.parseDouble(route[0].getBounds().getSouthwest().getLat()),Double.parseDouble(route[0].getBounds().getSouthwest().getLng()));
               mapBounds.include(southWest);
               /** no alternatives set so only one route*/
               Legs[] leg = route[0].getLegs();
               /** get the steps */
               Steps[] step =leg[0].getSteps();
               /** init points and options */
               points = new ArrayList();
               lineOptions = new PolylineOptions();
               /** Traversing through the steps */
               for (int i=0; i < step.length; i++ ){
                   String polyline;
                   polyline = step[i].getPolyline().getPoints();
                   /** classes needed from google */
                   List<LatLng> list = decodePoly(polyline);
                   /** Traversing all points in list*/
                   for (int n = 0; n < list.size(); n++) {
                       double lat = list.get(n).latitude;
                       double lon = list.get(n).longitude;
                       LatLng position=new LatLng(lat, lon);
                       points.add(position);
                   }
               }
               lineOptions.addAll(points);
               lineOptions.width(12);
               lineOptions.color(Color.BLUE);
               lineOptions.geodesic(true);
               googleMap.addPolyline(lineOptions);
               googleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(mapBounds.build(),10));
           } else {
               Toast.makeText(getActivity(), getString(R.string.server_broken), Toast.LENGTH_SHORT).show();
           }

        }

        @Override
        public void onFailure(Call<GoogleDirections> call, Throwable t) {
            Log.d("Error ", t.getMessage());

        }
    });
}

private List<LatLng> decodePoly(String encoded) {

    List<LatLng> poly = new ArrayList<>();
    int index = 0, len = encoded.length();
    int lat = 0, lng = 0;

    while (index < len) {
        int b, shift = 0, result = 0;
        do {
            b = encoded.charAt(index++) - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
        lat += dlat;

        shift = 0;
        result = 0;
        do {
            b = encoded.charAt(index++) - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
        lng += dlng;

        LatLng p = new LatLng((((double) lat / 1E5)),
                (((double) lng / 1E5)));
        poly.add(p);
    }
    return poly;
}
查看更多
时光不老,我们不散
5楼-- · 2019-01-26 08:33

The best way to do this would be to use the method mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(yourBounds,200));. The second argument (200) is the padding around the poly line defined in yourBounds.

Here is some example code:

private GoogleMap mMap;

public void addPolyline(ArrayList<LatLng> result) {
    // Paint Lines on map
    PolylineOptions lineOptions = null;
    lineOptions = new PolylineOptions();
    lineOptions.addAll(result);
    lineOptions.width(10);
    lineOptions.color(Color.RED);
    mMap.addPolyline(lineOptions);
    LatLngBounds.Builder b = new LatLngBounds.Builder();
    for (LatLng l: result) { b.include(l); }

    mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(b.build(),200));
}
查看更多
登录 后发表回答