【问题标题】:Convert WGS84 to OSGB36将 WGS84 转换为 OSGB36
【发布时间】:2013-01-23 20:23:07
【问题描述】:

是否有任何已知的 java 库可以让我将 WGS 84 线转换为 OSGB36,或者是否有一个好的公式可以使用?我目前正在使用这个,但它不是很准确,所以我想知道是否有更好的我可以使用。

private static double[] Wgs84ToBNG(double inLat, double inLon) {

    double lat = inLat * Math.PI / 180.0;
    double lon = inLon * Math.PI / 180.0;
    double a = 6377563.396; // Airy 1830 major & minor semi-axes
    double b = 6356256.910;
    double F0 = 0.9996012717; // NatGrid scale factor on central meridian
    double lat0 = 49 * Math.PI / 180.0; // NatGrid true origin
    double lon0 = -2 * Math.PI / 180.0;
    double N0 = -100000; // northing & easting of true origin, metres
    double E0 = 400000;
    double e2 = 1 - (b * b) / (a * a); // eccentricity squared
    double n = (a - b) / (a + b), n2 = n * n, n3 = n * n * n;
    double cosLat = Math.cos(lat), sinLat = Math.sin(lat);
    double nu = a * F0 / Math.sqrt(1 - e2 * sinLat * sinLat); // transverse
                                                                // radius of
                                                                // curvature
    double rho = a * F0 * (1 - e2)
            / Math.pow(1 - e2 * sinLat * sinLat, 1.5); // meridional radius
                                                        // of curvature
    double eta2 = nu / rho - 1;
    double Ma = (1 + n + (5 / 4) * n2 + (5 / 4) * n3) * (lat - lat0);
    double Mb = (3 * n + 3 * n * n + (21 / 8) * n3) * Math.sin(lat - lat0)
            * Math.cos(lat + lat0);
    double Mc = ((15 / 8) * n2 + (15 / 8) * n3)
            * Math.sin(2 * (lat - lat0)) * Math.cos(2 * (lat + lat0));
    double Md = (35 / 24) * n3 * Math.sin(3 * (lat - lat0))
            * Math.cos(3 * (lat + lat0));
    double M = b * F0 * (Ma - Mb + Mc - Md); // meridional arc
    double cos3lat = cosLat * cosLat * cosLat;
    double cos5lat = cos3lat * cosLat * cosLat;
    double tan2lat = Math.tan(lat) * Math.tan(lat);
    double tan4lat = tan2lat * tan2lat;
    double I = M + N0;
    double II = (nu / 2) * sinLat * cosLat;
    double III = (nu / 24) * sinLat * cos3lat * (5 - tan2lat + 9 * eta2);
    double IIIA = (nu / 720) * sinLat * cos5lat
            * (61 - 58 * tan2lat + tan4lat);
    double IV = nu * cosLat;
    double V = (nu / 6) * cos3lat * (nu / rho - tan2lat);
    double VI = (nu / 120)
            * cos5lat
            * (5 - 18 * tan2lat + tan4lat + 14 * eta2 - 58 * tan2lat * eta2);
    double dLon = lon - lon0;
    double dLon2 = dLon * dLon;
    double dLon3 = dLon2 * dLon;
    double dLon4 = dLon3 * dLon;
    double dLon5 = dLon4 * dLon;
    double dLon6 = dLon5 * dLon;
    double N = I + II * dLon2 + III * dLon4 + IIIA * dLon6;
    double E = E0 + IV * dLon + V * dLon3 + VI * dLon5;
    double[] returnValue = { E, N };
    return returnValue;
} 

