【问题标题】:Is there an R function to parse a compound coordinate reference system?是否有 R 函数来解析复合坐标参考系?
【发布时间】:2025-12-21 00:00:11
【问题描述】:

我最近开始使用机载 LiDAR 数据,该数据具有由水平(投影)和垂直分量组成的复合坐标参考系统。下面显示了一个示例,其中包含从 WKT 描述创建复合 CRS 对象的代码。

我正在从 LiDAR 点云中导出各种栅格图层,我只想将复合 CRS 的水平分量分配给这些图层(示例中为 EPSG:7856)。有谁知道现有的包函数可以可靠地提取水平 PROJCRS 组件,即允许各种新旧 CRS 定义?

2021-11-01 更新:调整了 WKT 字符串的原始示例,以提供在 R 中创建复合 CRS 对象的代码。

# Create a compound CRS object of the type used for
# publicly available LiDAR point cloud data in Australia.
# Requires the glue and sf packages.
#
wkt <- glue::glue('COMPOUNDCRS["GDA2020 / MGA zone 56 + AHD height - AUSGeoid2020 (Meters) (with axis order normalized for visualization) (with axis order normalized for visualization)",
    PROJCRS["GDA2020 / MGA zone 56",
        BASEGEOGCRS["GDA2020",
            DATUM["Geocentric Datum of Australia 2020",
                ELLIPSOID["GRS 1980",6378137,298.257222101,
                    LENGTHUNIT["metre",1]]],
            PRIMEM["Greenwich",0,
                ANGLEUNIT["degree",0.0174532925199433]],
            ID["EPSG",7844]],
        CONVERSION["UTM zone 56S",
            METHOD["Transverse Mercator",
                ID["EPSG",9807]],
            PARAMETER["Latitude of natural origin",0,
                ANGLEUNIT["degree",0.0174532925199433],
                ID["EPSG",8801]],
            PARAMETER["Longitude of natural origin",153,
                ANGLEUNIT["degree",0.0174532925199433],
                ID["EPSG",8802]],
            PARAMETER["Scale factor at natural origin",0.9996,
                SCALEUNIT["unity",1],
                ID["EPSG",8805]],
            PARAMETER["False easting",500000,
                LENGTHUNIT["metre",1],
                ID["EPSG",8806]],
            PARAMETER["False northing",10000000,
                LENGTHUNIT["metre",1],
                ID["EPSG",8807]]],
        CS[Cartesian,2],
            AXIS["easting",east,
                ORDER[1],
                LENGTHUNIT["metre",1]],
            AXIS["northing",north,
                ORDER[2],
                LENGTHUNIT["metre",1]],
        ID["EPSG",7856]],
    VERTCRS["AHD height - AUSGeoid2020 (Meters)",
        VDATUM["Australian Height Datum"],
        CS[vertical,1],
            AXIS["gravity-related height",up,
                LENGTHUNIT["metre",1]],
        ID["EPSG",5711]]]')

# Create the compound CRS object
compound_crs <- st_crs(wkt)

【问题讨论】:

  • 嗨@michael。不知道我能不能弄明白。但是为了更容易找到解决方案,是否可以提供一个最小的可重现示例?
  • 嗨@lovalery。我不确定 - 除了问题中发布的 WKT 之外,示例还应包括哪些内容?
  • 嗨@michael。如果我们可以下载您的一个文件(或您的一个文件的摘录)以生成带有 COMPOUNDCRS 部分的 sf 对象,那就太好了。
  • 谢谢@lovalery。我不愿意发布下载链接,因为我认为这与 SO 上的最小可重现示例不一致,但我已经调整了问题中的示例以显示代码以在 R 中创建与一个相同的复合 CRS由我正在使用的 LiDAR 数据使用。
  • 感谢@michael 分享compound CRS 的示例以及您开发的get_horizontal_crs() 函数。要回答您的问题,我完全不确定您要查找的功能是否存在于 R 包中。但是,我想解决方案在PROJ 库中:本机存在两个函数,即extractGeographicCRS()extractVerticalCRS()。说实话,我从来没有直接安装过这个库,更不知道如何从 R 中使用它!很抱歉我不能更好地帮助你。无论如何,我希望有人能告诉我们如何使用 R 中的这两个功能......干杯。

标签: r sf


【解决方案1】:

在 R 空间丛林中进行了大量拖网之后,我还没有找到提取水平 CRS 分量的现有函数。下面的函数是我尝试写的一个。我已经使用新旧 LiDAR 数据对其进行了测试,其中旧数据具有简单(仅水平)CRS,而新数据具有复合 CRS。

我确信一定有一个现有的更好的方法。

2021 年 11 月 1 日更新:调整了函数以接受与 sf::st_crs() 函数兼容的任何空间对象。

# Retrieve the horizontal component of a compound CRS.
# The object x can be an 'sf' package 'crs' object or any
# spatial object from which a CRS can be queried using the
# sf::st_crs function.
#
get_horizontal_crs <- function(x) {
  xcrs <- sf::st_crs(x)
  if (is.na(xcrs)) stop("No CRS defined")

  wkt <- sf::st_as_text(xcrs)
  
  if (!grepl("COMPD_CS", wkt)) {
    # Should just be a horizontal CRS - simply return it
    xcrs
  } else {
    # Extract the horizontal component
    i <- regexpr("PROJCS\\[", wkt)
    wkt <- substring(wkt, i)
    
    # Match square brackets to discard any trailing
    # component (e.g. the vertical CRS)
    wkt_chars <- strsplit(wkt, "")[[1]]
    level <- 1
    k <- match("[", wkt_chars)
    while (level > 0) {
      k <- k + 1
      if (wkt_chars[k] == '[') {
        level <- level + 1
      } else if (wkt_chars[k] == ']') {
        level <- level - 1
      }
    }
    
    wkt <- substring(wkt, 1, k)
    
    sf::st_crs(wkt)
  }
}

【讨论】:

  • 暂时不情愿地接受了我自己的答案 - 但仍然希望有人能提出更好的方法。不支持在 sf 包中实施此工具的请求 (github.com/r-spatial/sf/issues/1831)。