Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PolyLine is not on the roads: it goes straight from one point to other

My map contains multiple points to tap the location of the user from where he passes, but the polyline is not shown on the roads, but shows a direct line from one marker to other. I want my polyline to go across the road: as the roads turns, it should also turn.

Here's my relevant code

 dataholder = FirebaseDatabase.getInstance().getReference("UserLocation");
 Log.d("onMapReady", "iam here");
 dataholder.addValueEventListener(new ValueEventListener() {

     @Override
     public void onDataChange(DataSnapshot dataSnapshot) {
         Log.d("data",String.valueOf(dataSnapshot.getValue()));
         System.out.println(dataSnapshot.getValue());
         for (DataSnapshot a : dataSnapshot.getChildren()) {
             MapData mapData = a.getValue(MapData.class);
             arrayList.add(mapData);
             lati.add(arrayList.get(i).getLatituide());
             longit.add(arrayList.get(i).getLongitude());
             Log.d("mapi","i am in loop");
             mMap = googleMap;
             Double lat = Double.parseDouble(lati.get(i));
             Double longi = Double.parseDouble(longit.get(i));
             sydney = new LatLng(longi, lat);
             points.add(sydney);
             MarkerOptions mop = new MarkerOptions();
             mop.position(sydney);
             mop.title("check");
             mMap.addMarker(mop);
             Log.d("latitude", String.valueOf(lat));
             Log.d("longitude", String.valueOf(longi));
             // Add a marker in Sydney and move the camera
             mMap.addMarker(new MarkerOptions().position(sydney).title("check"));
             mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));

             i++;
         }

    line.addAll(points).width(5).color(Color.RED);
    line.geodesic(true);
    mMap.addPolyline(line);

    mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
        @Override
        public boolean onMarkerClick(Marker marker) {
            Toast.makeText(getApplicationContext(),marker.getTitle().toString(),Toast.LENGTH_LONG).show();
            return false;
        }
    });
like image 637
Rana Arslan Avatar asked Mar 07 '23 14:03

Rana Arslan


1 Answers

Try to use Google Maps Roads API part Snap to Road which

returns the best-fit road geometry for a given set of GPS coordinates. This service takes up to 100 GPS points collected along a route, and returns a similar set of data with the points snapped to the most likely roads the vehicle was traveling along.

Something like that for data from Google Maps Roads API Snap to Road example:

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {

    private GoogleMap mGoogleMap;
    private MapFragment mapFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mapFragment = (MapFragment) getFragmentManager()
                .findFragmentById(R.id.map_fragment);
        mapFragment.getMapAsync(this);
    }

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

        List<LatLng> sourcePoints = new ArrayList<>();
        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 polyLineOptions = new PolylineOptions();
        polyLineOptions.addAll(sourcePoints);
        polyLineOptions.width(5);
        polyLineOptions.color(Color.BLUE);
        mGoogleMap.addPolyline(polyLineOptions);

        mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(sourcePoints.get(0), 15));

        List<LatLng> snappedPoints = new ArrayList<>();
        new GetSnappedPointsAsyncTask().execute(sourcePoints, null, snappedPoints);
    }


    private String buildRequestUrl(List<LatLng> trackPoints) {
        StringBuilder url = new StringBuilder();
        url.append("https://roads.googleapis.com/v1/snapToRoads?path=");

        for (LatLng trackPoint : trackPoints) {
            url.append(String.format("%8.5f", trackPoint.latitude));
            url.append(",");
            url.append(String.format("%8.5f", trackPoint.longitude));
            url.append("|");
        }
        url.delete(url.length() - 1, url.length());
        url.append("&interpolate=true");
        url.append(String.format("&key=%s", <your_Google_Maps_API_key>);

        return url.toString();
    }


    private class GetSnappedPointsAsyncTask extends AsyncTask<List<LatLng>, Void, List<LatLng>> {

        protected void onPreExecute() {
            super.onPreExecute();
        }

        protected List<LatLng> doInBackground(List<LatLng>... params) {

            List<LatLng> snappedPoints = new ArrayList<>();

            HttpURLConnection connection = null;
            BufferedReader reader = null;

            try {
                URL url = new URL(buildRequestUrl(params[0]));
                connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.connect();

                InputStream stream = connection.getInputStream();

                reader = new BufferedReader(new InputStreamReader(stream));
                StringBuilder jsonStringBuilder = new StringBuilder();

                StringBuffer buffer = new StringBuffer();
                String line = "";

                while ((line = reader.readLine()) != null) {
                    buffer.append(line+"\n");
                    jsonStringBuilder.append(line);
                    jsonStringBuilder.append("\n");
                }

                JSONObject jsonObject = new JSONObject(jsonStringBuilder.toString());
                JSONArray snappedPointsArr = jsonObject.getJSONArray("snappedPoints");

                for (int i = 0; i < snappedPointsArr.length(); i++) {
                    JSONObject snappedPointLocation = ((JSONObject) (snappedPointsArr.get(i))).getJSONObject("location");
                    double lattitude = snappedPointLocation.getDouble("latitude");
                    double longitude = snappedPointLocation.getDouble("longitude");
                    snappedPoints.add(new LatLng(lattitude, longitude));
                }

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            } finally {
                if (connection != null) {
                    connection.disconnect();
                }
                try {
                    if (reader != null) {
                        reader.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            return snappedPoints;
        }

        @Override
        protected void onPostExecute(List<LatLng> result) {
            super.onPostExecute(result);

            PolylineOptions polyLineOptions = new PolylineOptions();
            polyLineOptions.addAll(result);
            polyLineOptions.width(5);
            polyLineOptions.color(Color.RED);
            mGoogleMap.addPolyline(polyLineOptions);

            LatLngBounds.Builder builder = new LatLngBounds.Builder();
            builder.include(result.get(0));
            builder.include(result.get(result.size()-1));
            LatLngBounds bounds = builder.build();
            mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 10));

        }
    }

}

And don't forget to add Google Maps Roads API support for your project in Google APIs Console (select your project, than select Dashboard, than press "+ ENABLE APIS AND SERVICES " button, than on the left side "Filter by" select "Maps", than press "Google Maps Roads API" and, finally, press button "ENABLE").

You should get something like that:

Snapped points polyline

where: blue polyline - for source points, red polyline - for snapped points.

Remember there is a limit of 100 GPS points and 2500 request per day per user (IP) and 10 requests per sec. And also you need more elegant solution for snapped points JSON downloading.

like image 164
Andrii Omelchenko Avatar answered Mar 10 '23 10:03

Andrii Omelchenko