大地主题算法正算-用于计算从指定的 LatLng 出发,按某个方向行进指定距离所得到的 LatLng(Java实现版)
主要算法修改自网络上一个VB 脚本实现版。已经通过Google 地图 API提供的方法进行了验证。具体计算的经纬度存在一定的误差,可以容忍。
/**
* ** a, b, c, alpha, e, e2, W, V As Doubleprivate double A1,A2;
private final double R = 6371229; //地球的半径
}
/**
* 用于计算从指定的 LatLng 出发,按某个方向行进指定距离所得到的 LatLng。
* @param STARTLAT 起点维度
* @param STARTLONG 起点经度
* @param ANGLE1 起点到终点的方位角
* @param DISTANCE 距离长度
* @return 经纬度
*/
public double[] computeOffset(double STARTLAT, double STARTLONG, double ANGLE1, double DISTANCE ){//正算
double sinu1, cosu1, sinA0, cotq1, sin2q1, cos2q1, cos2A0;
double k2, q0, sin2q1q0, cos2q1q0 ;
double q ;
double theta;
double aa, BB, cc, EE22, AAlpha, BBeta;
double sinu2, lamuda;
double e1;
double W1;
B1 = STARTLAT;
L1 = STARTLONG;
A1 = ANGLE1;
s = DISTANCE;
//
getellipseparameter();
if(B1 == 0){
if(A1 == 90){
A2 = 270;
B2 = 0;
L2 = L1 + s / a * 180 / Math.PI;
}
if(A1 == 270){
A2 = 90;
B2 = 0;
L2 = L1 - s / a * 180 / Math.PI;
}
return null;
}
B1 = rad(B1); //弧度函数
L1 = rad(L1);
A1 = rad(A1);
computerw();
e1 = e;
W1 = w;
sinu1 = Math.sin(B1) * Math.sqrt(1 - e1 * e1)/W1;
cosu1 = Math.cos(B1) / W1;
sinA0 = cosu1 * Math.sin(A1);
cotq1 = cosu1 * Math.cos(A1);
sin2q1 = 2 * cotq1 / (Math.pow(cotq1, 2) + 1);
cos2q1 = (Math.pow(cotq1,2) - 1) / (Math.pow(cotq1, 2) + 1);
cos2A0 = 1 - Math.pow(sinA0 , 2);
e2 = Math.sqrt(Math.pow(a ,2) - Math.pow(b, 2)) / b;
k2 = e2 * e2 * cos2A0;
aa = b * (1 + k2 / 4 - 3 * k2 * k2 / 64 + 5 * k2 * k2 * k2 / 256);
BB = b * (k2 / 8 - k2 * k2 / 32 + 15 * k2 * k2 * k2 / 1024);
cc = b * (k2 * k2 / 128 - 3 * k2 * k2 * k2 / 512);
e2 = e1 * e1;
//计算扁率
AAlpha = (e2 / 2 + e2 * e2 / 8 + e2 * e2 * e2 / 16) - (e2 * e2 / 16 + e2 * e2 * e2 / 16) * cos2A0 + (3 * e2 * e2 * e2 / 128) * cos2A0 * cos2A0;
BBeta = (e2 * e2 / 32 + e2 * e2 * e2 / 32) * cos2A0 - (e2 * e2 * e2 / 64) * cos2A0 * cos2A0;
q0 = (s - (BB + cc * cos2q1) * sin2q1) / aa;
sin2q1q0 = sin2q1 * Math.cos(2 * q0) + cos2q1 * Math.sin(2 * q0);
cos2q1q0 = cos2q1 * Math.cos(2 * q0) - sin2q1 * Math.sin(2 * q0);
q = q0 + (BB + 5 * cc * cos2q1q0) * sin2q1q0 / aa;
//theta = (AAlpha * q + BBeta * (sin2q1q0 - sin2q1)) * sinA0;
theta = (AAlpha * q + BBeta * (sin2q1q0 - sin2q1)) * sinA0;
sinu2 = sinu1 * Math.cos(q) + cosu1 * Math.cos(A1) * Math.sin(q);
B2 = Math.atan(sinu2 / (Math.sqrt(1 - e1 * e1) * Math.sqrt(1 - sinu2 * sinu2))) * 180 / Math.PI;
lamuda = Math.atan(Math.sin(A1) * Math.sin(q) / (cosu1 * Math.cos(q) - sinu1 * Math.sin(q) * Math.cos(A1))) * 180 / Math.PI;
if(Math.sin(A1)>0){
if (Math.sin(A1) * Math.sin(q) / (cosu1 * Math.cos(q) - sinu1 * Math.sin(q) * Math.cos(A1)) > 0) {
lamuda = Math.abs(lamuda);
}else{
lamuda = 180 - Math.abs(lamuda);
}
}else{
if (Math.sin(A1) * Math.sin(q) / (cosu1 * Math.cos(q) - sinu1 * Math.sin(q) * Math.cos(A1)) > 0) {
lamuda = Math.abs(lamuda) - 180;
}else{
lamuda = - Math.abs(lamuda);
}
}
L2 = L1 * 180 / Math.PI + lamuda - theta * 180 / Math.PI;
A2 = Math.atan(cosu1 * Math.sin(A1) / (cosu1 * Math.cos(q) * Math.cos(A1) - sinu1 * Math.sin(q))) * 180 / Math.PI;
if(Math.sin(A1)>0){
if (cosu1 * Math.sin(A1) / (cosu1 * Math.cos(q) * Math.cos(A1) - sinu1 * Math.sin(q)) > 0) {
A2 = 180 + Math.abs(A2);
}else{
A2 = 360 - Math.abs(A2);
}
}else{
if (cosu1 * Math.sin(A1) / (cosu1 * Math.cos(q) * Math.cos(A1) - sinu1 * Math.sin(q)) > 0) {
A2 = Math.abs(A2);
}else{
A2 = 180 - Math.abs(A2);
}
}
System.out.println(B2+","+L2);
return new double[]{B2,L2};
}