我正在编写一个程序,它需要一些纬度/长点,并且我将它们内部转换为UTM,以便以米为单位进行一些计算。
纬度/长点本身的范围非常小 - 约200米x 200米。它们几乎总是可以依赖于单个UTM区域(除非你感到不幸并且跨越区域的边界)。
但是,纬度/长度所在的区域不受限制。有一天,这个项目可能会针对澳大利亚的人们运行(哦,甚至一个州有多少个区域可以解决,有多少区域已经引起了我的痛苦......),另一天是墨西哥人。
我的问题是 - 有没有办法确定特定长/纬度所在的区域,以便它可以被送入转换库(我目前使用proj4和R包rgdal
)。
我的语言是R,但答案不一定是 - 也许只是一个简单的计算,或者我可以将系统调用嵌入proj
exectuable。
欢呼声。
答案 0 :(得分:38)
编辑:对于适用于地球上所有非极区的(非R)代码,请参阅here或here。
除非您正在处理来自几个特殊区域(Svalbard and parts of Norway)的数据,否则这是一个简单的计算,您可以自己在R中自己完成。以下是Wikipedia's description如何经度与UTM区号有关:
UTM系统将地球表面在80°S和84°N纬度之间划分为60个区域,每个区域的宽度为6°。 1区覆盖经度180°至174°W;区域编号向东增加到区域60,覆盖经度174到180东。
所以,假设你的数据Prime Meridian以西的经度被编码为从-180到0度的运行,这里是上面的R代码版本:
long2UTM <- function(long) {
(floor((long + 180)/6) %% 60) + 1
}
# Trying it out for San Francisco, clearly in UTM Zone 10
# in the figure in the Wikipedia article linked above
SFlong <- -122.4192
long2UTM(SFlong)
# [1] 10
这个表达式显然可以简化一点,但我认为在这种形式下,其构造的基础逻辑是最清楚的。如果您的某些经度大于180或小于-180,那么%% 60
位就在那里。
答案 1 :(得分:2)
我不知道r代码,但我想这个PL / SQL代码可以帮助你解决异常问题:
UTMZone := Trunc((lon - Zone0WestMeridian) / d);
--Special Cases for Norway & Svalbard
CASE
WHEN (lat > 55) AND (UTMZone = 31) AND (lat < 64) AND (lon > 2) THEN UTMZone := 32;
WHEN (lat > 71) AND (UTMZone = 32) AND (lon < 9) THEN UTMZone := 31;
WHEN (lat > 71) AND (UTMZone = 32) AND (lon > 8) THEN UTMZone := 33;
WHEN (lat > 71) AND (UTMZone = 34) AND (lon < 21) THEN UTMZone := 33;
WHEN (lat > 71) AND (UTMZone = 34) AND (lon > 20) THEN UTMZone := 35;
WHEN (lat > 71) AND (UTMZone = 36) AND (lon < 33) THEN UTMZone := 35;
WHEN (lat > 71) AND (UTMZone = 36) AND (lon > 32) THEN UTMZone := 37;
ELSE UTMZone := UTMZone;
END CASE;
答案 2 :(得分:0)
我使用先前的答案为我完成了此功能。 也许对这里的某人有用=)
utmzone <- function(lon,lat) {
## Special Cases for Norway & Svalbard
if (lat > 55 & lat < 64 & lon > 2 & lon < 6){
band <- 32
} else {
if (lat > 71 & lon >= 6 & lon < 9){
band <- 31
} else {
if (lat > 71 & lon >= 9 & lon < 12){
band <- 33
} else {
if (lat > 71 & lon >= 18 & lon < 21){
band <- 33
} else {
if (lat > 71 & lon >= 21 & lon < 24){
band <- 35
} else {
if (lat > 71 & lon >= 30 & lon < 33){
band <- 35
} else {
## Rest of the world
if (lon >= -180 & lon <= 180){
band <- (floor((lon + 180)/6) %% 60) + 1
} else {
band <- "something is wrong"
}}}}}}}
return(band)
}
utmzone(-43,-22)
#[1] 23
答案 3 :(得分:0)
所以我今天遇到了这个问题,我需要从纬度/经度找到 UTM 区域。这是我的 R 脚本,最后对斯瓦尔巴群岛、挪威和两极等一些边缘情况进行了测试:
require(tidyverse)
require(purrr)
require(testthat)
find_one_utm_zone <- function(longitude, latitude) {
# Special zones for Svalbard
if (latitude >= 72.0 && latitude <= 84.0 ) {
if (longitude >= 0.0 && longitude < 9.0)
return("31X");
if (longitude >= 9.0 && longitude < 21.0)
return("33X")
if (longitude >= 21.0 && longitude < 33.0)
return("35X")
if (longitude >= 33.0 && longitude < 42.0)
return("37X")
}
# Special zones for Norway
if (latitude >= 56.0 && latitude < 64.0 ) {
if (longitude >= 0.0 && longitude < 3.0)
return("31V");
if (longitude >= 3.0 && longitude < 12.0)
return("32V")
}
# North + South Poles
if (latitude > 84.0){
if ((longitude+180)%%360-180 < 0) {return("Y")}
if ((longitude+180)%%360-180 > 0) {return("Z")}
} else if (latitude < -80.0){
if ((longitude+180)%%360-180 < 0) {return("A")}
if ((longitude+180)%%360-180 > 0) {return("B")}
}
# Everything in the middle
if ( (latitude>-80.0) && (latitude<=84.0) ){
mid_zones <- LETTERS[c(3:8,10:14,16:24)] # C to X, skip I and O
utm_letter <- mid_zones[ min(floor( (latitude + 80) / 8 )+1 , 20) ]
utm_number <- (floor( (longitude + 180) / 6 ) %% 60) + 1 # modulo in case longitude is 0 to 360 instead of -180 to 180
utm_zone <- paste0(utm_number, utm_letter)
return(utm_zone)
} else {
stop("lat long not valid (or something else broke)")
}
}
find_utm_zone <- function(lon, lat){
purrr::map2_chr(.x = lon, .y = lat, .f = find_one_utm_zone)
}
使用示例
locs <-
tibble(lon = c(-100,30,150, 4, 7, 22, 0, 12, -34, -20),
lat = c(-45, 85, 12, 57, 81, 83, 5, -81, 85, 83),
desired_utm_zone = c("14G","Z","56P", "32V" ,"31X","35X","31N", "B","Y","27X"))
locs2 <-
locs %>%
mutate(utm_zone = find_utm_zone(lon = lon,lat = lat))
测试它是否有效:
testthat::expect_equal(locs2$utm_zone, locs2$desired_utm_zone)