1

Edit: It was suggested that I use this formula to calculate the distance between my current location and a marker that is placed, but I am getting the same result no matter where I place the marker, which is 1.004822115417686E7. I will show that method in my updated code.

I just want the distance from my location to the Marker that is placed. I tried to use the distanceTo(Location dest) method, but I do not know how to convert my Marker LatLng into a Location object, if that's even possible. As a result, I decided to go with the Location.distanceBetween method.

The problem is that my results are not correct at all. What am I doing wrong? Have I misread the Android Docs?

All I'm doing is performing an onMapLongClickto add a Marker. There is not a Marker on the current location. It will just be the blue dot to show where the user is located.

The basics of map usage:

User parks car. User places marker on map where they parked. User goes and does something in a nearby building. User comes back out, opens app, locates car. App will show distance to car. Distances do not need to account for obstacles, turns, etc. Just a straight line distance will work.

Code:

 @Override
public void onMapLongClick(LatLng latLng) {
    mMap.clear();
    //m is the Marker
    m = mMap.addMarker(new MarkerOptions()
            .position(latLng)
            .title("My Ride")
            .icon(BitmapDescriptorFactory.fromResource(R.drawable.custom_marker30x48)));
    float[] results = new float[1];
    Location currentPos = new Location(LocationManager.GPS_PROVIDER);
    latLng = m.getPosition();
    Location.distanceBetween(currentPos.getLatitude(), currentPos.getLongitude(), latLng.latitude, latLng.longitude, results);
    Log.d(TAG, "Distance using distanceBetween(): " + results[0] + " meters");
    Log.d(TAG, "Distance using meterDistanceBetweenPoints: " + meterDistanceBetweenPoints((float)currentPos.getLatitude(), (float)currentPos.getLongitude(), (float)latLng.latitude, (float)latLng.longitude));
    Toast.makeText(getApplicationContext(), "Marker Added", Toast.LENGTH_SHORT).show();
}
private double meterDistanceBetweenPoints(float lat_a, float lng_a, float lat_b, float lng_b) {
    float pk = (float) (180.f/Math.PI);

    float a1 = lat_a / pk;
    float a2 = lng_a / pk;
    float b1 = lat_b / pk;
    float b2 = lng_b / pk;

    double t1 = Math.cos(a1) * Math.cos(a2) * Math.cos(b1) * Math.cos(b2);
    double t2 = Math.cos(a1) * Math.sin(a2) * Math.cos(b1) * Math.sin(b2);
    double t3 = Math.sin(a1) * Math.sin(b1);
    double tt = Math.acos(t1 + t2 + t3);

    return 6366000 * tt;
}

This is the output in Logcat:

Distance using distanceBetween(): 1.0061643E7 meters
Distance using meterDistanceBetweenPoints: 1.004822115417686E7

What am I doing wrong here? According to the Android Docs, it says:

The computed distance is stored in results[0]

I'm literally placing a Marker 20-30 feet from my location, so what is this strange output? It's not even correct for the new function I attempted.

DevOpsSauce
  • 1,319
  • 1
  • 20
  • 52

2 Answers2

1

In onMapLongClick you are clearing all the previous markers by this line:

mMap.clear();

Therefore every time you put new marker, previous markers are cleared. If you want marker at both place, i.e. your location and clicked location then every time on onMapLongClick do:

 @Override
public void onMapLongClick(LatLng latLng) {
    mMap.clear();
    //marker at clicked location
    mMap.addMarker(new MarkerOptions()
            .position(latLng)
            .title("My Ride")
            .icon(BitmapDescriptorFactory.fromResource(R.drawable.custom_marker30x48)));
    //marker at your location
    mMap.addMarker(new MarkerOptions()
                .position(MyLatLng)
                .title("My Location")
                .icon(BitmapDescriptorFactory.fromResource(R.drawable.custom_marker30x48)));
    //----
    //do whatever else you want
    //----    
    }

And MyLatLng you can get from onLocationChanged function:

