由于施肥博士App研发,需要将App上的高德坐标系的点坐标与底图上的北京54平面坐标系的点坐标进行叠加重合。这个问题纠结了一年,最近有新的发现与方法,故在此写一篇技术贴总结记录。
要实现如下功能,通过当前所在定位坐标,获得当前位置的土壤养分数据。
CoordinateConverter converter = new CoordinateConverter();
// CoordType.GPS 待转换坐标类型
converter.from(CoordType.GPS);
// sourceLatLng待转换坐标点 DPoint类型
converter.coord(sourceLatLng);
// 执行转换操作
DPoint desLatLng = converter.convert();
通过查看原始地图数据(1:50000比例尺),发现广东省纵横跨幅很大,存在两个坐标系(其使用高斯-克吕格投影,6度分带划分),分别为Beijing 1954 GK Zone 19N(即108~114°)和Beijing 1954 GK Zone 20N(即114~120°范围)。
高斯-克吕格(Gauss-Kruger)投影简称“高斯投影”,又名”等角横切椭圆柱投影”,地球椭球面和平面间正形投影的一种。德国数学家、物理学家、天文学家高斯(Carl FriedrichGauss,1777一 1855)于十九世纪二十年代拟定,后经德国大地测量学家克吕格(Johannes Kruger,1857~1928)于 1912年对投影公式加以补充,故名。
该投影按照投影带中央子午线投影为直线且长度不变和赤道投影为直线的条件,确定函数的形式,从而得到高斯一克吕格投影公式。投影后,除中央子午线和赤道为直线外, 其他子午线均为对称于中央子午线的曲线。设想用一个椭圆柱横切于椭球面上投影带的中央子午线,按上述投影条件,将中央子午线两侧一定经差范围内的椭球面正形投影于椭圆柱面。将椭圆柱面沿过南北极的母线剪开展平,即为高斯投影平面。取中央子午线与赤道交点的投影为原点,中央子午线的投影为纵坐标x轴,赤道的投影为横坐标y轴,构成高斯克吕格平面直角坐标系。
高斯-克吕格投影在长度和面积上变形很小,中央经线无变形,自中央经线向投影带边缘,变形逐渐增加,变形最大之处在投影带内赤道的两端。由于其投影精度高,变形小,而且计算简便(各投影带坐标一致,只要算出一个带的数据,其他各带都能应用),因此在大比例尺地形图中应用,可以满足军事上各种需要,能在图上进行精确的量测计算。
我国采用6度分带和3度分带:
1∶2.5万及1∶5万的地形图采用6度分带投影,即经差为6度,从零度子午线开始,自西向东每个经差6度为一投影带,全球共分60个带,用1,2,3,4,5,……表示.即东经0~6度为第一带,其中央经线的经度为东经3度,东经6~12度为第二带,其中央经线的经度为9度。
1∶1万的地形图采用3度分带,从东经1.5度的经线开始,每隔3度为一带,用1,2,3,……表示,全球共划分120个投影带,即东经1.5~ 4.5度为第1带,其中央经线的经度为东经3度,东经4.5~7.5度为第2带,其中央经线的经度为东经6度.我省位于东经113度-东经120度之间,跨第38、39、40共计3个带,其中东经115.5度以西为第38带,其中央经线为东经114度;东经115.5~118.5度为39带,其中央经线为东经117度;东经118.5度以东到山海关为40带,其中央经线为东经120度。地形图上公里网横坐标前2位就是带号,例如:1∶5万地形图上的横坐标为20345486,其中20即为带号,345486为横坐标值。2.当地中央经线经度的计算六度带中央经线经度的计算:当地中央经线经度=6°×当地带号-3°,例如:地形图上的横坐标为20345,其所处的六度带的中央经线经度为:6°×20-3°=117°(适用于1∶2.5万和1∶5万地形图)。三度带中央经线经度的计算:中央经线经度=3°×当地带号(适用于1∶1万地形图)。
近文献检索等查找,常用的WGS84转北京54坐标系的方式有七参数转换法、三参数转换法。也有实现该算法的软件,而本系统需要实现自动化处理,即要自己写算法或者调用类库或接口。在这其中最麻烦的是,如何得知这三个参数或者七个参数,需要采集两个不同坐标系下面的对应点坐标集合(一般至少五个),并运用一定的算法,获得这些参数。这些参数算好之后,带入获得转换参数。因此,最麻烦的部分,我一直没法解决。广东省范围涉及面大,验证成本高。在无法确定一个县求得参数是否符合另一个地方。
1、把从GPS中接收到84坐标系下的大地坐标(经纬度高程B、L, H,其中B为纬度,L为经度,H为高程),使用84坐标系的椭球参数转换为84坐标系下的地心直角坐标(空间坐标):
X=(N+H)cosB * CosL
Y=(N+H)cosB* sinL
Z=[N(1-e2)+H]* sinB
其中N为法线长度,计算公式为N=a/sqrt(l—e2*sin2B),a为椭球体长轴半径,e为第一偏心率。
WGS84坐标系地球参数为:
椭圆长半径a: 6378137.00
第一偏心率e2: 0.006 694 379 901 3
2、使用七参数转换为54坐标系下的地心直角坐标:
X = △X + k*x - β*z + γ*y + x Y = △Y + k*y + α*z - γ*x + y Z = △Z + k*z - α*y + β*x + z
其中,
△X △Y △Z——三个坐标方向的平移参数;
α β γ——三个方向的旋转角参数
k——尺度参数
在小范围内可使用七参数的特殊形式即三参数,即k、α、β、γ都等于0,变成:
X = △X + x
Y = △Y + y
Z = △Z + z3、使用54坐标系的椭球参数转换为54坐标系下的大地坐标(B, L, H):
L=arctan(Y/X)但大地纬度B的计算比较复杂,通常采用迭代法:
上式右端有待定量B ,需迭代计算,迭代时可取
用B的初值B1计算N1和sin B1,将上式进行第二次迭代直至最后两次B 值之差小于允许误差为止。
计算出了B值,大地高也可得出:北京54坐标系地球参数为:
椭圆长半径a: 6378245.0
第一偏心率e2: 0.006 693 421 622 965 949
基本原理说完了,开始说正事啦~(>_<)~~~~
后来,经提醒查看了原始数据,采样点数据部分是有经纬度的属性值记录,而其图层投影坐标系正是北京54坐标系。那么条件充足,就差实现了。
使用wandergis大神的coordtransform 坐标转换(Python和js版本),由于后端技术栈是Java,其开源代码,本人将其转换为Java语言作为一个库进行使用。
受到《ArcGIS中将WGS84坐标转换为北京54或者西安80坐标系(供讨论)》的启发,在ArcMap 10.2软件中已提供坐标系转换支持,可在toolbox工具箱中找到投影工具:
Arctoolboxs->Data management tools->Projections and Transformations->Feature->Project
Beijing_1954_To_WGS_1984_1 15918 China - Orduz basin(适用鄂尔多斯盆地)
Beijing_1954_To_WGS_1984_2 15919 China - offshore Yellow Sea (黄海地区)
Beijing_1954_To_WGS_1984_3 15920 China - offshore South China Sea - Pearl River basin (南海及珠江盆地)
Beijing_1954_To_WGS_1984_4 15921 China - south and west Tarim basin (西南塔里木盆地)
Beijing_1954_To_WGS_1984_5 15935 China - south and west Tarim basin 西南塔里木盆地)
Beijing_1954_To_WGS_1984_6 15936 China - Orduz basin (鄂尔多斯盆地)
取采样点数据,经过两者坐标系的集合及转换后对比,与底图数据有大概一定的数据位移。取转换后的坐标值与实际值,以X、Y值差值作为偏移量。
ArcMap有的功能,ArcGIS Server自然也是会有的。基于RESTful原则的ArcGIS接口,实现投影参数的返回。
地址如下:
http://[gisServer-host]/arcgis/rest/services/Utilities/Geometry/GeometryServer/project
要点:可查询ArcGIS REST API 的help文档。
Input Spatial Reference:
4326(WGS84 wkid的编号)
Output Spatial Reference:
21479 //19N坐标系
21480 //20N坐标系
private static JSONObject projectWGSToBj(double x, double y,int outSR) {
//寻找GP地址
String GPPath =
CommonConstants.GISSERVER_PATH + "/arcgis/rest/services/Utilities/Geometry/GeometryServer/project";
GPPath += "?" +
"inSR=4326" +
"&outSR=" +outSR+
"&geometries=%7B%0D%0A++%22geometryType%22+%3A+%22esriGeometryPoint%22%2C%0D%0A++%22geometries%22+%3A%5B%7B%22x%22+%3A+" + x + "%2C+%22y%22+%3A" + y
+ "%7D%5D%0D%0A%7D&transformation=15920&transformForward=false&f=pjson";
JSONObject result = HttpRequestUtil.getUrlConnection(GPPath, "", RequestMethod.GET);
return result;
}
即实现WGS84坐标转北京54的投影。
方法总比困难多,还是要办法解决问题的,还是要根据业务来走,业务带动技术。
最终我要实现的功能流程如下:
参考文献:
1. 国内外各地图API坐标系比较
2. 百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系互转
3. 墨卡托投影、高斯-克吕格投影、UTM投影及我国分带方法
4. ArcGIS中的北京54和西安80投影坐标系详解
5. WGS84 与 北京54 坐标系互转
6. ArcGIS中将WGS84坐标转换为北京54或者西安80坐标系(供讨论)
7. 使用ArcGIS实现WGS84经纬度坐标到北京54高斯投影坐标的转换