0

I'm having a difficult time figuring out how to properly get distances between two Locations in Xamarin. At least I'm consistently getting the wrong results, according to almighty Google.

This code explains the problem.

    public void OnLocationChanged(Location location)
    {
        // Longitude/Latitude of Tower Bridge.
        location.Longitude = 51.5053446;
        location.Latitude = -0.0765396;

        foreach (var store in this.stores)
        {
            if (store.DistanceView != null)
            {
                Location store_loc = new Location(location.Provider);
                //store_loc.Longitude = double.Parse(store.GPSN);
                //store_loc.Latitude = double.Parse(store.GPSW);

                // Longitude/Latitude of Big Ben.
                store_loc.Longitude = 51.5005747;
                store_loc.Latitude = -0.1247025;

                var distance = location.DistanceTo(store_loc);

                // Google Maps ("measure distance") says 3.44km.
                // Xamarin (variable "distance") says 5351.983 meters.

                store.DistanceView.Text = distance.ToString();
            }
        }
    }

The actual locations I'm working with are different (for reasons of privacy), but the measurement error is similar, in that I'm getting a result that's not quite twice as high as measured by Google Maps, but somewhere in the vicinity. At any rate, the above measurements should match, and they don't.

Teekin
  • 12,581
  • 15
  • 55
  • 67
  • What unit of measurement are you expecting to get back? DistanceTo returns meters. Also, the documentation explains that it is approximate. If it isn't giving you the expected results, you could always make your own function for more precise measurements. The formula isn't too difficult. – Brandon Miller Jan 08 '19 at 21:02
  • After doing some research, it looks like GeoCoordinate.GetDistanceTo() may be a little more precise? https://forums.xamarin.com/discussion/104195/distance-between-two-coordinates-using-geocoder – Brandon Miller Jan 08 '19 at 21:14
  • 1
    You are comparing an WGS84 ellipsoid measurement (android) against a great circle measurement (google map javascript), plus, the bigger issue?, it seems you have a unit of measure issue: miles vs meters (I have not plugged those locs into my calculator), plus those locations are not very precise, 12-14 places for a really good distance) – SushiHangover Jan 08 '19 at 21:14
  • @SushiHangover: Thanks for the hint! I'm completely new to location theory, but according to the following answer, 12-14 places is total overkill, in fact 7 is almost overkill and near the limit of what GPS can achieve: https://gis.stackexchange.com/questions/8650/measuring-accuracy-of-latitude-and-longitude/8674#8674 – Teekin Jan 09 '19 at 11:53
  • @SushiHangover: I agree that the numbers *look* like it's a metric/imperial problem, but Xamarin tells me that those are meters and Google Maps tells me the others are kilometers. I don't know where imperial might come from, since I'm in a place where metric is used and American cinema is pretty much the only place I run into imperial numbers. – Teekin Jan 09 '19 at 11:59
  • @BrandonMiller: I expect to get meters from `DistanceView`, because its description explicitly declares the result to be in meters. I expect kilometers from Google because it says "km". – Teekin Jan 09 '19 at 12:16
  • @SushiHangover: http://www.movable-type.co.uk/scripts/latlong.html says that the difference between accounting for the ellipsoidal shape of the Earth and not doing so can lead to errors up to 0.3%. That would be fine in my case, but my results are out of whack, considering that. – Teekin Jan 09 '19 at 12:23
  • @Teekin I plugged your values into my utilities and yes, what you are seeing is "correct", but correct to who's definition. Android Location is based upon an ellipsoid calculation, but it is wonky at best, you can search in the android bug tracker about it, but it will not change as it has been that way since API 1. Using something like my answer here (https://stackoverflow.com/a/49332522/4984832) you will get your ~3448 meter result and note, this formula is based upon Google Android Maps Utils / SphericalUtil methods (I do not use the Android Location distance/distancebetween/speed/etc..) – SushiHangover Jan 09 '19 at 21:05
  • @Teekin Note: The Google SphericalUtil is not "highly accurate" depending upon which part of the world you are using it for, but it is fast, so you are not going to perform airplane/drone/autonomous maneuvers with it as +/-10m means crash/live-death, but for normal human/car nav. directions, time remaining, fuel checks, etc.. it works fine. – SushiHangover Jan 09 '19 at 21:10
  • Thank you again for the help. I'm still having trouble getting those 3.4-3.5km using your code (I only need accuracy up to 100 meters or so): var loc_tower_bridge = new LatLng(51.5053446, -0.0765396); var loc_big_ben = new LatLng(51.5005747, -0.1247025); var dist = Meters.ComputeDistanceBetween(loc_tower_bridge, loc_big_ben); // Gives me 5381.6775670637. – Teekin Jan 10 '19 at 13:59
  • @SushiHangover: But I'm a bit confused about "correct" according to who's definition. The meter is very well defined, and surely the only correct answer is the amount of meters between two points on the surface of the earth, accounting for curvature. I don't see what other answer could be correct, of course given varying accuracy and precision. I'm trying to get the distance that one must travel to another point (100-meter inaccuracy is fine). I don't see how such widely varying results could both be correct by anyone's measure. – Teekin Jan 10 '19 at 14:06
  • @Teekin I used your LatLng values and just got `3375.57597257177`, using LatLng from Google Places on those two Landmarks, ('LatLng(51.5055, -0.075406); LatLng(51.5007, -0.124621);'), I get `3448.01877639027`, not sure how you got `5381.*` using ComputeDistanceBetween. – SushiHangover Jan 10 '19 at 22:50
  • @SushiHangover: Pardon the noobness, but I'm having a hard time figuring out where to get Google Places LatLng from (tried Xamarin.Google.Places.Api.Android and Google.Apis NuGet packages). My result came from handrolling my own LatLng, since it looked like a simple container class for a couple of doubles. Also, does that solution require Google PlayServices to be installed? – Teekin Jan 13 '19 at 16:06
  • @SushiHangover: I found it by installing Xamarin.GooglePlayServices.Places through NuGet, and now I'm getting the proper result. Looks like I'll just have to accept the PlayServices requirement, although I was hoping to get away with not using it. If you post your advice as an answer to the question, I'll accept it as the correct one, even if it's just a link to your other answer or a copy/paste of the code. At any rate, thanks again! :) – Teekin Jan 13 '19 at 16:26

0 Answers0