Нахождение расстояния между двумя геолокациями при использовании фреймворка MvvmCross

Я использую фреймворк MvvmCross для создания кросс-платформенного (iOS, Android, WP7) приложения. Я использую MvxGeoLocationWatcher, который создает для меня объекты MvxGeoLocation с требуемой долготой, широтой, скоростью, заголовком и т. д.

Мне нужно найти расстояние между двумя точками (по прямой). На Android я звоню fromLocation.distanceTo(toLocation). На iOS я бы использовал CLLocationDistance distance = [fromLocation distanceFromLocation:toLocation];.

Таким образом, обе эти платформы используют метод местоположения для расчета расстояния, и в настоящее время он недоступен для объекта MvxGeoLocation.

Есть ли планы добавить его в ближайшее время? Если нет, что было бы лучшим подходом для добавления этой функциональности?

  1. Я бы изменил сам класс и предоставил реализации для конкретной платформы - возможно, сделав его частичным классом и поместив конкретный код в частичный класс кода для конкретной платформы. Или, возможно, с помощью методов расширения?
  2. Или, возможно, лучше всего использовать метод, который принимает две точки и возвращает расстояние. В каком случае этот метод должен быть в MvxGeoLocationWatcher?
  3. Добавьте алгоритм расчета в себя, возможно, используя что-то из Рассчитать расстояние двух географических точек в км c# и забудьте об использовании специфичных для платформы реализаций

person Jason Steele    schedule 26.04.2012    source источник
comment
Я бы выбрал 1 - с методом расширения - тогда я, возможно, опубликую это как образец Git или просто Gist.   -  person Stuart    schedule 26.04.2012
comment
На самом деле я думаю, что неправильно понял 1... что бы я сделал, так это написал метод расширения, который использует два местоположения. Я бы лично попытался сохранить это вне mvvmcross - например. в дополнительной библиотеке надстроек или даже просто в виде фрагмента кода. Я думаю о том, чтобы сделать mvvmcross как можно более легким, особенно во избежание ненужного раздувания компоновщика от monotouch.   -  person Stuart    schedule 26.04.2012


Ответы (1)


В настоящее время mvvmcross намеренно не включает расчеты широты и долготы.

Мотивом для этого послужило:

  • чтобы уменьшить размер кода - не каждому приложению нужны эти вычисления
  • кроме того, я имею в виду, что некоторые вычисления лучше выполняются с помощью собственных библиотек, а не общего С# - например. некоторые вычисления полигонов выиграют от собственного аппаратного ускорения. Этот тип мышления существует не только для геовычислений, но и для других областей - например. везде, где требуются такие вещи, как манипулирование изображениями, имеет смысл использовать собственное ускорение.

Возможно, в какой-то момент в будущем mvvmcross предоставит «официальный» плагин IoC помощника местоположения (или набор методов расширения)... например. возможно, мы создадим подключаемый модуль IoC вокруг http://xamarin.com/mobileapi ... и я также очень рад, что другие тоже создают и публикуют их.

So....

На очень простом уровне определение расстояния между двумя точками широты/долготы легко сделать на C# — есть куча довольно простых примеров кода, таких как отличные примеры javascript на http://www.movable-type.co.uk/scripts/latlong.html - и там куча библиотек на github и codeplex, например http://sharpmap.codeplex.com/

В RunSat (в т.ч. на айфоне) использую:

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);
        }
    }
}

Обратите внимание, что лицензия на этот фрагмент — это атрибуция CC, потому что она получена из movable type — http://www.movable-type.co.uk/scripts/latlong.html:

Я предлагаю эти формулы и сценарии для бесплатного использования и адаптации как свой вклад в информационную сферу с открытым исходным кодом, от которой я получил так много. Вы можете повторно использовать эти скрипты [в соответствии с простой лицензией с указанием авторства, без каких-либо явных или подразумеваемых гарантий] при условии, что вы сохраните мое уведомление об авторских правах и ссылку на эту страницу.

person Stuart    schedule 26.04.2012
comment
Спасибо за ответ @Stuart. Можете ли вы сказать мне, является ли приведенный вами фрагмент более точным, если рассматривать Землю как эллипсоид, а не рассматривать Землю как сферу? (т.е. учитывается, что Земля выпячивается на экваторе). Большое спасибо. - person Jason Steele; 26.04.2012
comment
смотрит на movable-type.co.uk/scripts/latlong.html как это метод гаверсина/большого круга... он хорошо работает для моих велосипедных прогулок и пробежек, но локально земля довольно плоская ;) - person Stuart; 26.04.2012