两点经纬度之间距离计算
辅助类
GaoDeCoord.cs
GaoDeCoord.cs using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Text; namespace RB.Common { #region 高德地图求范围自有数据 /// <summary> /// 经纬度坐标 /// </summary> public class Degree { public Degree(double x, double y) { X = x; Y = y; } private double x; public double X { get { return x; } set { x = value; } } private double y; public double Y { get { return y; } set { y = value; } } } public class CoordDispose { //WGS84坐标系 private const double EARTH_RADIUS = 6378137.0;//地球半径(米) /// <summary> /// 弧度转换为角度数公式 /// </summary> /// <param name="d"></param> /// <returns></returns> private static double degrees(double d) { return d * (180 / Math.PI); } /// <summary> /// 以一个经纬度为中心计算出四个顶点 /// </summary> /// <param name="distance">半径(米)</param> /// <returns></returns> public static Degree[] GetDegreeCoordinates(Degree Degree1, double distance) { double dlng = 2 * Math.Asin(Math.Sin(distance / (2 * EARTH_RADIUS)) / Math.Cos(Degree1.X)); dlng = degrees(dlng);//一定转换成角度数 /*** * |←0.435→| * —— ————————————————— * ↑ | | | * 0.5 | | | * ↓ | | | * —— |———————|———————| * | | | * | | | * | | | * ————————————————— * 0.5*2/0.435*2=1.149 * 如果需要求左右范围内所有数据,所以就需要*1.149 * ***/ distance = distance * 1.149; double dlat = distance / EARTH_RADIUS; dlat = degrees(dlat);//一定转换成角度数 return new Degree[] { new Degree(Math.Round(Degree1.X + dlat,6), Math.Round(Degree1.Y - dlng,6)),//left-top new Degree(Math.Round(Degree1.X - dlat,6), Math.Round(Degree1.Y - dlng,6)),//left-bottom new Degree(Math.Round(Degree1.X + dlat,6), Math.Round(Degree1.Y + dlng,6)),//right-top new Degree(Math.Round(Degree1.X - dlat,6), Math.Round(Degree1.Y + dlng,6)) //right-bottom }; } /// <summary> /// 获取两个经纬度之间的距离 /// </summary> /// <param name="LonA">经度A</param> /// <param name="LatA">纬度A</param> /// <param name="LonB">经度B</param> /// <param name="LatB">经度B</param> /// <returns>距离(米)</returns> public static double getDistance(double LonA, double LatA, double LonB, double LatB) { // 东西经,南北纬处理,只在国内可以不处理(假设都是北半球,南半球只有澳洲具有应用意义) double MLonA = LonA; double MLatA = LatA; double MLonB = LonB; double MLatB = LatB; // 地球半径(千米) //double R = 6371.004; // 地球半径(米) //double R = 6378137.0; double C = Math.Sin(rad(LatA)) * Math.Sin(rad(LatB)) + Math.Cos(rad(LatA)) * Math.Cos(rad(LatB)) * Math.Cos(rad(MLonA - MLonB)); return (EARTH_RADIUS * Math.Acos(C)); } /// <summary> /// 角度数转换为弧度公式 /// </summary> /// <param name="d"></param> /// <returns></returns> private static double rad(double d) { return d * Math.PI / 180.0; } /// <summary> /// 冒泡排序 /// </summary> /// <param name="m"></param> /// <returns></returns> public static double[] sort(double[] m) { //执行多少次 for (double i = 0; i < m.Length; i++) { //每执行1次,将最大的排在最后 //m.Length-1,因为 m[j + 1] <= m[5] for (int j = 0; j < m.Length - 1; j++) { double a = m[j]; double b = m[j + 1]; if (a > b) { m[j + 1] = a; m[j] = b; } } } return m; } } #endregion }
调用方法
Recommend
Recommend #region 04 推荐好友 + Recommend /// <summary> /// 推荐好友 /// </summary> /// <param name="userid">关注者ID</param> /// <param name="longitude">经度</param> /// <param name="latitude">纬度</param> /// <returns></returns> public JsonResponse Recommend(int userid, double longitude, double latitude) { //设置查询距离 int distance = int.Parse(ConfigurationManager.AppSettings["Distance"].ToString()); //获取不了经纬度,默认为(0,0) if (longitude == 0 && latitude == 0) { var z = new SelectSqlSection<DTemporaryRecord>().Join<DUserDetail>((a, b) => a.User_id == b.User_id).Take(10); IList<UserDetail> list = DDataBase.DataBase.ToIList<UserDetail>(z); //返回个人信息 return Response.ReturnFun(list); } //1.设定范围求圆的4个角度 Degree[] dd = CoordDispose.GetDegreeCoordinates(new Degree(longitude, latitude), distance); //2.使用冒泡排序求最大值和最小值 X,Y double[] arrX = { dd[0].X, dd[1].X, dd[2].X, dd[3].X }; double[] arrY = { dd[0].Y, dd[1].Y, dd[2].Y, dd[3].Y }; //从小到大 double[] vvX = CoordDispose.sort(arrX); double[] vvY = CoordDispose.sort(arrY); //3.经度在X最小值和最大值范围内,纬度同上 var xyz = new SelectSqlSection<DTemporaryRecord>().Join<DUserDetail>((a, b) => a.User_id == b.User_id). Where(a => a.PositionX > vvX[0] && a.PositionX < vvX[3] && a.PositionY > vvY[0] && a.PositionY < vvY[3]). Take(10); var xylist = DDataBase.DataBase.ToDataSet(xyz).Tables[0]; //4.在圆的4个角度范围内 更精确查询每个点的距离 for (int i = 0; i < xylist.Rows.Count; i++) { double DIST = CoordDispose.getDistance(longitude, latitude, double.Parse(xylist.Rows[i].ItemArray[2].ToString()), double.Parse(xylist.Rows[i].ItemArray[3].ToString())); //如果得到的距离大于设定的距离,则去掉 if (DIST > distance) { xylist.Rows.Remove(xylist.Rows[i]); i--; //游标也需要跟着-1 } } #region 数据库交互 //判断 (临时表) 关注者ID var xxx = new SelectSqlSection<DTemporaryRecord>().Where(a => a.User_id == userid); IList<TemporaryRecord> realTimelist = DDataBase.DataBase.ToIList<TemporaryRecord>(xxx); TemporaryRecord ret = new TemporaryRecord(); ret.User_id = userid; ret.PositionX = longitude; ret.PositionY = latitude; if (realTimelist == null || realTimelist.Count == 0) { //添加并返回id int id = DDataBase.DataBase.InsertScalar(ret); } else { //修改 ret.Id = realTimelist[0].Id; DDataBase.DataBase.Update(ret); } #endregion //返回查询的结果 return Response.ReturnFun(xylist); } #endregion
作者:【唐】三三
出处:https://www.cnblogs.com/tangge/p/4191638.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具