是否有 R 函数来解析复合坐标参考系?
Is there an R function to parse a compound coordinate reference system?
我最近开始使用机载 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)
在 R 空间丛林中进行了大量拖网之后,我还没有找到提取水平 CRS 分量的现有函数。下面的函数是我尝试写的一个。我用新旧 LiDAR 数据对其进行了测试,其中旧数据具有简单(只是水平)CRS,而新数据具有复合 CRS。
我相信一定有更好的方法。
2021-11-01 更新: 调整函数以接受与 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)
}
}
我最近开始使用机载 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)
在 R 空间丛林中进行了大量拖网之后,我还没有找到提取水平 CRS 分量的现有函数。下面的函数是我尝试写的一个。我用新旧 LiDAR 数据对其进行了测试,其中旧数据具有简单(只是水平)CRS,而新数据具有复合 CRS。
我相信一定有更好的方法。
2021-11-01 更新: 调整函数以接受与 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)
}
}