Location MyLatLng;
@Override
public void onLocationChanged(Location location) {
    MyLatLng = location;
}

And for calculating distance between two locations refer to this solution: https://stackoverflow.com/a/8050255/7026525

Rishabh Chandel
  • 725
  • 1
  • 11
  • 28
  • Perhaps I should clarify. I'm clearing the marker every time so the user can change it if they want. The current location is just the blue dot. I don't need a marker for the current location. – DevOpsSauce Dec 31 '17 at 09:21
  • Okay, then don't put the second marker. For calculating distance simply go ahead with the second method provided in the given above link. – Rishabh Chandel Dec 31 '17 at 15:56
  • Results are still wrong. My logcat says the same result no matter where I place the marker. Even if I place it directly on top of my current location, I get 1.004822115417686E7 as the result. This is not working. – DevOpsSauce Dec 31 '17 at 18:19
0

Ok, so I think I got this unless someone posts a better answer. Since there's code involved, I'm posting it as an answer. I added a little code by creating a LocationManager object and putting my code within a try/catch block after verifying my mLocationPermissionGranted boolean was true (which it is because I already handle that before this step). I then took that result and converted it from meters to feet. Here is the updated function:

@Override
public void onMapLongClick(LatLng latLng) {
    mMap.clear();
    //m is the Marker
    m = mMap.addMarker(new MarkerOptions()
            .position(latLng)
            .title("My Ride")
            .icon(BitmapDescriptorFactory.fromResource(R.drawable.custom_marker30x48)));

    float[] results = new float[1];
    //New LocationManager object
    LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    Criteria criteria = new Criteria();
    try {
        if (mLocationPermissionsGranted) { //<-- already checked before, so it's true
            Location currentPos = locationManager.getLastKnownLocation(locationManager.getBestProvider(criteria, false));
            latLng = m.getPosition();
            Location.distanceBetween(currentPos.getLatitude(), currentPos.getLongitude(), latLng.latitude, latLng.longitude, results);
            Log.d(TAG, "Distance using distanceBetween(): " + (results[0])/0.3048 + " feet"); //<-- CONVERT FROM METERS TO FEET
            Log.d(TAG, "Distance using meterDistanceBetweenPoints: " + (meterDistanceBetweenPoints((float) currentPos.getLatitude(), (float) currentPos.getLongitude(), (float) latLng.latitude, (float) latLng.longitude))/0.3048); //<-- CONVERT FROM METERS TO FEET
            //Toast.makeText(getApplicationContext(), "Marker Added", Toast.LENGTH_SHORT).show();
            Toast.makeText(getApplicationContext(), "Result: " + (results[0])/0.3048 + " feet", Toast.LENGTH_LONG).show();
        }
    } catch(SecurityException e) {
        Log.d(TAG, "Exception: " + e.getMessage());
    }
}
private double meterDistanceBetweenPoints(float lat_a, float lng_a, float lat_b, float lng_b) {
    float pk = (float) (180.f/Math.PI);

    float a1 = lat_a / pk;
    float a2 = lng_a / pk;
    float b1 = lat_b / pk;
    float b2 = lng_b / pk;

    double t1 = Math.cos(a1) * Math.cos(a2) * Math.cos(b1) * Math.cos(b2);
    double t2 = Math.cos(a1) * Math.sin(a2) * Math.cos(b1) * Math.sin(b2);
    double t3 = Math.sin(a1) * Math.sin(b1);
    double tt = Math.acos(t1 + t2 + t3);

    return 6366000 * tt;
}

I measured the length of where I'm standing, and the result was roughly 35 feet. I'm using a tape measure, so it's not highly accurate, but it will suffice for this. My result in Logcat was:

Distance using distanceBetween(): 34.041595584138484 feet
Distance using meterDistanceBetweenPoints: 33.671114637701

I think I got it! If anyone has a better solution, let me know. I'm open to suggestions.

DevOpsSauce
  • 1,319
  • 1
  • 20
  • 52