【问题标题】:Finding the distance between two Geo locations when using the MvvmCross framework使用 MvvmCross 框架时查找两个 Geo 位置之间的距离
【发布时间】:2012-05-07 02:12:51
【问题描述】:

我正在使用 MvvmCross 框架来构建一个跨平台(iOS、Android、WP7)应用程序。我正在使用 MvxGeoLocationWatcher 为我创建具有所需的经度、纬度、速度、航向等的 MvxGeoLocation 对象。

我需要找到两个位置之间的距离(如乌鸦飞过)。在 Android 上,我打电话给fromLocation.distanceTo(toLocation)。在 iO 上,我会使用 CLLocationDistance distance = [fromLocation distanceFromLocation:toLocation];。

因此,这两个平台都在位置上使用一种方法来计算距离,而这目前在 MvxGeoLocation 对象上不可用。

有计划尽快添加吗?如果不是,我添加此功能的最佳方法是什么?

  1. 我是否会更改类本身并提供特定于平台的实现 - 可能通过使其成为部分类并将特定代码放入特定于平台的代码部分类中。或者也许通过使用扩展方法?
  2. 或者最好的方法是采用两点并返回距离。在什么情况下这个方法应该在 MvxGeoLocationWatcher 上?
  3. 可能使用Calculate distance of two geo points in km c# 中的某些内容在我自己中添加计算算法,然后忘记使用特定于平台的实现

【问题讨论】:

  • 我会选择 1 - 使用扩展方法 - 然后我可能会将其作为 Git 示例或仅作为 Gist 发布
  • 其实我认为我误读了 1... 我要做的是编写一个消耗两个位置的扩展方法。我个人会尝试将其保留在 mvvmcross 之外-例如在可选的附加库中,甚至只是作为代码 sn-p。我正在考虑尝试让 mvvmcross 尽可能轻量级 - 特别是为了避免 monotouch 造成不必要的链接器膨胀。

标签: windows-phone-7 xamarin.ios xamarin.android mvvmcross


【解决方案1】:

目前 mvvmcross 故意不包括 lat/lng 计算。

这样做的动机是:

  • 降低代码大小 - 并非每个应用都需要这些计算
  • 此外,我认为某些计算最好由本机库完成,而不是通用 C# - 例如一些多边形计算将受益于本机硬件加速。这种类型的想法不仅适用于地理计算,还适用于其他领域 - 例如。无论何时需要图像处理之类的东西,使用原生加速都是有意义的。

mvvmcross 可能会在未来的某个时候提供“官方”位置助手 IoC 插件(或一组扩展方法)......例如也许我们围绕http://xamarin.com/mobileapi 构建了一个 IoC 插件......我也很高兴其他人也构建和发布它们。

所以....

在一个非常简单的层面上,在 C# 中计算两个 lat/lng 点之间的距离很容易 - 有大量相当简单的代码示例可用,例如 http://www.movable-type.co.uk/scripts/latlong.html 上的优秀 javascript 示例 - 并且有大量github 和 codeplex 上的库,例如 http://sharpmap.codeplex.com/

在 RunSat(包括 iPhone)中,我使用:

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

请注意,此 sn-p 上的许可证是 CC 署名 - 因为它源自活字 - http://www.movable-type.co.uk/scripts/latlong.html:

我提供这些公式和脚本作为我的免费使用和改编 对我收到的开源信息领域的贡献 非常。欢迎您重复使用这些脚本 [在一个简单的 署名许可,不提供任何明示或暗示的保证] 只是您保留我的版权声明和对此的引用 页面。

【讨论】:

  • 感谢@Stuart 的回答。你能告诉我你给出的sn-p是否更准确的是“将地球视为椭球体”而不是“将地球视为球体”? (即考虑到地球在赤道处隆起)。非常感谢。
  • 在movable-type.co.uk/scripts/latlong.html 上看起来就像是Haversine/大圆方法......它适用于我的自行车骑行和跑步 - 但当地的地球非常平坦;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-16
相关资源
最近更新 更多