ASP.NET MVC 经纬度的距离计算 GeoCoordinate [C#]

目的

这次专题遇到了两个经纬度之间的距离计算,目前有好几间餐厅位置的资料,及很多活动场地位置资料,都有经纬度的资讯。而目的是要计算出选取某活动场地时,附近5公里内的餐厅有哪几间,并且显示彼此之间的距离是多少做成API。

上网查了一下公式,因为是计算球面两点的最短距离,所以公式相当複杂,不过网路上有满多别人已经写好的演算公式的funcition可以参考,只要将两地点的经纬度参数丢进去就可以了。

不过经过老师指点后,其实asp.net就有个参考可以计算经纬度两点之间的最短距离。程式码可以不用那么长也不会让使用者看到计算的公式。
那就是使用,也就是今天的主角 GeoCoordinate

首先要先加入参考

System.Device

using 参考

using System.Device.Location;

Controller

首先已知前端会post给我一个活动场地的经度(lng)及纬度(lat)给我。
先建立个post的function其名为PlaceNearRestaurant

[HttpPost]  public ActionResult PlaceNearRestaurant(double lat, double lng)    {           }

GeoCoordinate

接下来在function内var一个new GeoCoordinate资料型别。

var coord = new GeoCoordinate(lat, lng);

GeoCoordinate是经纬度的资料型别,要提供纬度及经度,需引用System.Device.Location才可呼叫的出来。

纬度的範围可从-90.0 到90.0,若不在这範围内则会报错。

从资料库先筛选出需要的资料

private Activivtiest db = new Activivtiest();

Activivtiest是ADO.NET的实体资料模型,是与资料库做连接的一个model。

var foods = db.Restaurants.Where(x => !(string.IsNullOrEmpty(x.Latitude)) || !(string.IsNullOrEmpty(x.Longitude))).ToList();

function内从资料库取出全部的餐厅资料(Restaurants资料表),但这边要先使用where过滤掉没有提供经度及纬度的餐厅资料,不然到时候若某餐厅没有提供经纬度,GeoCoordinate计算时会报错。

显示餐厅的栏位资料

var Newfoods = foods.Select(x => new           {               Id = x.Id,               Name = x.Name,               lat = x.Latitude,               lng = x.Longitude,               add = x.Address,               optime = x.Time,               tel = x.TEL                               }              return Content(JsonConvert.SerializeObject(Newfoods), "application/json");                   

再var一个Newfood来对刚刚的foods进行筛选显示,先测试一下是否有取得餐厅的资料,回传的是Json的格式。

确认有取得资料后,就要来计算活动场地与餐厅之间的距离了。

计算场地与餐厅的距离

 Dis = (int)(new GeoCoordinate(double.Parse(x.Latitude),double.Parse(x.Longitude))).GetDistanceTo(coord)

在上面Newfoods的Select内需要再多加一个Dis栏位,用来存放计算后的距离资料,资料型态使用int。

计算距离的方法介绍

是使用 GeoCoordinate().GetDistanceTo()
这个方法是GeoCoordinate内建的计算球面两点的最短距离方法,演算法都已经写在GetDistanceTo()内了,只需要丢入需要的参数即可。回传的距离单位是公尺(M)。

用法:

GeoCoordinate(餐厅的纬度,餐厅的经度).GetDistanceTo(活动场地的经纬度)

记得若从资料库取得座标记得要将资料型态转型为double。

回传后,就可以成功的获得计算餐厅与活动场地的距离了。

筛选出5公里内的餐厅

程式码:

return Content(JsonConvert.SerializeObject(Newfoods.Where(x => x.Dis <= 5000).OrderBy(x => x.Dis)), "application/json");

只要在Newfoods内进行where资料筛选,取得刚刚的Dis栏位,然后只显示小于等于5000公尺的资料就好,并使用递增的方式呈现。
序列化成Json格式,就可以取得5公里内的餐厅资料了。

将单位变成公里的呈现方式

程式码:

DisView = (int)(new GeoCoordinate(double.Parse(x.Latitude),double.Parse(x.Longitude))).GetDistanceTo(coord) >= 1000 ? ((double)(new GeoCoordinate(double.Parse(x.Latitude),double.Parse(x.Longitude))).GetDistanceTo(coord) / 1000.0).ToString("0.0") + "KM": (int)(newDisView GeoCoordinate(double.Parse(x.Latitude),double.Parse(x.Longitude))).GetDistanceTo(coord) + "M"

看起来有点複杂,就是在Newfoods建立一个用来显示距离的栏位[DisView],使用三元运算式,将计算距离的公式套入,若大于等于1000公尺则取计算后的距离/1000(将单位转换成公里),再加上字串KM。
不然的话小于1000就显示计算后的距离就好,单位就不用转换成公里了,并加上字串M。

就可以return资料了,这样就完成了一个可以计算活动场地与餐厅的经纬度距离并筛选出5公里内的餐厅API了。

附上整个程式码:

Controller

using

using twActivitiest.Models;using System.Device.Location;using Newtonsoft.Json;

function

//与资料库的关联private Activivtiest db = new Activivtiest();#region 显示场地5公里内的美食与显示距离        [HttpPost]                public ActionResult PlaceNearRestaurant(double lat, double lng)        {                                    //取得post的经纬度资料并存成座标型态            var coord = new GeoCoordinate(lat, lng);                        //从资料库进行筛选,不要经度或纬度有空白资料的餐厅            var foods = db.Restaurants.Where(x => !(string.IsNullOrEmpty(x.Latitude)) || !(string.IsNullOrEmpty(x.Longitude))).ToList();                                    //筛选要的栏位并计算活动场地与餐厅之间的距离            var Newfoods = foods.Select(x => new            {                Id = x.Id,                Name = x.Name,                lat = x.Latitude,                lng = x.Longitude,                add = x.Address,                optime = x.Time,                tel = x.TEL,                                                //计算活动场地与餐厅的距离方法                                Dis = (int)(new GeoCoordinate(double.Parse(x.Latitude), double.Parse(x.Longitude))).GetDistanceTo(coord),                                                //距离显示方式大于等于1000公尺就将单位转成公里                                DisView = (int)(new GeoCoordinate(double.Parse(x.Latitude), double.Parse(x.Longitude))).GetDistanceTo(coord) >= 1000                 ? ((double)(new GeoCoordinate(double.Parse(x.Latitude), double.Parse(x.Longitude))).GetDistanceTo(coord) / 1000.0).ToString("0.0") + "KM"                 : (int)(new GeoCoordinate(double.Parse(x.Latitude), double.Parse(x.Longitude))).GetDistanceTo(coord) + "M"            }             );                                    //筛选出只要取得5000公尺内的餐厅资料,并将资料型态序列化成Json格式,并回传资料                        return Content(JsonConvert.SerializeObject(Newfoods.Where(x => x.Dis <= 5000).OrderBy(x => x.Dis)), "application/json");        }        #endregion

以上,感谢阅读。


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章