免责声明 这是一项家庭任务。请不要认真对待这个问题或思考这个问题超过2秒。这根本不值得。对不起。
我正在尝试计算路线的大致距离。在 getPoints 方法中,我从数据库请求所有路线点并将它们写入数组。这部分工作良好并且符合预期。在这里你可以看到代码片段:
public ArrayList<Double> getPoints() {
ArrayList<Double> location = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("select latitude,longitude from " + Table_Name_Location, null);
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
Double latitude = cursor.getDouble(cursor.getColumnIndex("Lat"));
Double longitude = cursor.getDouble(cursor.getColumnIndex("Longi"));
location.add(latitude);
location.add(longitude);
}
}
cursor.close();
return location;
}
private double distance(double lat1, double lon1, double lat2, double lon2) {
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1))
* Math.sin(deg2rad(lat2))
+ Math.cos(deg2rad(lat1))
* Math.cos(deg2rad(lat2))
* Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
return (dist);
}
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
private double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}
但是,当计算距离本身时,问题就出现了。由于某种原因,半正矢公式计算距离不正确。我发现问题出在距离方法的某个地方,但我自己无法识别。我比较了半正矢公式的实现,但没有发现与原始公式有任何差异。
Android SDK 包含一个 Location 类,用于计算 Haversine 公式。
这是源代码。
该方法的标题为 “distanceBetween”,并使用 private “computeDistanceAndBearing” 方法。
并且,计算值是距离(以米为单位)、初始方位和最终方位。
这是移植版本。
我删除了 BearingDistanceCache 参数,并将其调整为返回 double 数组。
double[] computeDistanceAndBearing(double lat1, double lon1, double lat2, double lon2) {
// Based on http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
// using the "Inverse Formula" (section 4)
// Convert lat/long to radians
lat1 *= Math.PI / 180.0;
lat2 *= Math.PI / 180.0;
lon1 *= Math.PI / 180.0;
lon2 *= Math.PI / 180.0;
double a = 6378137.0; // WGS84 major axis
double b = 6356752.3142; // WGS84 semi-major axis
double f = (a - b) / a;
double aSqMinusBSqOverBSq = (a * a - b * b) / (b * b);
double l = lon2 - lon1;
double aA = 0.0;
double u1 = Math.atan((1.0 - f) * Math.tan(lat1));
double u2 = Math.atan((1.0 - f) * Math.tan(lat2));
double cosU1 = Math.cos(u1);
double cosU2 = Math.cos(u2);
double sinU1 = Math.sin(u1);
double sinU2 = Math.sin(u2);
double cosU1cosU2 = cosU1 * cosU2;
double sinU1sinU2 = sinU1 * sinU2;
double sigma = 0.0;
double deltaSigma = 0.0;
double cosSqAlpha;
double cos2SM;
double cosSigma;
double sinSigma;
double cosLambda = 0.0;
double sinLambda = 0.0;
double lambda = l; // initial guess
for (int iter = 0; iter < 20; iter++) {
double lambdaOrig = lambda;
cosLambda = Math.cos(lambda);
sinLambda = Math.sin(lambda);
double t1 = cosU2 * sinLambda;
double t2 = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda;
double sinSqSigma = t1 * t1 + t2 * t2;
sinSigma = Math.sqrt(sinSqSigma);
cosSigma = sinU1sinU2 + cosU1cosU2 * cosLambda;
sigma = Math.atan2(sinSigma, cosSigma);
double sinAlpha = (sinSigma == 0) ? 0.0 :
cosU1cosU2 * sinLambda / sinSigma;
cosSqAlpha = 1.0 - sinAlpha * sinAlpha;
cos2SM = (cosSqAlpha == 0) ? 0.0 : cosSigma - 2.0 * sinU1sinU2 / cosSqAlpha;
double uSquared = cosSqAlpha * aSqMinusBSqOverBSq;
aA = 1 + (uSquared / 16384.0) * (4096.0 + uSquared * (-768 + uSquared * (320.0
- 175.0 * uSquared)));
double bB = (uSquared / 1024.0) * (256.0 + uSquared * (-128.0 + uSquared * (74.0
- 47.0 * uSquared)));
double cC = (f / 16.0) * cosSqAlpha * (4.0 + f * (4.0 - 3.0 * cosSqAlpha));
double cos2SMSq = cos2SM * cos2SM;
deltaSigma = bB * sinSigma * (cos2SM + (bB / 4.0) * (cosSigma * (-1.0 + 2.0 * cos2SMSq)
- (bB / 6.0) * cos2SM * (-3.0 + 4.0 * sinSigma * sinSigma) * (-3.0
+ 4.0 * cos2SMSq)));
lambda = l + (1.0 - cC) * f * sinAlpha * (sigma + cC * sinSigma * (cos2SM
+ cC * cosSigma * (-1.0 + 2.0 * cos2SM * cos2SM)));
double delta = (lambda - lambdaOrig) / lambda;
if (Math.abs(delta) < 1.0e-12) {
break;
}
}
float mDistance, mInitialBearing, mFinalBearing;
mDistance = (float) (b * aA * (sigma - deltaSigma));
float initialBearing = (float) Math.atan2(cosU2 * sinLambda,
cosU1 * sinU2 - sinU1 * cosU2 * cosLambda);
initialBearing = (float) (initialBearing * (180.0 / Math.PI));
mInitialBearing = initialBearing;
float finalBearing = (float) Math.atan2(cosU1 * sinLambda,
-sinU1 * cosU2 + cosU1 * sinU2 * cosLambda);
finalBearing = (float) (finalBearing * (180.0 / Math.PI));
mFinalBearing = finalBearing;
return new double[] { mDistance, mInitialBearing, mFinalBearing };
}
并且,这是一个示例用法。
根据一些消息来源,从纽约市到洛杉矶的距离约为3,934公里。
double[] nyc = { 40.712778, -74.006111 };
double[] la = { 34.05, -118.25 };
double[] x = computeDistanceAndBearing(nyc[0], nyc[1], la[0], la[1]);
输出
[3945043.75, -86.26732635498047, -114.04286193847656]