标签:
辅助类 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
两点经纬度之间距离计算
标签:
原文地址:http://www.cnblogs.com/tangge/p/4191638.html