【问题讨论】:

    标签: java android coordinate-transformation wgs84


    【解决方案1】:

    看看这个page

    在“程序/源代码”部分中,您将找到标题为“WGS84 Lat/Long OSGB36 Grid References”的小节。在本小节中,有几个指向提供此功能的实用程序的链接。

    在另一个post 中,您可以找到此类任务的源代码以及解释。

    【讨论】:

    • 如果我在 nearby.org.uk/… 上转换 435559 387705 我得到 53.384999 -1.466852。但是如果我用这个jstott.me.uk/jcoord/#download java 库来做,我会得到 53.38472825292496,-1.465323287762786。哪一个是正确的?
    • 如果是已知位置,您也可以在 Google 地图上进行验证。
    • 嗯,我下载的java包有70米左右。
    【解决方案2】:

    如果您不确定其他库的正确性,我会将结果与 PROJ.4 进行比较。如果您不想使用本机库,还有一个用于 PROJ.4 的纯 Java 端口。

    将 PROJ.4 用于 WGS84 Lat/Long OSGB36 已在此处讨论:
    PROJ.4 library and OSGB36

    使用cs2cs:
    http://trac.osgeo.org/proj/wiki/man_cs2cs
    OSGB36 字符串:
    http://spatialreference.org/ref/epsg/27700/proj4/
    WGS84 字符串:
    http://spatialreference.org/ref/epsg/4326/proj4/

    Java 端口:
    http://sourceforge.net/projects/jmapprojlib/

    【讨论】:

      【解决方案3】:

      我在这方面做了一些工作,并使用了文档A guide to coordinate systems in Great Britain 它告诉你如果你仔细阅读它需要知道的一切。 从公式中使用的变量名称来看,您很可能已经研究过同一个文档。我认为整个文档中与坐标系之间转换有关的最重要的一段是这个(从第 30 页底部开始)

      总结一下:对于一个简单的基准面变化,经纬度坐标从基准面 A 到 基准B,首先转换为笛卡尔坐标(公式见附件B),所有椭球高度为 零并使用基准 A 的椭球参数; 然后应用来自基准 A 的 Helmert 变换 使用等式(3)到基准 B; 终于使用椭球体转换回纬度和经度 基准B的参数(公式见附录C),丢弃基准B椭球高。

      它描述了您必须采取的 3 个步骤。您引用的公式会将纬度/经度转换为东/北在同一基准面。这不是转型

      从您的方法的命名中,您将传入 WGS84 纬度/经度,因此您应该:

      1) 将网格参考系统(以及相关的真实起源等)的所有想法都抛诸脑后,直到您将纬度/经度从一个基准转换为另一个

      2) 使用操作系统指南中的公式 B1 到 B5 将 WGS84 纬度/经度转换为 WGS84 基准的 3D 笛卡尔坐标(即 x、y 和 z)。确保使用 WGS84 基准的参数(长轴/短轴)

      3) 使用提到的 Helmert 变换,将您刚刚计算的笛卡尔坐标转换为相对于 Airy 1830 椭球的笛卡尔坐标。您将在第 6.6 节中找到获取新笛卡尔所需的 7 个参数

      新坐标xGB、yGB、zGB分别为:

      double xGB = tx + (x * (1 + s)) + (-rz * y) + (ry * z);
      double yGB = ty + (rz * x) + (y * (1 + s)) + (-rx * z);
      double zGB = tz + (-ry * x) + (rx * y) + (z * (1 + s));
      

      他们实际上并没有把它拼出来,他们只是假设你记得你的矩阵数学

      4) 现在使用公式 B6 到 B8 将那些新的笛卡尔坐标(相对于 OSGB36 基准面)转换为相对于 OSGB36 基准面的纬度/经度

      从这里您可以继续使用您引用的公式计算网格东距和北距

      【讨论】:

      • 我展示的代码只是复制粘贴,我完全不知道如何转换不同的坐标系。
      • 那么看起来该方法的名称错误。如果您传入相对于 OSGB36 基准的纬度/经度,它将返回东向和北向。由于所有 GPS 纬度/经度都是 w.r.t WGS84,因此它是不准确的。如今,纬度/经度(OSGB36)本身对任何人都没有多大用处,因为它只印在我们地图的最边缘。甚至皇家海军现在也已将其图表切换到 WGS84 系统。 OSGB36 纬度/经度值实际上仅用作计算操作系统参考的必要中间值。
      【解决方案4】:

      我用过jcoord。非常有用且易于实现。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-25
        • 1970-01-01
        • 2017-03-08
        • 1970-01-01
        • 2021-06-04
        • 1970-01-01
        • 1970-01-01
        • 2020-05-29
        相关资源
        最近更新 更多