如何把空间数据从CGCS2000转换到WGS84和BD09——JAVA语⾔实现
⽬录
1 背景说明
最近的项⽬中涉及到空间数据的转换,主要是把CGCS200坐标转换为WGS84坐标和BD09坐标。我在⽹上了许久,只到了WGS84坐标转BD09坐标的⼯具类,但没有到CGCS200转换到WGS84坐标的⼯具类。我实在没有办法,就只有⾃⼰写。但我没有GIS⾏业的教育背景,不了解坐标转换的专业知识,不过我断定GIS⾏业⼀定有现成的相关⽅法。通过查阅相关资料,最后在ArcGIS提供的 ArcGIS Runtime API for Java中到了相关API。我借此实现了个⼯具类,测试效果也还不错。现在写出这篇⽂章,共享我的代码,希望能帮到有同样问题的开发者。
为了⽅便GIS⾏业外的朋友更流畅地阅读本⽂,先阐释下相关名词概念。
1.1 空间数据
从数据库的⾓度来看,是指在表中以geometry类型存在的数据。
从java语⾔的⾓度来看,是指com.ry包下各种类的对象,包括Point、Multipoint、Polyline、Polygon等等.
1.2 CGCS2000
CGCS2000:China Geodetic Coordinate System 2000,2000国家⼤地坐标系,是我国当前最新的国家⼤地坐标系。该坐标系在ArcGIS中有众多⼦坐标系。如下图所⽰。本⽂选⽤的是CGCS2000_3_Degree_GK_CM_105E。下⽅的坐标系详情中有WKID,您需要记录下这个值,后续会⽤到。
1.3 WGS84
WGS84:World Geodetic System 1984,是为GPS全球定位系统使⽤⽽建⽴的坐标系统,在全球有⼴泛的使⽤。
1.4 BD09
BD09:百度地图坐标系,它是在标准Web墨卡托的基础上进⾏GCJ-02加偏之后,再加上百度⾃⾝的加偏算法。
2 读取数据库中的geometry数据
我采⽤的⽅式是在数据库⽤SQL语句查询出geometry字段的String表达形式,再做后续处理。代码⽚段如下:
@Query( value ="select SHAPE.STAsText() FROM LAND WHERE ID=?", nativeQuery =true)
String getShapeString (String id);
下⾯这个字符串是本⽂通过此⽅法在数据库中查询出来的,此字符串表⽰⼀个地块的坐标,逗号分隔
出每个坐标点,多个坐标点连成⼀个⾯。(此数据是测试数据,由笔者随意编造,没有描述任何真实意义)
POLYGON ((370907.330099999904697 3418398.496099999174576, 370899.395100000314615
3418410.75789999861853, 370909.574500000104318 3418415.690899999812245))
3 代码实现
3.1 CGCS2000转WGS84
上⾯的这个字符串表⽰的是CGCS2000坐标系下的数据。下⾯的代码实现了将多边形地块坐标转换为WGS84,再从WGS84转换为
BD09。
package;
import BD09Point;
西贝尔跑车import PolygonResult;
import*;
import ArrayList;
import List;
/**
* ⽤于坐标转换的⼯具类
*
* @author wang.jingan
* @since 2019-07-20 10:39:16
*/
public class CoordinateSystemTransform {
/**
* 通过String字符串得到三个坐标系的空间数据对象
*
描写声音的成语* @param shape 转化为String的Geometry数据
* @return PolygonResult对象,内含三个坐标系的空间数据对象
*/
public static PolygonResult shapeStringToPolygons(String shape){
//获取两个坐标系
SpatialReference cgcs2000 = ate(4544);
SpatialReference wgs84 = ate(4326);
//创建⼀个CGCS2000的点收集器,为创建Polygon对象做准备
PointCollection land =new PointCollection(cgcs2000);
/
/准备返回的百度坐标点集合
List<BD09Point> pointsBD09 =new ArrayList<>();
//获取需要的字符串
String shapeSubstring = shape.substring(10, shape.length()-2);
//得到每个点的原始数据
String[] points = shapeSubstring.split(",");
//遍历每个点
for(String pointString : points){
//去前后的空格
pointString = im();
//把经纬度分开成两个数据
String[] xy = pointString.split(" ");
Double x = Double.valueOf(xy[0]);
Double y = Double.valueOf(xy[1]);
//把点添加到点收集器
land.add(x, y);
//得到CGCS2000点数据
Point pointCgcs2000 =new Point(x, y, cgcs2000);
银耳凉拌菜的做法//把CGCS2000点数据转化为WGS84点数据
Point pointwgs84 =(Point) GeometryEngine.project(pointCgcs2000, wgs84);
//获取点数据中的经纬度,X为经度,Y为纬度
double pointwgs84X = X();
double pointwgs84Y = Y();
//把wgs84点坐标转化为bdo9点坐标
double[] bd09 = GPSUtil.gps84_To_bd09(pointwgs84Y, pointwgs84X);
BD09Point coordinatesDTO =new BD09Point();
coordinatesDTO.setLat(bd09[0]);
coordinatesDTO.setLon(bd09[1]);
pointsBD09.add(coordinatesDTO);
}
//从点收集器中创建Polygon,得到⼀个cgcs2000的Polygon
Polygon polygonCgcs2000 =new Polygon(land);
//转换为wgs84的Polygon
Polygon polygonWgs84 =(Polygon) GeometryEngine.project(polygonCgcs2000, wgs84);
//装⼊返回数据
PolygonResult result =new PolygonResult();
result.setCgcs2000(polygonCgcs2000);
result.setWgs84(polygonWgs84);
result.setBd09(pointsBD09);
return result;
}
}
3.2 BD09坐标系中点的表⽰
在ArcGIS中wkid⽤于表⽰相关坐标系的代码, 并⽤ate(int wkid) 进⾏创建对
应的坐标系。但BD09坐标系 在ArcGIS中没有相关的wkid,所以BD09坐标是通过点的集合表⽰,⽽WGS84的坐标是通过com.ry 包下的Polygon类的对象表⽰。
BD09坐标系的点是笔者⾃⼰定义的⼀个类。代码如下:
package;
public class BD09Point {
private Double lat;
魔兽地图天龙八部private Double lon;
public Double getLat(){
return lat;
}
public void setLat(Double lat){
this.lat = lat;
}
public Double getLon(){
return lon;
}
public void setLon(Double lon){
this.lon = lon;
}
@Override
public String toString(){
return"BD09Point{"+"lat="+ lat +", lon="+ lon +'}';
}
}
3.3 WGS84转BD09
此⼯具类⽹上有很多,同时涉及到很多测量学和数学知识,我也不太擅长那些⽅⾯,所以就没有⾃⼰写,直接⽤了 这篇⽂章的代码,您也可以⾃⾏在⽹上寻类似⼯具。
3.4测试结果
如下图所⽰,测试结果未发现异常。
4 依赖和环境
这篇⽂章⾸次发表是2019年7⽉,当时我⽤使⽤的ArcGIS Runtime SDK for Java版本为100.4.0。
<dependency>
<groupId>com.esri.arcgisruntime</groupId>
<artifactId>arcgis-java</artifactId>
<version>100.4.0</version>
</dependency>
当时是只需要在l中加⼊上⾯的依赖即可,默认配置的maven仓库或者阿⾥云仓库都可以⾃动下载jar包,也不需要安装任何ArcGIS 环境,就可以使⽤运⾏。
和平精英外挂但⽂章发布后⼤约半年,就陆续有开发者留⾔反馈说,不能正确加载jar包,报错提⽰“程序包com.ry不存在”。开始我以为是他们的Maven配置出了问题,我就⼿动下载100.8.0的jar⽂件,放在了我的CSDN资源中,供需要的朋友下载。之所以下载100.8.0版本,是因为
原来的100.4.0的jar包我也没有刻意保存,也不到了。但解决完jar包加载问题后,⼜有不少开发者反馈出现了如下报错:
Caused by: java.lang.RuntimeException: Could not find runtime in any of:
- A directory specified by calling ArcGISRuntimeEnvironment.setInstallDirectory()
- The current directory F:\Code\Intimate\other\gis-demo
- A location specified by the environment variable ARCGISRUNTIMESDKJAVA_100_10_0
- Within the “.arcgis” directory in the user’s home path C:\Users\admin.arcgis
我在⾃⼰的电脑上在测试,也重现了这个问题。开始我以为是100.8.0作为更⾼的版本,有其新的要求。我就花了不少功夫到arcgis的官⽹中到并下载到了100.4.0的jar包,但是运⾏后也会报⼀样的错。我看这个jar包上传时间是2020年10⽉30⽇,估计是新下载的
100.4.0,相对于2019年的⽂件,也做了些更新吧。
其实上述问题的实质就是ArcGIS Runtime API for Java的运⾏环境没有成功构建。
那么解决办法就只有两个了:
第⼀个⽅法是到⽼版本的100.4.0.jar。我尝试了很久,都没有到相关资源,所以就暂时放弃了,如果有读者到,可以联系我。小百货批发网
第⼆个⽅法是使⽤新版本的jar包,并在此基础上构建ArcGIS Runtime API for Java的运⾏环境。我进⾏了⼀些探索后,成功实现了。
解决办法请参见我新写的另⼀篇博客:(左侧博客标题有超链接,请点击跳转)。
您也可以直接下载⽰例代码:(左侧资源标题含有超链接,请点击跳转 )。
5 提⽰
虽然我是通过公开途径下载的 ArcGIS Runtime API for Java 的相关jar包和资源⽂件,并未曾接收到任何关于收费的提⽰,但我也未查询到 ArcGIS Runtime API for Java 的供应商Esri 有表明这款软件是可以免费使⽤的开源软件。因此如需在实际项⽬开发中使⽤ArcGIS Runtime API for Java,请先向Esri公司咨询授权的相关事宜,避免不必要的纠纷和损失。
我在撰写本⽂时就职的公司是购买了ArcGIS 的软件使⽤权,在使⽤ ArcGIS Runtime API for Java时,也得到了Esri的技术⽀持。
如果您希望使⽤开源软件完成类似功能,建议查询⼀下geotools。
6 结语
本⽂的参考⽂献已经在正⽂中注明了出处。如果转载本⽂,也请注明出处和作者。这篇⽂章是我在CSDN上写的第⼀篇博客,时间仓促,技术有限,也不太了解CSDN上写博客的技巧,难免有些纰漏,欢迎读者指出其中的不⾜,也希望⼤家在博客下的留⾔区积极讨论。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论