Jason Steele
Jason Steele

Reputation: 1606

Finding the distance between two Geo locations when using the MvvmCross framework

I am using the MvvmCross framework to build a cross platform (iOS, Android, WP7) application. I am using the MvxGeoLocationWatcher which creates MvxGeoLocation objects for me with the required Long, Lat, speed, heading etc.

I need to find the distance between two locations (as the crow flies). On Android I call fromLocation.distanceTo(toLocation). On iOs I would use CLLocationDistance distance = [fromLocation distanceFromLocation:toLocation];.

So both these platforms use a method on the location to calculate the distance and this isn't currently available on the MvxGeoLocation object.

Are there plans to add it soon? If not what would be the best approach for me to add this functionality?

  1. Would I change the class itself and provide platform specific implementations - perhaps by making it a partial class and putting the specific code in a platform specific code partial class. Or perhaps by using extension methods?
  2. Or perhaps its best done as method that takes two points and returns the distance. In which case should this method be on MvxGeoLocationWatcher?
  3. Add the calculation algorithm in myself perhaps using something from Calculate distance of two geo points in km c# and forget about using the platform specific implementations

Upvotes: 1

Views: 1474

Answers (1)

Stuart
Stuart

Reputation: 66882

Currently mvvmcross has deliberately not included lat/lng calculations.

The motivation for this was:

  • to keep the code size down - not every app needs those calculations
  • further I have in my mind that some calculations are better done by native libraries rather than generic C# - e.g. some polygon calculations would benefit from native hardware acceleration. This type of thought is there not only for geo-calcuations, but also for other areas - e.g. whereever things like image manipulation are required, then using native acceleration makes sense.

It may be that mvvmcross provides an "official" location helper IoC plugin (or set of extension methods) at some point in the future... e.g. it maybe that we build an IoC plugin around http://xamarin.com/mobileapi ... and I'm also very happy for others to build and publish them too.

So....

At a very simple level, working out the distance between two lat/lng points is easy to do in C# - there are heaps of fairly simple code example available like the excellent javascript ones at http://www.movable-type.co.uk/scripts/latlong.html - and there are heaps of libraries on github and codeplex like http://sharpmap.codeplex.com/

In RunSat (including on iPhone) I use:

using System;

namespace Cirrious.NewRunSat.Core.Models.Utils
{
    public class DistanceCalcs
    {
        /// <summary>
        /// Calculates the distance between two points of latitude and longitude.
        /// Great Link - http://www.movable-type.co.uk/scripts/latlong.html
        /// </summary>
        /// <param name="lat1">First coordinate.</param>
        /// <param name="long1">First coordinate.</param>
        /// <param name="lat2">Second coordinate.</param>
        /// <param name="long2">Second coordinate.</param>
        /// <returns>the distance in metres</returns>
        public static Double DistanceInMetres(double lat1, double lon1, double lat2, double lon2)
        {

            if (lat1 == lat2 && lon1 == lon2)
                return 0.0;

            var theta = lon1 - lon2;

            var distance = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) +
                           Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) *
                           Math.Cos(deg2rad(theta));

            distance = Math.Acos(distance);
            if (double.IsNaN(distance))
                return 0.0;

            distance = rad2deg(distance);
            distance = distance * 60.0 * 1.1515 * 1609.344;

            return (distance);
        }

        private static double deg2rad(double deg) {
          return (deg * Math.PI / 180.0);
        }

        private static double rad2deg(double rad) {
          return (rad / Math.PI * 180.0);
        }
    }
}

Note that the license on this snippet is CC attribution - because its derived from movable type - http://www.movable-type.co.uk/scripts/latlong.html:

I offer these formulæ & scripts for free use and adaptation as my contribution to the open-source info-sphere from which I have received so much. You are welcome to re-use these scripts [under a simple attribution license, without any warranty express or implied] provided solely that you retain my copyright notice and a reference to this page.

Upvotes: 3

Related Questions