`
jacky-zhang
  • 浏览: 316669 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

基于经纬度计算方向,距离等

阅读更多
The code encapsulating a location on an Ellipsoid,
public class GlobalCoordinates
implements Comparable<GlobalCoordinates>, Serializable
{
private double mLatitude;
private double mLongitude;
public GlobalCoordinates(double latitude, double longitude)
{
mLatitude = latitude;
mLongitude = longitude;
}
public double getLatitude()
{
return mLatitude;
}
public void setLatitude(double latitude)
{
mLatitude = latitude;
}
public double getLongitude()
{
return mLongitude;
}
public void setLongitude(double longitude)
{
mLongitude = longitude;
}
}

Negative latitudes are in the southern hemisphere, and negative longitudes are in the western hemisphere. The Comparable<T> implementation is omitted for clarity.

Now, we start getting to the fun part. The next type encapsulates the “geodetic curve.”
public class GeodeticCurve implements Serializable
{
private final double mEllipsoidalDistance;
private final double mAzimuth;
private final double mReverseAzimuth;
public GeodeticCurve(double ellipsoidalDistance, double azimuth,
double reverseAzimuth)
{
mEllipsoidalDistance = ellipsoidalDistance;
mAzimuth = azimuth;
mReverseAzimuth = reverseAzimuth;
}
public double getEllipsoidalDistance()
{
return mEllipsoidalDistance;
}
public double getAzimuth()
{
return mAzimuth;
}
public double getReverseAzimuth()
{
return mReverseAzimuth;
}
}

A “geodetic curve” is the solution we’re looking for. It describes how to get from one point on an ellipsoid to another. The ellipsoidal distance is the distance, in meters, between the two points along the surface of the ellipsoid. The azimuth is the direction of travel from the starting point to the ending point. The reverse azimuth, of course, is the direction back from the endpoint (which isn’t necessarily a 180 degree turn on an ellipsoid).

The final input to Vincenty’s Formula we need is an ellipsoid. We hold onto four parameters of an ellipsoid: the length of each semi-axis (in meters), the flattening ratio, and the inverse of the flattening ratio. Technically, we only need the length of one semi-axis and any one of the other three parameters. We’ll record all four for convenience.
public class Ellipsoid implements Serializable
{
private final double mSemiMajorAxis;
private final double mSemiMinorAxis;
private final double mFlattening;
private final double mInverseFlattening;
private Ellipsoid(double semiMajor, double semiMinor, double flattening,
double inverseFlattening)
{
mSemiMajorAxis = semiMajor;
mSemiMinorAxis = semiMinor;
mFlattening = flattening;
mInverseFlattening = inverseFlattening;
}
static public final Ellipsoid WGS84 = fromAAndInverseF(6378137.0,
298.257223563);
static public final Ellipsoid GRS80 = fromAAndInverseF(6378137.0,
298.257222101);
static public final Ellipsoid GRS67 = fromAAndInverseF(6378160.0, 298.25);
static public final Ellipsoid ANS = fromAAndInverseF(6378160.0, 298.25);
static public final Ellipsoid Clarke1880 = fromAAndInverseF(6378249.145,
293.465);
static public Ellipsoid fromAAndInverseF(double semiMajor,
double inverseFlattening)
{
double f = 1.0 / inverseFlattening;
double b = (1.0 – f) * semiMajor;
return new Ellipsoid(semiMajor, b, f, inverseFlattening);
}
public double getSemiMajorAxis()
{
return mSemiMajorAxis;
}
public double getSemiMinorAxis()
{
return mSemiMinorAxis;
}
public double getFlattening()
{
return mFlattening;
}
public double getInverseFlattening()
{
return mInverseFlattening;
}
}

Generally, you won’t need to specify ellipsoid parameters. The Ellipsoid type has a number of static instances that define “reference ellipsoids”. Reference ellipsoids represent some organization’s consensus on the “best” ellipsoidal parameters to use to model Earth. Two of the most widely accepted reference ellipsoids are defined above: WGS84 (the 1984 World Geodetic System) and GRS80 (the 1980 Geodetic Reference System).

Finally, we have the class that actually implements Vincenty’s Formula to solve the Geodetic Inverse Problem given a reference ellipsoid and two sets of global coordinates (equation numbers in comments relate directly to Vincenty’s publication):
public class GeodeticCalculator
{
private final double TwoPi = 2.0 * Math.PI;
public GeodeticCurve calculateGeodeticCurve(Ellipsoid ellipsoid,
GlobalCoordinates start, GlobalCoordinates end)
{
// get constants
double a = ellipsoid.getSemiMajorAxis();
double b = ellipsoid.getSemiMinorAxis();
double f = ellipsoid.getFlattening();
// get parameters as radians
double phi1 = Angle.toRadians(start.getLatitude());
double lambda1 = Angle.toRadians(start.getLongitude());
double phi2 = Angle.toRadians(end.getLatitude());
double lambda2 = Angle.toRadians(end.getLongitude());
// calculations
double a2 = a * a;
double b2 = b * b;
double a2b2b2 = (a2 – b2) / b2;
double omega = lambda2 – lambda1;
double tanphi1 = Math.tan(phi1);
double tanU1 = (1.0 – f) * tanphi1;
double U1 = Math.atan(tanU1);
double sinU1 = Math.sin(U1);
double cosU1 = Math.cos(U1);
double tanphi2 = Math.tan(phi2);
double tanU2 = (1.0 – f) * tanphi2;
double U2 = Math.atan(tanU2);
double sinU2 = Math.sin(U2);
double cosU2 = Math.cos(U2);
double sinU1sinU2 = sinU1 * sinU2;
double cosU1sinU2 = cosU1 * sinU2;
double sinU1cosU2 = sinU1 * cosU2;
double cosU1cosU2 = cosU1 * cosU2;
// eq. 13
double lambda = omega;
// intermediates we’ll need to compute ’s’
double A = 0.0;
double B = 0.0;
double sigma = 0.0;
double deltasigma = 0.0;
double lambda0;
boolean converged = false;
for (int i = 0; i < 10; i++)
{
lambda0 = lambda;
double sinlambda = Math.sin(lambda);
double coslambda = Math.cos(lambda);
// eq. 14
double sin2sigma = (cosU2 * sinlambda * cosU2 * sinlambda)
+ (cosU1sinU2 – sinU1cosU2 * coslambda)
* (cosU1sinU2 – sinU1cosU2 * coslambda);
double sinsigma = Math.sqrt(sin2sigma);
// eq. 15
double cossigma = sinU1sinU2 + (cosU1cosU2 * coslambda);
// eq. 16
sigma = Math.atan2(sinsigma, cossigma);
// eq. 17 Careful! sin2sigma might be almost 0!
double sinalpha = (sin2sigma == 0) ? 0.0
: cosU1cosU2 * sinlambda / sinsigma;
double alpha = Math.asin(sinalpha);
double cosalpha = Math.cos(alpha);
double cos2alpha = cosalpha * cosalpha;
// eq. 18 Careful! cos2alpha might be almost 0!
double cos2sigmam = cos2alpha == 0.0 ? 0.0
: cossigma – 2 * sinU1sinU2 / cos2alpha;
double u2 = cos2alpha * a2b2b2;
double cos2sigmam2 = cos2sigmam * cos2sigmam;
// eq. 3
A = 1.0 + u2 / 16384 * (4096 + u2 * (-768 + u2 * (320 – 175 * u2)));
// eq. 4
B = u2 / 1024 * (256 + u2 * (-128 + u2 * (74 – 47 * u2)));
// eq. 6
deltasigma = B * sinsigma * (cos2sigmam + B / 4
* (cossigma * (-1 + 2 * cos2sigmam2) – B / 6 * cos2sigmam
* (-3 + 4 * sin2sigma) * (-3 + 4 * cos2sigmam2)));
// eq. 10
double C = f / 16 * cos2alpha * (4 + f * (4 – 3 * cos2alpha));
// eq. 11 (modified)
lambda = omega + (1 – C) * f * sinalpha
* (sigma + C * sinsigma * (cos2sigmam + C * cossigma * (-1 + 2 *
cos2sigmam2)));
// see how much improvement we got
double change = Math.abs((lambda – lambda0) / lambda);
if ((i > 1) && (change < 0.0000000000001))
{
converged = true;
break;
}
}
// eq. 19
double s = b * A * (sigma – deltasigma);
double alpha1;
double alpha2;
// didn’t converge? must be N/S
if (!converged)
{
if (phi1 > phi2)
{
alpha1 = 180.0;
alpha2 = 0.0;
}
else if (phi1 < phi2)
{
alpha1 = 0.0;
alpha2 = 180.0;
}
else
{
alpha1 = Double.NaN;
alpha2 = Double.NaN;
}
}
// else, it converged, so do the math
else
{
double radians;
// eq. 20
radians = Math.atan2(cosU2 * Math.sin(lambda),
(cosU1sinU2 – sinU1cosU2 * Math.cos(lambda)));
if (radians < 0.0) radians += TwoPi;
alpha1 = Angle.toDegrees(radians);
// eq. 21
radians = Math.atan2(cosU1 * Math.sin(lambda),
(-sinU1cosU2 + cosU1sinU2 * Math.cos(lambda))) + Math.PI;
if (radians < 0.0) radians += TwoPi;
alpha2 = Angle.toDegrees(radians);
}
if (alpha1 >= 360.0) alpha1 -= 360.0;
if (alpha2 >= 360.0) alpha2 -= 360.0;
return new GeodeticCurve(s, alpha1, alpha2);
}
}
There you have it! You have the tools you need to know the answer to the question “How far is it from here to there?”

Here’s an example of using the code to calculate how far it is from the Lincoln Memorial in Washington, D.C. to the Eiffel Tower in Paris:

public class Example
{
static public void main(String[] args)
{
// instantiate the calculator
GeodeticCalculator geoCalc = new GeodeticCalculator();
// select a reference elllipsoid
Ellipsoid reference = Ellipsoid.WGS84;
// set Lincoln Memorial coordinates
GlobalCoordinates lincolnMemorial;
lincolnMemorial = new GlobalCoordinates(38.88922, -77.04978);
// set Eiffel Tower coordinates
GlobalCoordinates eiffelTower;
eiffelTower = new GlobalCoordinates(48.85889, 2.29583);
// calculate the geodetic curve
GeodeticCurve geoCurve = geoCalc.calculateGeodeticCurve(
reference, lincolnMemorial, eiffelTower
);
double ellipseKilometers = geoCurve.getEllipsoidalDistance() / 1000.0;
double ellipseMiles = ellipseKilometers * 0.621371192;
System.out.println(“Lincoln Memorial to Eiffel Tower using WGS84″);
System.out.printf(
” Ellipsoidal Distance: %1.2f kilometers (%1.2f miles)\n”,
ellipseKilometers, ellipseMiles
);
System.out.printf(” Azimuth: %1.2f degrees\n”,
geoCurve.getAzimuth()
);
System.out.printf(” Reverse Azimuth: %1.2f degrees\n”,
geoCurve.getReverseAzimuth()
);
}
}

The library also supports 3-D geodetic calculations (measurements that account for the elevation above or below the reference ellipsoid). For complete source code, documentation, and examples, download the entire Java library.

referencehttp://www.gavaghan.org/blog/2007/11/16/java-gps-receivers-and-geocaching-vincentys-formula/
http://www.gavaghan.org/blog/free-source-code/geodesy-library-vincentys-formula-java/
分享到:
评论

相关推荐

    经纬度计算距离、方位角等java源码

    本篇文章将详细讲解如何利用Java编程语言实现这一功能,主要基于给定的"经纬度计算"标签以及压缩包中的"Caculate.java"源码。 首先,我们了解地球坐标系统。在地理坐标系统中,每个位置由经度和纬度来表示,经度...

    mysql函数-根据经纬度坐标计算距离

    总的来说,通过理解和应用哈弗辛公式,以及创建相应的MySQL函数,我们可以有效地在数据库中处理基于经纬度的地理位置计算。这对于开发基于位置的应用程序,如导航、地图服务或附近搜索等功能非常有用。

    电子-根据两点经纬度计算距离.doc

    根据两点经纬度计算距离是基于地球坐标系的概念。地球坐标系是由经度和纬度组成的。经度是指从本初子午线到某点的水平角距离,纬度是指某点与地球赤道面的夹角。 在地球坐标系中,经度的范围是从 0° 到 180°,...

    通过两点的经纬度信息计算距离及相对方位角(正北角)

    计算两点之间的距离,可以使用球面距离公式,也就是著名的“大圆距离”算法,基于地球是一个近似的球体。在MATLAB中,我们可以利用Haversine公式,它考虑了地球的曲率: \[ a = \sin^2\left(\frac{\Delta \phi}{2}\...

    已知两点经纬度,求距离和方位

    Haversine公式基于球面三角学,用于计算地球上两点之间的大圆距离。公式如下: \[ a = \sin^2\left(\frac{\Delta \phi}{2}\right) + \cos(\phi_1) \cdot \cos(\phi_2) \cdot \sin^2\left(\frac{\Delta \lambda}{2}\...

    经纬度计算距离,经纬度计算距离公式,matlab源码.zip

    本资源“经纬度计算距离,经纬度计算距离公式,matlab源码.zip”提供了一个基于MATLAB的实现,用于解决这个问题。下面将详细介绍经纬度计算距离的基本原理、常用的计算公式以及MATLAB源码的相关知识。 首先,我们了解...

    已知经纬度计算距离的代码

    总的来说,理解和实现这种基于经纬度的距离计算方法是GIS开发、地图应用、导航系统等领域必备的技能。通过这样的计算,我们可以确定两个地点之间的大致距离,这对于规划路线、物流管理、定位服务等多种应用都至关...

    两经纬度之间的距离

    在IT行业中,尤其是在地理信息系统(GIS)或者基于位置服务(LBS)的应用中,计算两个经纬度之间的距离是一项常见的任务。这项技术对于导航系统、地图应用、物流配送、社交网络等多个领域都至关重要。本篇文章将深入...

    经纬度计算问题c++写的

    在IT行业中,经纬度计算是地理信息系统(GIS)和定位服务中的重要组成部分。C++作为一门强大且灵活的编程语言,常被用于处理这类复杂的计算任务。本篇将深入探讨如何利用C++解决经纬度计算问题,以及相关知识点。 ...

    经纬度计算距离 源码

    在IT行业中,经纬度计算距离是一项常见的地理信息系统(GIS)任务,主要应用于地图应用、导航系统、定位服务等。这个源码可能是一个程序或者库,用于在地球上任意两点的经纬度坐标之间计算出它们的球面距离。接下来...

    经纬度计算

    3. 开源库:如Python的geopy库,提供了经纬度计算的功能,包括距离和方向的计算。 总之,经纬度计算在现代科技中扮演着重要角色,从个人导航到全球气候变化研究,无处不在。理解和掌握这些基本概念和计算方法,对于...

    邻站经纬度计算工具v9.91.zip

    【描述】"邻站经纬度计算工具"顾名思义,其主要功能是基于地球坐标系统,通过输入不同站点的经度和纬度,计算出这些站点之间的相对位置关系。它能够帮助用户快速获取相邻站点间的距离、方位角等信息,从而进行路线...

    已知经纬度计算角度

    在IT领域,尤其是在地理信息系统(GIS)或者...通过这种方式,我们可以在C#环境下,利用Visual Studio 2010进行调试,解决已知经纬度计算角度的问题。这不仅有助于开发GIS应用,也能在定位、导航等场景中发挥重要作用。

    基于GPS经纬度的空间相对方位与距离计算方法初探.pdf

    文章给出了一套基于经纬度和高度信息的坐标转换方法,用于飞行试验科目验证。首先,将WGS-84坐标转换为空间直角坐标,然后将空间直角坐标转换为平面直角坐标,最后通过计算得出飞机与地面站连线相对于真北的相对方位...

    经纬度距离计算小工具

    在IT领域,经纬度距离计算是一项基础而重要的工作,尤其在地理信息系统(GIS)、导航、定位服务以及数据处理中有着广泛的应用。这个“经纬度距离计算小工具”显然是为了帮助用户方便地进行地理位置间的距离计算,...

    用经纬度计算距离,并比较

    根据给定文件的信息,本文将围绕“如何使用Java语言基于经纬度数据计算两点之间的距离,并进行比较”的主题展开。此程序主要关注于经纬度数据的处理与地理距离的计算。 ### 一、经纬度与距离计算的基本原理 #### 1...

    知道距离及方位角,计算对方经纬度

    在地理信息系统(GIS)中,计算目标位置的经纬度是一个常见的任务,特别是在导航、军事、海洋探索和航空航天等领域。当你已经知道自己的位置(即我方的经纬度)、与目标的距离以及目标相对于你的方位角时,可以使用...

    gps得到经纬度计算距离和方位角

    在Android开发中,获取GPS经纬度并计算距离和方位角是一项常见的任务,这对于地图应用、导航系统以及其他地理位置相关的服务至关重要。下面将详细讲解如何实现这一功能,并基于Android平台进行讨论。 首先,Android...

Global site tag (gtag.js) - Google Analytics