【问题标题】:How to use GeoTools MathTransform?如何使用 GeoTools MathTransform?
【发布时间】:2021-03-28 17:40:59
【问题描述】:

我需要使用 GeoTools Java 库将点从 EPSG:4312 转换为 WGS84。 但我不确定我是否正确使用它,我也不确定它是否提供了正确的结果。

请参阅以下代码示例:

    @Test
    public void testSingle4312ToWGS84() throws FactoryException, TransformException {
        double latitude = 29.0;
        double longitude = -99.0;

        CoordinateReferenceSystem sourceCrs = CRS.decode("EPSG:4312");
        CoordinateReferenceSystem targetCrs = CRS.decode("EPSG:4326");
        MathTransform engine = CRS.findMathTransform(sourceCrs, targetCrs, false);

        DirectPosition source = new DirectPosition2D(sourceCrs, longitude, latitude);
        DirectPosition target = new DirectPosition2D(targetCrs);
        engine.transform(source, target);

        System.out.println("x,y=" + target.getCoordinate()[0] + "," + target.getCoordinate()[1]);
    }

运行上述代码时,我得到以下结果:

x,y=-81.00483829765083,-150.99434404015307

这是错误的,因为 -150 不是有效的纬度。

当我创建 source 对象时,我用经度初始化 X,用纬度初始化 Y,遵循 X 是经度,Y 是纬度的基本原理(根据地理社区)。 但是,如果我反转它们:

DirectPosition source = new DirectPosition2D(sourceCrs, latitude, longitude);

我现在得到的结果看起来更真实:

x,y=29.003866857343915,-98.99222530180596

当然,我现在必须将 X 解释为纬度,将 Y 解释为经度。

那么,问题 #1,我们是否应该采用逆理性,将 X 视为纬度,将 Y 视为经度?

接下来,我想验证结果。首先,尝试使用 Oracle SQL SDO 函数转换同一点:

select sdo_cs.transform (
MDSYS.SDO_GEOMETRY(2001, 4312, MDSYS.SDO_POINT_TYPE(-99, 29, NULL), NULL, NULL),
8307
) from dual;

提供以下结果:

MDSYS.SDO_GEOMETRY(2001, 8307, MDSYS.SDO_POINT_TYPE(-98.9924748682774, 29.0036029261273, NULL), NULL, NULL)

转换后的点与 GeoTools 生成的点相似,但相差约 40 米。

接下来,我尝试了website 提供的转换,它提供了与 Oracle 相同的结果。 我还使用了 Luciad AIXM Viewer,这是一个 GML 的图形表示工具,它也会在 Oracle 计算的同一位置显示我的点。

所以,我有 3 个独立的工具提供相同的结果点,该结果点与 GeoTools 计算的结果点相距 40 米。 问题 #2,为什么 Geotools 会失败? Geotools 对于 CRS 转换是否可靠?

【问题讨论】:

    标签: java geometry geotools geography


    【解决方案1】:

    对于轴顺序的第一个问题,您遇到了一个常见的初学者问题,即假设您知道投影的轴顺序是什么,并且在 ESPG:4326 的情况下它是固定的。

    例如下面的代码:

    CoordinateReferenceSystem targetCrs = CRS.decode("EPSG:4326");
    
    System.out.println("EPSG:4326 - " + CRS.getAxisOrder(targetCrs));
    System.out.println("WGS84 - " + CRS.getAxisOrder(DefaultGeographicCRS.WGS84));
    

    给出这个输出:

    EPSG:4326 - NORTH_EAST
    WGS84 - EAST_NORTH
    

    但是如果你添加Hints.putSystemDefault(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE);这一行,输出变成:

    EPSG:4326 - EAST_NORTH
    WGS84 - EAST_NORTH
    

    因此,一般来说,您永远不应该在代码中依赖“已知”的轴顺序,而是使用类似的东西:

    double latitude = 29.0;
    double longitude = -99.0;
    
    CoordinateReferenceSystem sourceCrs = CRS.decode("EPSG:4312");
    CoordinateReferenceSystem targetCrs = CRS.decode("EPSG:4326");
    
    MathTransform engine = CRS.findMathTransform(sourceCrs, targetCrs, false);
    
    DirectPosition2D source;
    if (CRS.getAxisOrder(sourceCrs).equals(org.geotools.referencing.CRS.AxisOrder.EAST_NORTH)) {
      source = new DirectPosition2D(sourceCrs, longitude, latitude);
    } else {
      source = new DirectPosition2D(sourceCrs, latitude, longitude);
    }
    DirectPosition target = new DirectPosition2D(targetCrs);
    engine.transform(source, target);
    
    if (CRS.getAxisOrder(targetCrs).equals(org.geotools.referencing.CRS.AxisOrder.EAST_NORTH)) {
      System.out.println("lon,lat=" + target.getCoordinate()[0] + "," + target.getCoordinate()[1]);
    } else {
      System.out.println("lon,lat=" + target.getCoordinate()[1] + "," + target.getCoordinate()[0]);
    }
    

    至于转换的准确性取决于您导入的引用模块以及 Oracle 使用的 CRS 定义。加载gt-epsg-hsql 模块后,我看到ToWGS84[601.705, 84.263, 485.227, 4.7354, -1.3145, -5.393, -2.3887] 矩阵与EPSG registry 中提供的最准确的变换相同。如果有可用的 NTv2 转换,那么adding that to your project 应该会提高精度。

    【讨论】:

    • 感谢您的教育回答:)。使用 Oracle Database 12c 企业版 12.2.0.1.0 版时
    • 我不确定是否有办法找出 Oracle 使用什么转换 - docs.oracle.com/database/121/SPATL/… 不清楚
    • 当使用 Oracle Database 12.2.0.1.0 并执行:select * from cs_srs where srid=4312 时,我看到 WKTEXT 中没有 TOWGS84 元素,但有一个 WKTEXT3D 具有 TOWGS84[577.326, 90.129, 463.919, 5.137, 1.474、5.297、2.4232],这与 gt-epsg-hsql-12.4(我正在使用的版本)不同。目前我会坚持使用 GeoTools,但很难向客户解释,我的转换比 Oracle 更正确。
    • 您可能可以更新 Oracle 使用的转换,但如果您真的担心 10 米,那么您应该为投影添加 NTv2 转换
    • 有效问题。我的客户正在使用德克萨斯州的坐标测试奥地利到 WGS84 的转换。我知道......但我还必须支持 EPSG:4269 和其他人,我被描述的第一个问题阻止了。然而,使用 Oracle 和 GeoTools 转换这个奥地利点会导致 0.22 米的差异,这属于可接受的公差。所以,我会坚持使用 GeoTools,因为我认为它适用于现实世界的数据。顺便说一句,在 Luciad Viewer 上做了一些逆向工程,我发现这个工具使用与 Oracle 相同的 TOWGS84 阵列,这解释了它们的完美匹配。
    猜你喜欢
    • 1970-01-01
    • 2013-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-24
    • 2021-07-09
    相关资源
    最近更新 更多