您的位置:首页 > 其它

两点经纬度之间距离计算

2014-12-29 14:40 176 查看
辅助类
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: