所以,给定
50.0452345
(x) 和 4.3242234
(y),我想知道 x + 500 米,x - 500 米,y - 500 米,y + 500 米。我找到了许多算法,但几乎所有算法似乎都处理点之间的距离。
50.0452345
(x) 和 4.3242234
(y),我想知道 x + 500 米,x - 500 米,y - 500 米,y + 500 米。每经过一度经度所对应的公里数大约为
(pi/180) * r_earth * cos(theta*pi/180)
其中theta
为纬度(以度为单位),r_earth
约为6378公里。
每度纬度对应的公里数在所有位置大致相同,约为:
(pi/180) * r_earth = 111 km / degree
所以你可以这样做:
new_latitude = latitude + (dy / r_earth) * (180 / pi);
new_longitude = longitude + (dx / r_earth) * (180 / pi) / cos(latitude * pi/180);
只要dx
和dy
与地球半径相比较小,并且不靠近极地,就可以。cos(latitude*180/pi)
时使用的是角度制。 - josch接受的答案是完全正确并且可行的。我进行了一些微调并将其转换为以下内容:
double meters = 50;
// number of km per degree = ~111km (111.32 in google maps, but range varies
// between 110.567km at the equator and 111.699km at the poles)
//
// 111.32km = 111320.0m (".0" is used to make sure the result of division is
// double even if the "meters" variable can't be explicitly declared as double)
double coef = meters / 111320.0;
double new_lat = my_lat + coef;
// pi / 180 ~= 0.01745
double new_long = my_long + coef / Math.cos(my_lat * 0.01745);
对于纬度,请执行以下操作:
var earth = 6378.137, //radius of the earth in kilometer
pi = Math.PI,
m = (1 / ((2 * pi / 360) * earth)) / 1000; //1 meter in degree
var new_latitude = latitude + (your_meters * m);
对于经度执行以下操作:
var earth = 6378.137, //radius of the earth in kilometer
pi = Math.PI,
cos = Math.cos,
m = (1 / ((2 * pi / 360) * earth)) / 1000; //1 meter in degree
var new_longitude = longitude + (your_meters * m) / cos(latitude * (pi / 180));
变量your_meters
可以包含正值或负值。
m
以及其中发生的情况,那将会更好。 - Hossein我花了大约两个小时来解决@nibot提供的问题,我只需要一个方法来根据中心点和宽度/高度(或半径)以公里为单位创建边界框:
数学/地理上,我没有完全理解解决方案。通过试错,我调整了解决方案,以获得四个坐标。在当前位置和移动到四个坐标的新位置的距离(以公里为单位):
北:
private static Position ToNorthPosition(Position center, double northDistance)
{
double r_earth = 6378;
var pi = Math.PI;
var new_latitude = center.Lat + (northDistance / r_earth) * (180 / pi);
return new Position(new_latitude, center.Long);
}
东:
private static Position ToEastPosition(Position center, double eastDistance)
{
double r_earth = 6378;
var pi = Math.PI;
var new_longitude = center.Long + (eastDistance / r_earth) * (180 / pi) / Math.Cos(center.Lat * pi / 180);
return new Position(center.Lat, new_longitude);
}
南方:
private static Position ToSouthPosition(Position center, double southDistance)
{
double r_earth = 6378;
var pi = Math.PI;
var new_latitude = center.Lat - (southDistance / r_earth) * (180 / pi);
return new Position(new_latitude, center.Long);
}
西方:
private static Position ToWestPosition(Position center, double westDistance)
{
double r_earth = 6378;
var pi = Math.PI;
var new_longitude = center.Long - (westDistance / r_earth) * (180 / pi) / Math.Cos(center.Lat * pi / 180);
return new Position(center.Lat, new_longitude);
}
出于完整性考虑发布此方法。
直接使用此方法来:
Python方法,可将任意点移动指定米数。
def translate_latlong(lat,long,lat_translation_meters,long_translation_meters):
''' method to move any lat,long point by provided meters in lat and long direction.
params :
lat,long: lattitude and longitude in degrees as decimal values, e.g. 37.43609517497065, -122.17226450150885
lat_translation_meters: movement of point in meters in lattitude direction.
positive value: up move, negative value: down move
long_translation_meters: movement of point in meters in longitude direction.
positive value: left move, negative value: right move
'''
earth_radius = 6378.137
#Calculate top, which is lat_translation_meters above
m_lat = (1 / ((2 * math.pi / 360) * earth_radius)) / 1000;
lat_new = lat + (lat_translation_meters * m_lat)
#Calculate right, which is long_translation_meters right
m_long = (1 / ((2 * math.pi / 360) * earth_radius)) / 1000; # 1 meter in degree
long_new = long + (long_translation_meters * m_long) / math.cos(lat * (math.pi / 180));
return lat_new,long_new
将坐标偏移10米的Python工作代码。
def add_blur(lat, long):
meters = 10
blur_factor = meters * 0.000006279
new_lat = lat + blur_factor
new_long = long + blur_factor / math.cos(lat * 0.018)
return new_lat, new_long
0.00006279
可能会导致巨大的偏移。请将其替换为以下值:```earth_radius_in_km = 6378.137通过应用此更改,我的偏移量从36米缩小到了约10厘米!
- Hosseinpublic double MeterToDegree(double meters, double latitude)
{
return meters / (111.32 * 1000 * Math.Cos(latitude * (Math.PI / 180)));
}
double newMeter = 3000 * 0.1 / 10000;
double lat1 = point_A.latitude - newMeter;
double lat2 = point_A.latitude + newMeter;
double lon1 = point_A.longitude - newMeter;
double lon1 = point_A.longitude + newMeter;
Cursor c = mDb.rawQuery("select * from TABLE1 where lat >= " + lat1 + " and lat <= " + lat2 + " and lon >= " + lon1 + " and lon <= " + lon2 + " order by id", null);
原帖作者说: “我有50.0452345 (x) 和 4.3242234 (y),我想知道 x + 500 米…”
我假设他给出的 x 和 y 值的单位是米(而不是经度、纬度)。如果是这样,那么他陈述了到 0.1 微米的测量值,因此我假设他对翻译输出需要类似的精度。我还假设他所指的“+500米”等意味着朝南北方向和朝东西方向前进。 他提到了参考点:“基于一个坐标的两个新纬度”,但他没有给出经度和纬度,因此为了具体解释该过程,我将给出他请求的围绕[30 度经度,30 度纬度]点的 500 米方框角落的纬度和经度。
GRS80 椭球面上的精确解可使用以下函数集给出 (我为名为“PARI”的免费开源数学程序编写了这些函数,它可以设置任意位数的精度):
\\=======Arc lengths along Latitude and Longitude and the respective scales:
dms(u)=[truncate(u),truncate((u-truncate(u))*60),((u-truncate(u))*60-truncate((u-truncate(u))*60))*60];
SpinEarthRadiansPerSec=7.292115e-5;\
GMearth=3986005e8;\
J2earth=108263e-8;\
re=6378137;\
ecc=solve(ecc=.0001,.9999,eccp=ecc/sqrt(1-ecc^2);qecc=(1+3/eccp^2)*atan(eccp)-3/eccp;ecc^2-(3*J2earth+4/15*SpinEarthRadiansPerSec^2*re^3/GMearth*ecc^3/qecc));\
e2=ecc^2;\
b2=1-e2;\
b=sqrt(b2);\
fl=1-b;\
rfl=1/fl;\
U0=GMearth/ecc/re*atan(eccp)+1/3*SpinEarthRadiansPerSec^2*re^2;\
HeightAboveEllipsoid=0;\
reh=re+HeightAboveEllipsoid;\
longscale(lat)=reh*Pi/648000/sqrt(1+b2*(tan(lat))^2);
latscale(lat)=reh*b*Pi/648000/(1-e2*(sin(lat))^2)^(3/2);
longarc(lat,long1,long2)=longscale(lat)*648000/Pi*(long2-long1);
latarc(lat1,lat2)=(intnum(th=lat1,lat2,sqrt(1-e2*(sin(th))^2))+e2/2*sin(2*lat1)/sqrt(1-e2*(sin(lat1))^2)-e2/2*sin(2*lat2)/sqrt(1-e2*(sin(lat2))^2))*reh;
\\=======
然后我在PARI命令提示符中将参考点[30,30]输入这些函数,并让PARI解决距离该点+/- 500米的点,给出了原始帖子所要求的两个新经度和两个新纬度。以下是输入和输出示例:
? dms(solve(x=29,31,longarc(30*Pi/180,30*Pi/180,x*Pi/180)+500))
cpu time = 1 ms, real time = 1 ms.
%1172 = [29, 59, 41.3444979398934670450280297216509190843055]
? dms(solve(x=29,31,longarc(30*Pi/180,30*Pi/180,x*Pi/180)-500))
cpu time = 1 ms, real time = 1 ms.
%1173 = [30, 0, 18.6555020601065329549719702783490809156945]
? dms(solve(x=29,31,latarc(30*Pi/180,x*Pi/180)+500))
cpu time = 1,357 ms, real time = 1,358 ms.
%1174 = [29, 59, 43.7621925447500548285775757329518579545513]
? dms(solve(x=29,31,latarc(30*Pi/180,x*Pi/180)-500))
cpu time = 1,365 ms, real time = 1,368 ms.
%1175 = [30, 0, 16.2377963202802863245716034907838199823349]
?