使用GPS經(jīng)緯度定位附近地點(diǎn)(某一點(diǎn)范圍內(nèi)查詢)
數(shù)據(jù)庫(kù)中記錄了商家在百度標(biāo)注的經(jīng)緯度(如:116.412007, 39.947545)
最初想法,以圓心點(diǎn)為中心點(diǎn),對(duì)半徑做循環(huán),半徑每增加一個(gè)像素(暫定1米)再對(duì)周長(zhǎng)做循環(huán),到數(shù)據(jù)庫(kù)中查詢對(duì)應(yīng)點(diǎn)的商家(真是一個(gè)長(zhǎng)時(shí)間的循環(huán)工作),上網(wǎng)百度類似的文章有了點(diǎn)眉目
大致想法是已知一個(gè)中心點(diǎn),一個(gè)半徑,求圓包含于圓拋物線里所有的點(diǎn),這樣的話就需要知道所要求的這個(gè)圓的對(duì)角線的頂點(diǎn),問(wèn)題來(lái)了 經(jīng)緯度是一個(gè)點(diǎn),半徑是一個(gè)距離,不能直接加減
/// <summary>
/// 經(jīng)緯度坐標(biāo)
/// </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
{
private const double EARTH_RADIUS = 6378137.0;//地球半徑(米)
/// <summary>
/// 角度數(shù)轉(zhuǎn)換為弧度公式
/// </summary>
/// <param name="d"></param>
/// <returns></returns>
private static double radians(double d)
{
return d * Math.PI / 180.0;
}
/// <summary>
/// 弧度轉(zhuǎn)換為角度數(shù)公式
/// </summary>
/// <param name="d"></param>
/// <returns></returns>
private static double degrees(double d)
{
return d * (180 / Math.PI);
}
/// <summary>
/// 計(jì)算兩個(gè)經(jīng)緯度之間的直接距離
/// </summary>
public static double GetDistance(Degree Degree1, Degree Degree2)
{
double radLat1 = radians(Degree1.X);
double radLat2 = radians(Degree2.X);
double a = radLat1 - radLat2;
double b = radians(Degree1.Y) - radians(Degree2.Y);
double s = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) +
Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2)));
s = s * EARTH_RADIUS;
s = Math.Round(s * 10000) / 10000;
return s;
}
/// <summary>
/// 計(jì)算兩個(gè)經(jīng)緯度之間的直接距離(google 算法)
/// </summary>
public static double GetDistanceGoogle(Degree Degree1, Degree Degree2)
{
double radLat1 = radians(Degree1.X);
double radLng1 = radians(Degree1.Y);
double radLat2 = radians(Degree2.X);
double radLng2 = radians(Degree2.Y);
double s = Math.Acos(Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Cos(radLng1 - radLng2) + Math.Sin(radLat1) * Math.Sin(radLat2));
s = s * EARTH_RADIUS;
s = Math.Round(s * 10000) / 10000;
return s;
}
/// <summary>
/// 以一個(gè)經(jīng)緯度為中心計(jì)算出四個(gè)頂點(diǎn)
/// </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);//一定轉(zhuǎn)換成角度數(shù) 原PHP文章這個(gè)地方說(shuō)的不清楚根本不正確 后來(lái)lz又查了很多資料終于搞定了
double dlat = distance / EARTH_RADIUS;
dlat = degrees(dlat);//一定轉(zhuǎn)換成角度數(shù)
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
};
}
}
測(cè)試方法:
static void Main(string[] args)
{
double a = CoordDispose.GetDistance(new Degree(116.412007, 39.947545), new Degree(116.412924, 39.947918));//116.416984,39.944959
double b = CoordDispose.GetDistanceGoogle(new Degree(116.412007, 39.947545), new Degree(116.412924, 39.947918));
Degree[] dd = CoordDispose.GetDegreeCoordinates(new Degree(116.412007, 39.947545), 102);
Console.WriteLine(a+" "+b);
Console.WriteLine(dd[0].X + "," + dd[0].Y );
Console.WriteLine(dd[3].X + "," + dd[3].Y);
Console.ReadLine();
}
試了很多次 誤差在1米左右
拿到圓的頂點(diǎn)就好辦了
數(shù)據(jù)庫(kù)要是sql 2008的可以直接進(jìn)行空間索引經(jīng)緯度字段,這樣應(yīng)該性能更好(沒(méi)有試過(guò))
lz公司數(shù)據(jù)庫(kù)還老 2005的 這也沒(méi)關(guān)系,關(guān)鍵是經(jīng)緯度拆分計(jì)算,這個(gè)就不用說(shuō)了 網(wǎng)上多的是 最后上個(gè)實(shí)現(xiàn)的sql語(yǔ)句
SELECT id,zuobiao FROM dbo.zuobiao WHERE zuobiao<>'' AND
dbo.Get_StrArrayStrOfIndex(zuobiao,',',1)>116.41021 AND
dbo.Get_StrArrayStrOfIndex(zuobiao,',',1)<116.413804 AND
dbo.Get_StrArrayStrOfIndex(zuobiao,',',2)<39.949369 AND
dbo.Get_StrArrayStrOfIndex(zuobiao,',',2)>39.945721
相關(guān)文章
C#使用OpenCvSharp實(shí)現(xiàn)透視變換功能
這篇文章主要為大家詳細(xì)介紹了C#如何使用OpenCvSharp實(shí)現(xiàn)透視變換的功能,文中的示例代碼簡(jiǎn)潔易懂,具有一定的學(xué)習(xí)價(jià)值,需要的小伙伴可以參考下2023-11-11C#用Topshelf創(chuàng)建Windows服務(wù)的步驟分享
這篇文章主要給大家介紹了關(guān)于C#如何利用Topshelf創(chuàng)建Windows服務(wù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05C# HttpClient 如何使用 Consul 發(fā)現(xiàn)服務(wù)
這篇文章主要介紹了C# HttpClient 如何使用 Consul 發(fā)現(xiàn)服務(wù),幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2021-02-02詳解C#使用AD(Active Directory)驗(yàn)證內(nèi)網(wǎng)用戶名密碼
這篇文章主要介紹了詳解C#使用AD(Active Directory)驗(yàn)證內(nèi)網(wǎng)用戶名密碼的相關(guān)資料,希望通過(guò)本文能幫助到大家,讓大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-10-10C#使用String和StringBuilder運(yùn)行速度測(cè)試及各自常用方法簡(jiǎn)介
今天小編就為大家分享一篇關(guān)于C#使用String和StringBuilder運(yùn)行速度測(cè)試及各自常用方法簡(jiǎn)介,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-10-10