我想创建Android应用程序"兴趣点"。我已经阅读了很多不同的教程,我不明白为什么我需要将GPS坐标转换为ECEF然后转换为ENU。你能解释一下吗?
谢谢!
答案 0 :(得分:2)
地理空间坐标系是一个很大的主题,但ECEF和ENU等系统之间的主要选择是关于是否要描述地球表面的大区域或仅仅是一个小区域。
当Android通过geolocation API提供LocationListener时,它通常使用纬度/经度/海拔来实现此目的,这非常适合表示地球表面上的任何点,但它是"极性"或者"大地测量"坐标系不是绘制2D位置的理想选择。标准techniques允许将此坐标系转换为ECEF,这是另一个适用于整个地球的坐标系,但是是笛卡尔式的#34;所以可以使用比原始纬度/经度/高度坐标更简单的数学运算来旋转和缩放。
以地球为中心的地球固定(ECEF)使用一个坐标系,其原点位于地球的中心,因此地面上的任何点都将具有通常在数百万米内的坐标值。这非常适合描述卫星轨道或跨越多个大陆的位置,但对于城镇或城市内的2D景点不太方便。
如果要绘制地球表面一小块区域的二维地图,则东北向上坐标系可能更方便。要使用此功能,您需要一个参考位置(例如特定城市的中心),可以定义本地东/北/向上的方向。然后它们提供一组x / y / z轴,其中x和y轴为x和y轴。 y轴可能会直接转换为2D屏幕坐标。显然,随着感兴趣区域变大(例如超过100km),地球曲率的影响变得更加明显,并且ENU坐标系将不太有用。有关详细信息,请参阅wikipedia。
从ECEF到ENU坐标系的移动可以通过一组简单的矩阵加法来实现。可以从地图中心的ECEF位置计算的乘法,以及东/北/上方向的单位矢量。
答案 1 :(得分:0)
您可以在Java上以这种方式完成
public List<Double> convertGpsToECEF(double lat, double longi, float alt) {
double a=6378.1;
double b=6356.8;
double N;
double e= 1-(Math.pow(b, 2)/Math.pow(a, 2));
N= a/(Math.sqrt(1.0-(e*Math.pow(Math.sin(Math.toRadians(lat)), 2))));
double cosLatRad=Math.cos(Math.toRadians(lat));
double cosLongiRad=Math.cos(Math.toRadians(longi));
double sinLatRad=Math.sin(Math.toRadians(lat));
double sinLongiRad=Math.sin(Math.toRadians(longi));
double x =(N+0.001*alt)*cosLatRad*cosLongiRad;
double y =(N+0.001*alt)*cosLatRad*sinLongiRad;
double z =((Math.pow(b, 2)/Math.pow(a, 2))*N+0.001*alt)*sinLatRad;
List<Double> ecef= new ArrayList<>();
ecef.add(x);
ecef.add(y);
ecef.add(z);
return ecef;
}
public List<Double> convertECEFtoENU(List<Double> ecefUser, List<Double> ecefPOI, double lat, double longi){
double cosLatRad=Math.cos(Math.toRadians(lat));
double cosLongiRad=Math.cos(Math.toRadians(longi));
double sinLatRad=Math.sin(Math.toRadians(lat));
double sinLongiRad=Math.sin(Math.toRadians(longi));
List<Double> vector = new ArrayList<>();
vector.add(ecefUser.get(0)-ecefPOI.get(0));
vector.add(ecefUser.get(1)-ecefPOI.get(1));
vector.add(ecefUser.get(2)-ecefPOI.get(2));
double e= vector.get(0)*(-sinLongiRad)+vector.get(0)*(cosLongiRad);
double n= vector.get(0)*(-sinLatRad)*(cosLongiRad)+vector.get(1)*(-sinLatRad)*(sinLongiRad)+vector.get(2)*cosLatRad;
double u= vector.get(0)*(cosLatRad)*(cosLongiRad)+vector.get(1)*(cosLatRad)*(sinLongiRad)+vector.get(2)*sinLatRad;
List<Double> enu= new ArrayList<>();
enu.add(e);
enu.add(n);
enu.add(u);
return enu;
}