GeoTools 从以米为单位的 CRS 转换为以度数为单位的 CRS (WGS84)

Posted

技术标签:

【中文标题】GeoTools 从以米为单位的 CRS 转换为以度数为单位的 CRS (WGS84)【英文标题】:GeoTools transform from CRS in meters to CRS in degree (WGS84) 【发布时间】:2022-01-10 11:56:19 【问题描述】:

我正在尝试使用 GeoTools 在两个坐标系之间进行转换,一个以米为单位,另一个以度为单位,但无论如何我尝试转换的值都不正确。我尝试使用相同的代码遵循其他示例,但由于某种原因,它无法在这两个坐标系之间进行转换:[EPSG:3044] -> [EPSG:4326] (WGS 84)

我正在为两个 CRS 解析 WKT,然后使用 GeoTools 对其进行转换 - 下面是我当前的代码以及我的结果:

编辑源代码已更新,以反映使用 WKT 和内部 CRS 解码器的输出。

val sourceCRS = CRS.parseWKT(
  """PROJCS["ETRS89 / UTM zone 32N (N-E)",
    |    GEOGCS["ETRS89",
    |        DATUM["European_Terrestrial_Reference_System_1989",
    |            SPHEROID["GRS 1980",6378137,298.257222101,
    |                AUTHORITY["EPSG","7019"]],
    |            TOWGS84[0,0,0,0,0,0,0],
    |            AUTHORITY["EPSG","6258"]],
    |        PRIMEM["Greenwich",0,
    |            AUTHORITY["EPSG","8901"]],
    |        UNIT["degree",0.0174532925199433,
    |            AUTHORITY["EPSG","9122"]],
    |        AUTHORITY["EPSG","4258"]],
    |    PROJECTION["Transverse_Mercator"],
    |    PARAMETER["latitude_of_origin",0],
    |    PARAMETER["central_meridian",9],
    |    PARAMETER["scale_factor",0.9996],
    |    PARAMETER["false_easting",500000],
    |    PARAMETER["false_northing",0],
    |    UNIT["metre",1,
    |        AUTHORITY["EPSG","9001"]],
    |    AUTHORITY["EPSG","3044"]]""".stripMargin)

val targetCRS = CRS.parseWKT(
  """
    |GEOGCS["WGS 84",
    |    DATUM["WGS_1984",
    |        SPHEROID["WGS 84",6378137,298.257223563,
    |            AUTHORITY["EPSG","7030"]],
    |        AUTHORITY["EPSG","6326"]],
    |    PRIMEM["Greenwich",0,
    |        AUTHORITY["EPSG","8901"]],
    |    UNIT["degree",0.0174532925199433,
    |        AUTHORITY["EPSG","9122"]],
    |    AUTHORITY["EPSG","4326"]]
    |""".stripMargin)

val source = CRS.decode("EPSG:3044");
val target = CRS.decode("EPSG:4326");

val originalCoordinate = new Coordinate(5293975.04, 959436.64)
// WKT
val coordinateWKT = new Coordinate()
val wktTransform = CRS.findMathTransform(sourceCRS, targetCRS, true)
JTS.transform(originalCoordinate, coordinateWKT, wktTransform)
// EPSG
val coordinateEPSG = new Coordinate()
val epsgTransform = CRS.findMathTransform(source, target, true);
JTS.transform(originalCoordinate, coordinateEPSG, epsgTransform);
// Output
System.out.println(s"Original: $originalCoordinate")
System.out.println(s"EKT: $coordinateWKT")
System.out.println(s"EPSG: $coordinateEPSG")

而我的输入输出坐标是:

Original: (5293975.04, 959436.64, NaN)
EKT: (48.79550725975144, 6.678848738740256, NaN)
EPSG: (47.63578358581114, 15.117187455070956, NaN)

【问题讨论】:

【参考方案1】:

所以正确的转换坐标是:(56.4336819°, 4.1353377°)

可能您的源坐标不准确,因为它不在使用坐标系的区域内。

来自 epsg.io:

使用区域:6°E 到 12°E 之间的欧洲:奥地利;比利时;丹麦——陆上和海上;德国 - 陆上和海上;挪威,包括 - 陆上和海上;西班牙 - 离岸

您的坐标位于非洲东部,在印度洋中。

如果我使用来自奥地利的坐标,我会得到以下输出(Java 中):

CoordinateReferenceSystem source = CRS.decode("EPSG:25832"); 
CoordinateReferenceSystem target = CRS.decode("EPSG:4326");
Coordinate coordinate = new Coordinate(959436.64, 5293975.04);
// when you are using EPSG:3044, you have to change x and y: 
// Coordinate coordinate = new Coordinate(5293975.04, 959436.64);
MathTransform transform = CRS.findMathTransform(source, target, false);
JTS.transform(coordinate, coordinate, transform);

System.out.println(coordinate);  //(47.63578358581114, 15.117187455070956, NaN)

这与 epsg.io 的结果相同。 请注意,我使用的是 EPSG:25832 而不是 EPSG:3044。

【讨论】:

我可以看到错误与使用 WKT 解析器有关,使用它我得到错误的输出,但如果我使用“EPSG”解码器,它是正确的 - 想知道出了什么问题,但是对于我的使用,我可以改为更改解码器。 听起来不错!但是,如果您使用带有印度洋坐标的“EPSG”解码器,它是否有效?因为我试过了,但它没有用......结果和你发布的一样。

以上是关于GeoTools 从以米为单位的 CRS 转换为以度数为单位的 CRS (WGS84)的主要内容,如果未能解决你的问题,请参考以下文章

在地图上以米为单位绘制圆

传单地图宽度(以米为单位)

如何获得以米为单位的距离

在MYSQL中用2个坐标以米为单位计算地球距离的最佳方法是啥?

Postgis 中 2 点之间的距离,单位为 srid 4326,以米为单位

用给定的坐标和以米为单位的距离计算新坐标